Question How to call a Rest API in a schedule

raysefo

Well-known member
Joined
Feb 22, 2019
Messages
361
Programming Experience
10+
I have an ASP.NET Core 2.1 web application. The admin gets online game codes from the page below by selecting the related game (Razer Gold Pin), quantity, and email to send those codes.


A Rest API call is being made for the purchase. There is a limit for purchasing, a maximum of 200 purchases can be made at one time.


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 this somehow?

YqL9F.png


Javascript in the cshtml:
JavaScript:
$("#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);
                            }

                        });

controller method:
C#:
[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);
    }
}

Web API calling method:
C#:
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/scheduler. 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 also need if I can stop/cancel the job from this page before its end time. I really appreciate any help you can provide. I have no experience with this scheduling.

Thank you.
 
I think I am gonna try using RabbitMQ. Made some research, asked questions, and tried to decide which solution to choose. There is this web application for the user in order to enter a total number of codes and the game type. There will be IHostedService1 (producer) to get this total number of codes and send it to RabbitMQ in pieces that the 3rd party service can digest. There will be IHostedService2 (consumer) who gets those pieces after some time (not immediately) and call the 3rd party web service with Parallel.ForEachAsync may be reducing the total time elapsed by setting the max number of concurrent tasks we will enable in one call.

What do you say? Any suggestions?
 
If you are going to break up the big order into chunks for RabbitMQ, why not just break it up into chunks for yourself, and then do the same strategy that you would have implemented had you called RabbitMQ?

I can imagine that for RabbitMQ, you would have broken the big order into chunks, and then returned to the caller letting them know that you will notify them when the order is fulfilled. Why can't you just do the same and break up the big order into chunks and queue them up into your database, and then let the caller know that you will notify them when the order is fulfilled?
 
You mean without using RabbitMQ right? I think it can be removed from the solution. How can I implement Parallel.ForEachAsync
for 100 by 100 codes in the IHostedService?
 
Egads; you've spent nearly 2 months designing and researching how to implement Enterprise FizzBuzz.

If you'd slung together and crappy winforms app that has a 1 second timer, that ordered a single code every time it fired, you'd have ordered 3,954,700 codes by now

If you're doing it as an academic exercise, by all means crack on, but if the business is riding on this just get something out the door..
 
Back
Top Bottom