//Our GeneratorManager event.
 protected virtual void OnNumberGenerated(BatchAndNumberInput inputDetails, BatchAndNumber batchAndNumber)
 {
     NumberGenerated?.Invoke(this, new BatchAndNumberEventArgs()
     {
         BatchAndNumber = batchAndNumber, BatchAndNumberInput = inputDetails
     });
 }
        public async Task <IActionResult> PutBatchAndNumberInput(int id, BatchAndNumberInput batchAndNumberInput)
        {
            if (id != batchAndNumberInput.RequestId)
            {
                return(BadRequest());
            }

            _context.Entry(batchAndNumberInput).State = EntityState.Modified;

            try
            {
                await _context.SaveChangesAsync();
            }
            catch (DbUpdateConcurrencyException)
            {
                if (!BatchAndNumberInputExists(id))
                {
                    return(NotFound());
                }
                else
                {
                    throw;
                }
            }

            return(NoContent());
        }
        //Receive a number and multiply it by a random multiple.
        public async Task MultiplierManager(BatchAndNumberInput inputDetails, BatchAndNumber batchAndNumber)
        {
            int multiplier       = RandomWithinRange.RandomNumber(Global.MultiplierLowest, Global.MultiplierHighest);
            int multipliedNumber = multiplier * batchAndNumber.Number;
            int randomDelay      = RandomWithinRange.RandomNumber(Global.DelayLowest, Global.DelayHighest, Global.DelayMultiplier);

            batchAndNumber.Number = multipliedNumber;
            await Task.Delay(5000);

            OnNumberMultiplied(inputDetails, batchAndNumber);
        }
        //Generate a random number and fire an event with its results.
        public async Task GeneratorManager(BatchAndNumberInput inputDetails, int batch)
        {
            BatchAndNumber batchAndNumber = new BatchAndNumber();

            int randomNumber = RandomWithinRange.RandomNumber(Global.RandomIntegerLowest, Global.RandomIntegerHighest);
            int randomDelay  = RandomWithinRange.RandomNumber(Global.DelayLowest, Global.DelayHighest, Global.DelayMultiplier);

            batchAndNumber.Batch  = batch;
            batchAndNumber.Number = randomNumber;

            await Task.Delay(5000);

            OnNumberGenerated(inputDetails, batchAndNumber);
        }
        public async Task PerformBatchOperations(BatchAndNumberInput receivedBatchAndNumber)
        {
            NumberGenerated  += OnNumberFinishedGeneratingAsync;
            NumberMultiplied += OnNumberFinishedMultiplyingAsync;

            List <Task> listOfTasks = new List <Task>();

            //This is the second splitting point for our logic. While this means more db calls later when trying to keep track of our aggregate, it ultimately reduces our time,
            //Since unique numbers are now also generated asyncronously, as opposed to just batches themselves.
            for (int i = 1; i <= int.Parse(receivedBatchAndNumber.Numbers); i++)
            {
                listOfTasks.Add(PerformanceLogic(receivedBatchAndNumber, i));
            }

            await Task.WhenAll(listOfTasks);
        }
 //If we want to change the logic followed by the processor, this is our entrypoint to do so.
 private async Task PerformanceLogic(BatchAndNumberInput inputDetails, int batch)
 {
     await GeneratorManager(inputDetails, batch);
 }
        public async Task <ActionResult <BatchAndNumberInput> > PostBatchAndNumberInput(BatchAndNumberInput batchAndNumberInput)
        {
            int         totalBatches = Int32.Parse(batchAndNumberInput.Batches);
            List <Task> listOfTasks  = new List <Task>();

            _context.BatchAndNumberInput.Add(batchAndNumberInput);
            await _context.SaveChangesAsync();

            //This is our entrypoint. From here, I split into async streams by creating instances of the processor per-batch.
            for (int z = 1; z <= totalBatches; z++)
            {
                BatchesAndNumbersProcessor processor = new BatchesAndNumbersProcessor();
                listOfTasks.Add(processor.PerformBatchOperations(batchAndNumberInput));
            }

            await Task.WhenAll(listOfTasks);

            //_context.BatchAndNumberInput.Add(batchAndNumberInput);
            await _context.SaveChangesAsync();

            return(CreatedAtAction("GetBatchAndNumberInput", new { id = batchAndNumberInput.RequestId }, batchAndNumberInput));
        }