public AcceptedResult LinkFor( [FromHeader(Name = CORRELATION_ID)] string correlationId, [FromBody] LinkReferenceRequest request) { backgroundJob.Enqueue(() => LinkPatient(request, correlationId)); return(Accepted()); }
public ActionResult <IEnumerable <string> > Get(int a, int b) { _jobClient.Enqueue(() => new CalculatorService().AddDoNotIgnoreParams(new CalculatorService.AddRequest { a = a, b = b })); return(new string[] { a.ToString(), b.ToString() }); }
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline. public void Configure(IApplicationBuilder app, IWebHostEnvironment env, IBackgroundJobClient backgroundJobs) { if (env.IsDevelopment()) { app.UseDeveloperExceptionPage(); } app.UseHangfireDashboard(options: new DashboardOptions() { DashboardTitle = "hangfireTest" }); backgroundJobs.Enqueue(() => Console.WriteLine("Hello world from Hangfire!")); backgroundJobs.Schedule(() => ss(), TimeSpan.FromSeconds(5)); RecurringJob.AddOrUpdate("客户端", () => Console.WriteLine("定时执行5" + DateTime.Now), "*/5 * * * * *"); app.UseRouting(); app.UseEndpoints(endpoints => { endpoints.Map("/", async context => { backgroundJobs.Enqueue(() => Console.WriteLine("新型智能")); await context.Response.WriteAsync("Hello World!"); }); }); }
public async Task <IActionResult> ReProcessCrashDump([Required] long id) { var report = await WithoutLogs(database.CrashReports, true).Where(r => r.Id == id) .FirstOrDefaultAsync(); if (report == null) { return(NotFound()); } if (report.DumpLocalFileName == null) { return(BadRequest("Report no longer has a crash dump file")); } await database.ActionLogEntries.AddAsync(new ActionLogEntry() { Message = $"Report {report.Id} crash dump reprocessing requested", PerformedById = HttpContext.AuthenticatedUserOrThrow().Id, }); await database.SaveChangesAsync(); jobClient.Enqueue <StartStackwalkOnReportJob>(x => x.Execute(report.Id, CancellationToken.None)); return(Ok()); }
/// <summary> /// Handles the specified request. /// </summary> /// <param name="request">The request.</param> /// <param name="cancellationToken">The cancellation token.</param> /// <returns>Task<System.String[]>.</returns> public Task <string[]> Handle(CreateResourcesForBenchmarkCommand request, CancellationToken cancellationToken) { var awsJobId = _backgroungJobClient.Enqueue <IAWSHostService>(c => c.CreateVMForBenchmark(request.Id)); var azureJobId = _backgroungJobClient.Enqueue <IAzureResourceService>(c => c.CreateVMForBenchmark(request.Id)); return(Task.FromResult(new string[] { awsJobId, azureJobId })); }
public AcceptedResult authConfirm( [FromHeader(Name = CORRELATION_ID)] string correlationId, [FromBody] JObject request) { backgroundJob.Enqueue(() => AuthFor(request, correlationId)); return(Accepted()); }
public async Task <IActionResult> RefreshFileTree([Required] long id) { var item = await FindAndCheckAccess(id); if (item == null || item.Deleted) { return(NotFound()); } if (item.FileTreeUpdated != null && DateTime.UtcNow - item.FileTreeUpdated.Value < TimeSpan.FromMinutes(3)) { return(BadRequest("This file tree was refreshed very recently")); } var user = HttpContext.AuthenticatedUserOrThrow(); await database.ActionLogEntries.AddAsync(new ActionLogEntry() { Message = $"LFS project file tree refresh requested for {item.Id}", PerformedById = user.Id, }); await database.SaveChangesAsync(); jobClient.Enqueue <RefreshLFSProjectFilesJob>(x => x.Execute(item.Id, CancellationToken.None)); logger.LogInformation("LFS project {Id} file tree refreshed by {Email}", item.Id, user.Email); return(Ok()); }
private async Task <Guid> UpgradeMatrixForAdmin() { var upgradedPosition = await _matrixPositionHelper.FindEmptyPositionForHighestAdminAsync(_command.MatrixLevel); if (upgradedPosition is null) { throw new ValidationException($"FATAL! There is no empty space for Admin to upgrade matrix at level: {_command.MatrixLevel}"); } upgradedPosition.AssignMultiAccount(_multiAccount.Id); await _matrixPositionRepository.UpdateAsync(upgradedPosition); _backgroundJobClient.Enqueue <MatrixPositionHasBeenUpgradedJob>( job => job.Execute(upgradedPosition.Id, null)); _backgroundJobClient.Enqueue <InitWithdrawalJob>( job => job.Execute(new InitWithdrawalModel { MatrixPositionId = upgradedPosition.Id, WithdrawalFor = WithdrawalForHelper.UpgradedMatrix }, null)); return(upgradedPosition.Id); }
public async Task Process(NewItemRequest newItem) { try { var documentResult = new DocumentResultResponse(); var filePath = _fileManager.Download(newItem.DocumentUrl); var numberOfPages = _fileManager.GetNumberOfPages(filePath); for (var page = 1; page <= numberOfPages; page++) { var pagePath = _fileManager.GeneratePage(filePath, page); var text = _pdfToText.Get(pagePath); if (text == null) { var imagePath = _fileManager.GeneratePageInImage(filePath, page); text = await _cognitive.Get(imagePath).ConfigureAwait(false); _fileManager.Delete(imagePath); } documentResult.AddProcessedPage(text, page); _fileManager.Delete(pagePath); } _fileManager.Delete(filePath); documentResult.Success = true; _backgroundJobs.Enqueue(() => _callback.Send(documentResult, newItem)); } catch (Exception ex) { var documentResult = new DocumentResultResponse { Success = false, ErrorMessage = ex.Message }; _backgroundJobs.Enqueue(() => _callback.Send(documentResult, newItem)); } }
/// <summary> /// Starts a new job and waits for its result /// </summary> /// <typeparam name="TResult"></typeparam> /// <typeparam name="TJob"></typeparam> /// <param name="methodCall"></param> /// <param name="cancellationToken"></param> /// <returns></returns> public async Task <TResult> StartWaitAsync <TResult, TJob>([InstantHandle, NotNull] Expression <Func <TJob, Task> > methodCall, CancellationToken cancellationToken = default) { //todo find a way to mark this job as a Continuation when using backgroundJobClient.Enqueue var jobId = backgroundJobClient.Enqueue(methodCall); while (true) { cancellationToken.ThrowIfCancellationRequested(); var jobDetails = monitoringApi.JobDetails(jobId); string currentState = jobDetails.History[0].StateName; if (!runningStates.Contains(currentState)) { if (currentState == SucceededState.StateName) { return(GetResult <TResult>(jobId)); } else if (currentState == FailedState.StateName) { return(ThrowError <TResult>(jobId)); } else { throw new InvalidOperationException($"The job must be in the state '{SucceededState.StateName}' or '{FailedState.StateName}' but is in '{currentState}'"); } } await Task.Delay(100, cancellationToken); } }
public async Task <IAsyncResult> Handle() { Event stripeEvent; var secret = _settings.WebhookSecret; using (var stream = new StreamReader(HttpContext.Request.Body)) { var json = await stream.ReadToEndAsync(); stripeEvent = EventUtility.ConstructEvent(json, Request.Headers["Stripe-Signature"], secret, throwOnApiVersionMismatch: false); if (stripeEvent == null) { throw new InvalidOperationException("Unable to extract event."); } } try { if (stripeEvent.Type == Events.CheckoutSessionCompleted) { var data = StripeUtility.ParseStripePayload <Session>(stripeEvent); _logger.LogInformation("Webhook: Checkout Session completed for Session {CartSession}", data.Id); _backgroundJobQueue.Enqueue(() => _checkoutSessionCompleted.HandleWebhookEvent(data.Id)); } else if (stripeEvent.Type == Events.CustomerSubscriptionCreated || stripeEvent.Type == Events.CustomerSubscriptionUpdated || stripeEvent.Type == Events.CustomerSubscriptionDeleted) { var data = StripeUtility.ParseStripePayload <Subscription>(stripeEvent); _logger.LogInformation("Webhook: Subscription {SubscriptionId} changed for customer {CustomerId}", data.Id, data.CustomerId); _backgroundJobQueue.Enqueue(() => _subscriptionChanged.HandleWebhookEvent(data.Id)); } else if (stripeEvent.Type == Events.InvoiceFinalized || stripeEvent.Type == Events.InvoicePaymentSucceeded) { var data = StripeUtility.ParseStripePayload <Invoice>(stripeEvent); _logger.LogInformation("Webhook: Invoice {InvoiceId} changed for customer {CustomerId} with subscription {SubscriptionId}", data.Id, data.CustomerId, data.SubscriptionId); _backgroundJobQueue.Enqueue(() => _invoiceChanged.HandleWebhookEvent(data.SubscriptionId, data.Id)); } return(Ok() as IAsyncResult); } catch (StripeException e) { _logger.LogError(e, "StripeException occurred"); // return StatusCode(500) as IAsyncResult; throw; } catch (InvalidOperationException e) { _logger.LogError(e, "InvalidOperationException occurred"); // return StatusCode(500) as IAsyncResult; throw; } catch (Exception e) { _logger.LogError(e, "Exception occurred"); // return StatusCode(500) as IAsyncResult; throw; } }
public Version AddMaterial(Material material, IFormFile file) { string ext = file.FileName.Split(".").Last(); Version newVersion; if (_context.Materials.FirstOrDefault(p => p.Name == material.Name) == null) { newVersion = new Version { Material = material, Path = _config.GetValue <string>("PathFiles") + material.Name + "_1" + $".{ext}", Release = 1, Size = file.Length, UploadDateTime = DateTime.Now }; using (var filestream = new FileStream(newVersion.Path, FileMode.Create)) { file.CopyTo(filestream); } _context.Materials.Add(material); _context.Versions.Add(newVersion); _context.SaveChanges(); _backgroundJob.Enqueue(() => MailService.SendAsync($"Material with name \"{material.Name}\" was created")); return(newVersion); } return(null); }
/// <inheritdoc /> public void ProcessPayload(PullRequestEventPayload payload) { if ((payload.Action != "opened" && payload.Action != "synchronize") || payload.PullRequest.State.Value != ItemState.Open) { return; } backgroundJobClient.Enqueue(() => ScanPullRequest(payload.Repository.Id, payload.PullRequest.Number, payload.Installation.Id, JobCancellationToken.Null)); }
public void PostConfigure(IBackgroundJobClient backgroundJobClient, IRecurringJobManager recurringJobManager) { recurringJobManager.CreateRecurringJob <SomeJob>("some-job", y => y.DoTheJob(), Cron.Monthly()); recurringJobManager.CreateRecurringJob <SomeJob>("some-job-triggered", y => y.TriggeredJobAction(), Cron.Monthly()); backgroundJobClient.Enqueue <SomeJob>(y => y.DoTheJob()); backgroundJobClient.Enqueue <SomeJob>(y => y.DoTheJobButError()); }
public void Post <T>(ICommand <T> command, string jobname = null) { var name = jobname ?? command.GetType().Name; _logger.LogInformation("Offloading command {event}", name); name += GetJobRequestUserName(command.RequestUser); _backgroundJobClient.Enqueue <SheaftDispatcher>(bridge => bridge.Execute(name, command, CancellationToken.None)); }
public async Task <Guid> Handle(BuyPositionInMatrixCommand command, CancellationToken cancellationToken = default(CancellationToken)) { var userMultiAccount = await _userMultiAccountRepository.GetAsync(command.UserMultiAccountId); await ValidateUserMultiAccount(userMultiAccount, command.MatrixLevel); var sponsorAccountId = userMultiAccount.SponsorId.Value; var invitingUserMatrix = await _matrixPositionHelper.GetMatrixForGivenMultiAccountAsync(sponsorAccountId, command.MatrixLevel); if (invitingUserMatrix is null) { throw new ValidationException($"The inviting user from reflink does not have structure on level: {command.MatrixLevel}"); } MatrixPosition matrixPosition; if (_matrixPositionHelper.CheckIfMatrixHasEmptySpace(invitingUserMatrix)) { matrixPosition = invitingUserMatrix .OrderBy(x => x.DepthLevel) .First(x => x.UserMultiAccountId == null); } else { var userAccount = await _userAccountDataRepository.GetAsync(userMultiAccount.UserAccountDataId); var userMultiAccountIds = userAccount.UserMultiAccounts.Select(x => x.Id).ToList(); matrixPosition = await _matrixPositionHelper.FindTheNearestEmptyPositionFromGivenAccountWhereInParentsMatrixThereIsNoAnyMultiAccountAsync( sponsorAccountId, userMultiAccountIds, command.MatrixLevel); if (matrixPosition is null) { throw new ValidationException("There is no empty space in the structure where account can be assigned"); } await ChangeUserSponsor(userMultiAccount, matrixPosition); } matrixPosition.AssignMultiAccount(command.UserMultiAccountId); await _matrixPositionRepository.UpdateAsync(matrixPosition); _backgroundJobClient.Enqueue <MatrixPositionHasBeenBoughtJob>( job => job.Execute(matrixPosition.Id, null)); _backgroundJobClient.Enqueue <UserBoughtMatrixPositionJob>( job => job.Execute(userMultiAccount.Id, null)); _backgroundJobClient.Enqueue <InitWithdrawalJob>( job => job.Execute(new InitWithdrawalModel { MatrixPositionId = matrixPosition.Id, WithdrawalFor = WithdrawalForHelper.AssignmentInMatrix }, null)); return(matrixPosition.Id); }
public static IApplicationBuilder UseWorkoutPlanServiceDataAccessPoint(this IApplicationBuilder app, IBackgroundJobClient backgroundJobClient) { app.UseHangfireServer(); backgroundJobClient.Enqueue <IUpdateExercisesJob>(x => x.Run()); backgroundJobClient.Enqueue <IPopulateUserCacheJob>(x => x.Run()); backgroundJobClient.Enqueue <IPopulateWorkoutPlans>(x => x.Run()); backgroundJobClient.Enqueue <IPopulateWorkoutSchedulesJob>(x => x.Run()); return(app); }
public static IApplicationBuilder UseWorkoutExecutionServiceDataAccess(this IApplicationBuilder app, IBackgroundJobClient backgroundJobClient) { app.UseHangfireServer(); backgroundJobClient.Enqueue <IPopulateExercisesJob>(x => x.Run()); backgroundJobClient.Enqueue <IPopulateWorkoutsJob>(x => x.Run()); backgroundJobClient.Enqueue <IPopulateUsersJob>(x => x.Run()); backgroundJobClient.Enqueue <IPopulateMoodsJob>(x => x.Run()); backgroundJobClient.Enqueue <IPopulateFatiguesJob>(x => x.Run()); return(app); }
public async Task <IHttpActionResult> Average(AverageProjectsModel model) { if (!ModelState.IsValid) { return(BadRequest()); } if (!AllProjectsExist(model.Projects)) { return(NotFound()); } var now = DateTime.UtcNow; var project = new Project { UserId = User.Identity.GetUserId(), TraceId = Guid.NewGuid(), Name = model.Name, FileName = FormatStitchedFrom(model.Projects), TestName = model.TestName, TestType = model.TestType, Channel = model.Channel, Tag = model.Tag, Mass = model.Mass, Area = model.Area, Comments = $"{model.Comments} {FormatStitchedFromNames(model.Projects)}", IsAveragePlot = true, CreatedAt = now, UpdatedAt = now, StitchedFromNames = FormatStitchedFromNames(model.Projects), }; _db.Projects.Add(project); await _db.SaveChangesAsync(); var traceId = project.TraceId.ToString(); project.JobId = _jobClient.Enqueue <IBackgroundProcessor>( p => p.PrepareAverageProject( traceId, project.Id, model.Projects, JobCancellationToken.Null)); await _db.SaveChangesAsync(); var timeoutJobId = _jobClient.Schedule <IBackgroundProcessor>( p => p.HandleTimeout(traceId, project.Id), _options.ProjectPrepareTimeout); _jobClient.ContinueWith <IBackgroundProcessor>(project.JobId, p => p.CancelTimeout(traceId, project.Id, timeoutJobId), JobContinuationOptions.OnAnyFinishedState); return(Ok()); }
public async Task Execute(string repository, long pullRequestNumber, string commit, string githubUsername, bool open, CancellationToken cancellationToken) { logger.LogInformation("Update to PR {Repository}/{PullRequestNumber} detected by {GithubUsername}", repository, pullRequestNumber, githubUsername); var pullRequest = await database.GithubPullRequests.FirstOrDefaultAsync(p => p.Repository == repository && p.GithubId == pullRequestNumber, cancellationToken); if (pullRequest == null) { await database.LogEntries.AddAsync(new LogEntry() { Message = $"New Github pull request detected {repository}/{pullRequestNumber}", }, cancellationToken); pullRequest = new GithubPullRequest() { Repository = repository, GithubId = pullRequestNumber, LatestCommit = commit, AuthorUsername = githubUsername, Open = open, ClaSigned = await CheckNewCLASignedStatus(null, githubUsername), }; await database.GithubPullRequests.AddAsync(pullRequest, cancellationToken); } else { pullRequest.LatestCommit = commit; if (pullRequest.Open != open) { pullRequest.Open = open; await database.LogEntries.AddAsync(new LogEntry() { Message = $"Github pull request open state {repository}/{pullRequestNumber} is now {open}", }, cancellationToken); } pullRequest.ClaSigned = await CheckNewCLASignedStatus(pullRequest.ClaSigned, pullRequest.AuthorUsername); pullRequest.BumpUpdatedAt(); } await database.SaveChangesAsync(cancellationToken); jobClient.Enqueue <CheckAutoCommentsToPostJob>(x => x.Execute(pullRequest.Id, CancellationToken.None)); jobClient.Enqueue <SetCLAGithubCommitStatusJob>(x => x.Execute(pullRequest.Id, CancellationToken.None)); }
public void Execute(int level, int secretCode) { if (level == 0) { _hangfire.Enqueue <EndJob>(job => job.Execute(secretCode)); } else { _hangfire.Enqueue <IntermediateJob>(job => job.Execute(level - 1, secretCode)); } }
public IEnumerable <WeatherForecast> Get() { var rng = new Random(); _backgroundJobClient.Enqueue <NotificationJobService>((x) => x.NotificationEmails("123", "21:30")); return(Enumerable.Range(1, 5).Select(index => new WeatherForecast { Date = DateTime.Now.AddDays(index), TemperatureC = rng.Next(-20, 55), Summary = Summaries[rng.Next(Summaries.Length)] }) .ToArray()); }
private async Task DonationForFoundationPaid(Guid paymentId) { var payment = await _paymentHistoryRepository.GetAsync(paymentId); var projectDonatedModel = new DonationForFoundationModel { DonatedUserMultiAccountId = payment.UserPaymentForId, Amount = payment.AmountToPay }; _backgroundJobClient.Enqueue <DonationForFoundationJob>( job => job.Execute(projectDonatedModel, null)); }
public async Task <IActionResult> RefreshPollResults([Required] long id, [Required] long pollId) { var access = GetCurrentUserAccess(); var meeting = await GetMeetingWithReadAccess(id, access); if (meeting == null) { return(NotFound()); } var user = HttpContext.AuthenticatedUser() !; var poll = await database.MeetingPolls.FindAsync(id, pollId); if (poll == null) { return(NotFound()); } if (poll.ClosedAt == null) { return(BadRequest("The poll is not closed")); } if (DateTime.UtcNow - poll.PollResultsCreatedAt < TimeSpan.FromSeconds(30)) { return(BadRequest("The poll has been (re)computed in the past 30 seconds")); } if (meeting.OwnerId != user.Id && !user.HasAccessLevel(UserAccessLevel.Admin)) { return(this.WorkingForbid("You don't have permission to recompute polls in this meeting")); } await database.ActionLogEntries.AddAsync(new ActionLogEntry() { Message = $"Poll in meeting ({meeting.Id}) with title: {poll.Title} has been recomputed. " + "Note that random value used for tiebreak will be recomputed and may change the result.", PerformedById = user.Id, }); jobClient.Enqueue <ComputePollResultsJob>(x => x.Execute(poll.MeetingId, poll.PollId, CancellationToken.None)); logger.LogInformation("User {Email} has queued recompute for poll {Id} at {UtcNow}", user.Email, poll.PollId, DateTime.UtcNow); await database.SaveChangesAsync(); return(Ok()); }
public IActionResult AddMember( [FromBody, SwaggerRequestBody("Member to add to the mailing list.", Required = true)] MailingListAddMember request) { if (!ModelState.IsValid) { return(BadRequest(this.ModelState)); } string json = request.Candidate.SerializeChangeTracked(); _jobClient.Enqueue <UpsertCandidateJob>((x) => x.Run(json, null)); return(NoContent()); }
public virtual void Execute() { foreach (AwsProfile profile in _profileRepository.FindAll()) { Guid profileId = profile.Id; _backgroundJobClient.Enqueue <RefreshIpRanges>(x => x.Execute(profileId)); _backgroundJobClient.Enqueue <UpdateAllImages>(x => x.Execute(profileId)); _backgroundJobClient.Enqueue <UpdateAllInstances>(x => x.Execute(profileId)); _backgroundJobClient.Enqueue <UpdateAllStacks>(x => x.Execute(profileId)); _backgroundJobClient.Enqueue <RemoveStaleInstances>(x => x.Execute(profileId)); _backgroundJobClient.Enqueue <RemoveStaleStacks>(x => x.Execute(profileId)); if (!string.IsNullOrEmpty(profile.DetailedBillingS3Bucket)) { if (profile.IsBillingHistoryLoaded) { _backgroundJobClient.Enqueue <UpdateBillingData>(x => x.LoadDeltas(profileId)); } else { _backgroundJobClient.Enqueue <UpdateBillingData>(x => x.LoadAllHistory(profileId)); } } } }
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline. public void Configure( IApplicationBuilder app, IWebHostEnvironment env, IBackgroundJobClient backgroundJobClient, IRecurringJobManager recurringJobManager, IServiceProvider serviceProvider ) { if (env.IsDevelopment()) { app.UseDeveloperExceptionPage(); } else { app.UseExceptionHandler("/Home/Error"); // The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts. app.UseHsts(); } app.UseHttpsRedirection(); app.UseStaticFiles(); app.UseRouting(); app.UseAuthentication(); app.UseAuthorization(); app.UseEndpoints(endpoints => { endpoints.MapControllerRoute( name: "default", pattern: "{controller=Home}/{action=Index}/{id?}"); }); /* Hangfire Server Setup */ app.UseHangfireDashboard("/hangfire", new DashboardOptions { Authorization = new [] { new MyAuthorizationFilter() } }); backgroundJobClient.Enqueue(() => Console.WriteLine("Hangfire online.")); backgroundJobClient.Enqueue(() => serviceProvider.GetService <ISeeder>().Seed()); recurringJobManager.AddOrUpdate( "Auto-Delete", () => serviceProvider.GetService <IDeleteService>().CleanRecordsASync(), Cron.Hourly ); recurringJobManager.AddOrUpdate( "Reset", () => serviceProvider.GetService <ISeeder>().Seed(), "*/30 * * * *" ); }
public async Task <IActionResult> Index() { // backgroundJob.Enqueue(() => Debug.WriteLine("Background Job completed successfully!")); await messagesService.AddAsync(new Message { Content = "Hey" }); backgroundJob.Enqueue(() => LongProcess()); backgroundJob.Enqueue <ISendRequest>(x => x.SendSmsAsync("Hello HangFire Async!")); RecurringJob.AddOrUpdate(() => Console.WriteLine("Daily Job"), Cron.Daily(23, 12)); return(View()); }
private async Task SendPasswordResetEmail(ApplicationUser user) { var code = await _userManager.GeneratePasswordResetTokenAsync(user); var callbackUrl = Url.Action(nameof(ResetPassword), "Account", new { protectedSequence = _urlEncoderWrapper.UrlEncode(_protector.Protect(user.Id)), code = code }, protocol: HttpContext.Request.Scheme); var emailBody = _viewRenderer.Render("Account\\ForgottenPasswordEmailTemplate", new ActivationEmailViewModel { User = user, ActivationUrl = callbackUrl }); _backgroundJobClient.Enqueue(() => SendEmail(user, AccountContent.ResetPasswordEmailSubjectText, emailBody)); }
protected override Task ExecuteAsync(CancellationToken stoppingToken) { var sw = Stopwatch.StartNew(); Parallel.For(0, 250_000, new ParallelOptions { MaxDegreeOfParallelism = Environment.ProcessorCount }, i => { _backgroundJobs.Enqueue(() => EmptyDefault()); _backgroundJobs.Enqueue(() => EmptyCritical()); }); _logger.LogInformation($"Enqueued in {sw.Elapsed}"); return(Task.CompletedTask); }