Is there a way to implement a solution to my problem without using Quartz?
ASP.NET Core 2.1 Calling Rest API in Quartz.net
Hi there,
I have an ASP.NET Core 2.1 web application. The admin gets online game codes from the page below. Selecting the game (Razer Gold Pin), quantity, and email to send those codes.
A Rest API call is made for the purchase. There is a limit for purchasing, a maximum of 200 purchases can be made at once.
At first, there wasn't much to buy so there was no problem. But the demand has increased, when there are 10 thousand, 20 thousand purchases, it is necessary to purchase from this screen for hours. I wonder if can we make a large number of purchases without waiting in front of the screen with scheduling?
Here is the Javascript in the cshtml:
$("#btn_add").html(
'<span class="spinner-border spinner-border-sm" role="status" id="spinner" aria-hidden="true"></span> Loading...'
);
var selText = $("#validationCustom04").val();
var gameName = $("#validationCustom04 option:selected").text();
var quantity = $("#quantity").val();
var email = $("#email").val();
var price = $("#total").val();
var company = $("#validationCustom05").val();
if ($("#total").val() !== '') {
price = $("#total").val();
}
var serviceUrl = '/GameBanks/A101PinAsync?quantity=' + quantity + '&game=' + selText + '&email=' + email + '&prc=' + price + '&gameName=' + gameName + '&company=' + company;
$.ajax({
type: "GET",
url: serviceUrl,
dataType: 'json',
success: function (data) {
//alert(JSON.stringify(data));
ShowResult(data);
$("#spinner").remove();
$("#btn_add").html('Add');
}, error: function (xhr, status, error) {
$("#spinner").remove();
$("#btn_add").html('Add');
var errorMessage = xhr.responseText;
alert('Error - ' + errorMessage);
}
});
Here is the controller method:
[HttpGet]
public async Task<IActionResult> A101PinAsync(int quantity, string game, string email, int prc, string gameName, string company)
{
var price = 0;
try
{
string result = null;
var dList = new DemoList();
if (prc > 0)
{
price = prc;
}
var games = new Game { Product = game, Quantity = quantity };
var content = await games.CallGameAsync("Test", "12345", game, quantity, company);
var deserializedResult = JObject.Parse(content);
var root = JsonConvert.DeserializeObject<Root>(content);
if ((string)deserializedResult["coupons"]?[0]?["Serial"] == null)
{
result = result + gameName + ":" + (string)deserializedResult["Message"] + "\n";
}
else
{
foreach (var coupon in root.coupons)
{
result = result + gameName + " Serial:" + coupon.Serial + " Pin:" + coupon.Pin + "\n";
}
}
dList.gameList = result;
// NLOG
NLogPin(logger, User.Identity.Name, DateTime.Now, result, email);
return new JsonResult(dList);
}
catch (Exception e)
{
// NLOG
NLog(logger2, "OyunPalas " + e.Message, DateTime.UtcNow,0);
return StatusCode(500,e.Message);
}
}
Here is the Web API calling method:
public class Game
{
public string Username { get; set; }
public string Password { get; set; }
public string Product { get; set; }
public int Quantity { get; set; }
public string ShopNo { get; set; }
private static readonly Logger logger2 = LogManager.GetLogger("exceptionFile");
public async Task<string> CallGameAsync(string username, string password, string product, int quantity, string company)
{
try
{
HttpWebRequest request = null;
request = (HttpWebRequest)WebRequest.Create("http://111.111.111.111:1907//api/v2/web/purchase");
var svcCredentials = Convert.ToBase64String(Encoding.ASCII.GetBytes(username + ":" + password));
request.Headers.Add("Authorization", "Basic " + svcCredentials);
request.Method = "POST";
request.KeepAlive = false;
request.ContentType = "application/x-www-form-urlencoded";
var content = new FormUrlEncodedContent(new[]
{
new KeyValuePair<string, string>("productCode", product),
new KeyValuePair<string, string>("quantity", quantity.ToString()),
new KeyValuePair<string, string>("shopNo", company),
new KeyValuePair<string, string>("safeNo", company),
new KeyValuePair<string, string>("cashierNo", company)
});
var urlEncodedString = await content.ReadAsStringAsync();
using (var streamWriter = new StreamWriter(await request.GetRequestStreamAsync()))
{
await streamWriter.WriteAsync(urlEncodedString);
}
var httpResponse = (HttpWebResponse) (await request.GetResponseAsync());
var response = new HttpResponseMessage
{
StatusCode = httpResponse.StatusCode,
Content = new StreamContent(httpResponse.GetResponseStream()),
};
//Read response
var htmlResponse = await response.Content.ReadAsStringAsync();
return htmlResponse;
}
catch (Exception e)
{
//NLOG
NLog(logger2, "Test" + e.Message);
throw;
}
}
public void NLog(Logger logger, string user)
{
var sb = new StringBuilder();
sb.AppendLine("Test: " + user);
logger.Info(sb.ToString());
}
}
I have to pass the product (game type) to the job. I read the https://www.quartz-scheduler.net/documentation/quartz-3.x/tutorial/more-about-jobs.html#jobdatamap documentation but did not fully understand how to use it in my case. And I wonder if I can stop/cancel the job from this page before its end time?
I really appreciate any help you can provide. I'm sorry if the question is too silly as I have no experience with this quartz.net. @XuDong Peng-MSFT
3 answers
Sort by: Most helpful
-
-
Cenk 1,021 Reputation points
2022-12-06T13:47:34.117+00:00 I thought of a solution like this, but I'm not sure if it's viable.
- The user will enter which game, how many they want to buy, and their e-mail address on the screen.
- This data will be saved in a table (BulkRequest) containing this information and the status field in the SQL database. (game: ABC, quantity:20000, status:0)
- One IHostedService will get the saved data in a schedule which status=0 from the BulkRequest table and the save requests with status information in a new table (GameRequests) in multiples of 100. (game: ABC, quantity:100, status:0)
- Another IHostedService will get the records in 10 minutes schedule which status=0 from the GameRequests table and make the 3rd party API call. Write a response to another table (GameResponses) and set the status=1 if there is no error.
- When all requests are completed (status = 1), the status in the BulkRequest table will also be updated to 1.
- A third IHostedService will check the status of BulkRequest, if status=1 then maybe a fourth service will prepare a file and send the responses to the e-mail.
-
Bruce (SqlWork.com) 68,236 Reputation points
2022-12-06T17:25:04.357+00:00 I would handle each purchase request as standalone.
loop get next request while more items to purchase purchase from api update database row with successful count (allows restart) end email purchase receipt end
you don't say the rules of the api, but you could run multiple purchase threads, so more than 1 purchase is done at a time. also while bulk purchasing a single item, you could use multiple concurrent requests.