Hi,
Thks @oguzhanagir ! Didn't see that one. I've tested and it's working :)
It is a dependency issue because I need to include Hangfire core package to get access to JobStorage :
using System.Linq;
using Microsoft.EntityFrameworkCore;
using Abp.Collections.Extensions;
using Abp.BackgroundJobs;
using Abp.Dependency;
using MyApp.FileReferences.Generating;
using MyApp.Notifications;
using Abp.Domain.Uow;
using System;
using Abp.Extensions;
using MyApp.Events.Search;
using System.Linq.Dynamic.Core;
using System.Threading.Tasks;
using Hangfire;
namespace MyApp.Events.Exporting
{
public class FileDocIoGeneratorJob : AsyncBackgroundJob<FileDocIoGeneratorJobArgs>, ITransientDependency
{
private readonly IFileDocIoGenerator _fileDocIoGenerator;
private readonly IUnitOfWorkManager _unitOfWorkManager;
private readonly IAppNotifier _appNotifier;
private readonly IEventQueryManager _eventQueryManager;
public FileDocIoGeneratorJob(IFileDocIoGenerator fileDocIoGenerator,
IUnitOfWorkManager unitOfWorkManager,
IAppNotifier appNotifier,
IEventQueryManager eventQueryManager)
{
_fileDocIoGenerator = fileDocIoGenerator;
_appNotifier = appNotifier;
_unitOfWorkManager = unitOfWorkManager;
_eventQueryManager = eventQueryManager;
}
public override async Task ExecuteAsync(FileDocIoGeneratorEventForecastsJobArgs args)
{
await _unitOfWorkManager.WithUnitOfWorkAsync(async () =>
{
using (UnitOfWorkManager.Current.SetTenantId(args.TenantId))
{
try
{
var events = await _eventQueryManager.GetEventsQueryable().Take(maxExportCount).ToListAsync();
if (events.IsNullOrEmpty())
return;
file = await _fileDocIoGenerator.GenerateFileAsync(events);
await _appNotifier.FileGenerationJobSucceedAsync(file, "FileGenerationJobForSucceed", args.UserIdentifier);
}
catch (Exception ex)
{
var retry = JobStorage.Current.GetConnection().GetJobParameter("jobId", "RetryCount");
Logger.Error("File generation job for event forecasts failed", ex);
if(retry == "10")
await _appNotifier.FileGenerationJobFailedAsync("FileGenerationJobForFailed", args.UserIdentifier);
}
}
});
}
}
}
Since ABP backgroundjob abstracts Hangfire, I don't know how to proceed to get retryCount parameter
Hi,
Yes for sure ! I know your documentation for a while now ;) Have a look to my question please. Are you able to retreive "retryCount" Hangfire property with ABP ?
Tks
Great ! Thank you
Hi @m.aliozkaya,
Thanks for this feedback. I also use it in other parts of the code without any issue.
Did you try doing it from a background job like I did ?
@ismcagdas, I have more information, the error reported on server side is :
StatusCode cannot be set because the response has already started
here are the server logs :
WARN 2024-06-07 13:57:50,467 [110 ] e.Diagnostics.ExceptionHandlerMiddleware - The response has already started, the error handler will not be executed.
ERROR 2024-06-07 13:57:50,468 [110 ] AspNetCore.Server.IIS.Core.IISHttpServer - Connection ID "11024811889413598794", Request ID "80002efa-0000-9900-b63f-84710c7967bb": An unhandled exception was thrown by the application.
System.InvalidOperationException: StatusCode cannot be set because the response has already started.
at Microsoft.AspNetCore.Server.IIS.Core.IISHttpContext.ThrowResponseAlreadyStartedException(String name)
at Microsoft.AspNetCore.Server.IIS.Core.IISHttpContext.Microsoft.AspNetCore.Http.Features.IHttpResponseFeature.set_StatusCode(Int32 value)
at Abp.AspNetCore.Mvc.ExceptionHandling.AbpExceptionFilter.HandleAndWrapException(ExceptionContext context, WrapResultAttribute wrapResultAttribute)
at Abp.AspNetCore.Mvc.ExceptionHandling.AbpExceptionFilter.OnException(ExceptionContext context)
at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.Next(State& next, Scope& scope, Object& state, Boolean& isCompleted)
at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeNextResourceFilter>g__Awaited|25_0(ResourceInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted)
at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.Rethrow(ResourceExecutedContextSealed context)
at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.Next(State& next, Scope& scope, Object& state, Boolean& isCompleted)
at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeFilterPipelineAsync>g__Awaited|20_0(ResourceInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted)
at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeAsync>g__Awaited|17_0(ResourceInvoker invoker, Task task, IDisposable scope)
at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeAsync>g__Awaited|17_0(ResourceInvoker invoker, Task task, IDisposable scope)
at Microsoft.AspNetCore.Routing.EndpointMiddleware.<Invoke>g__AwaitRequestTask|6_0(Endpoint endpoint, Task requestTask, ILogger logger)
at Microsoft.AspNetCore.Localization.RequestLocalizationMiddleware.Invoke(HttpContext context)
at Microsoft.AspNetCore.Authorization.AuthorizationMiddleware.Invoke(HttpContext context)
at Abp.AspNetZeroCore.Web.Authentication.JwtBearer.JwtTokenMiddleware.<>c__DisplayClass0_0.<<UseJwtTokenMiddleware>b__0>d.MoveNext()
--- End of stack trace from previous location ---
at Microsoft.AspNetCore.Authentication.AuthenticationMiddleware.Invoke(HttpContext context)
at MyApp.Web.Startup.Startup.<>c.<<Configure>b__5_1>d.MoveNext() in D:\a\1\s\aspnet-core\src\MyApp.Web.Host\Startup\Startup.cs:line 193
--- End of stack trace from previous location ---
at Microsoft.AspNetCore.Diagnostics.ExceptionHandlerMiddlewareImpl.<Invoke>g__Awaited|8_0(ExceptionHandlerMiddlewareImpl middleware, HttpContext context, Task task)
at Microsoft.AspNetCore.Diagnostics.ExceptionHandlerMiddlewareImpl.HandleException(HttpContext context, ExceptionDispatchInfo edi)
at Microsoft.AspNetCore.Diagnostics.ExceptionHandlerMiddlewareImpl.<Invoke>g__Awaited|8_0(ExceptionHandlerMiddlewareImpl middleware, HttpContext context, Task task)
at Microsoft.AspNetCore.Diagnostics.StatusCodePagesMiddleware.Invoke(HttpContext context)
at Abp.AspNetCore.Security.AbpSecurityHeadersMiddleware.Invoke(HttpContext httpContext)
at Microsoft.AspNetCore.Server.IIS.Core.IISHttpContextOfT`1.ProcessRequestAsync()
The problem is occuring in the startup.cs file, here is the code line :
app.Use(async (context, next) => { await next(); if (context.Response.StatusCode == 404 && !Path.HasExtension(context.Request.Path.Value)) { context.Request.Path = "/index.html"; await next(); } });
Only POST requests are firing this exception ; If the user waits for 5/10 min, the problem disappears. Seems to be linked with JwtTokenMiddleware... maybe with a worker in charge of jwt tokens
Hi @ismcagdas,
Sure, I've just sent you an email.
Hi @Ismcagdas,
No we don't have any error message logged in server side. This seems to be linked with Chrome browsers. The same exact request sent with edge or Firefox is working fine. Here is the message displayed :
It is not something we can reproduce easily, it only happens for some users. We noticed only on Chrome with Windows 11.
In Kudu detailed logs, I found this :
Any idea ?
We really have to fix this as it is impacting several users right now. Tks
Hi @Ismcagdas,
Yes, it is possible to configure a custom host name on Azure CDN, it seems easy. But with ABP, I don't know how to proceed.
Do you mean that I don't need to change anything in my app settings/config ? Do I just need to create a DNS record to redirect all app requests to the CDN endpoint (server and client) ?
In fact, I would appreciate some guidance on how to implement a CDN with ABP. I'm using the same URL for server and client (angular) and tenant is being resolved from the URL (thanks to {TENANCY_NAME})
Sure,
Here is the logs :
WARN 2023-10-25 07:03:09,655 [25 ] me.Caching.Redis.AbpPerRequestRedisCache - IFeatureCollection has been disposed.
Object name: 'Collection'.
System.ObjectDisposedException: IFeatureCollection has been disposed.
Object name: 'Collection'.
at Microsoft.AspNetCore.Http.Features.FeatureReferences`1.ThrowContextDisposed()
at Microsoft.AspNetCore.Http.DefaultHttpContext.get_Items()
at Abp.Runtime.Caching.Redis.AbpPerRequestRedisCache.TryGetValueAsync(String key)
WARN 2023-10-25 07:03:09,655 [25 ] me.Caching.Redis.AbpPerRequestRedisCache - IFeatureCollection has been disposed.
Object name: 'Collection'.
System.ObjectDisposedException: IFeatureCollection has been disposed.
Object name: 'Collection'.
at Microsoft.AspNetCore.Http.Features.FeatureReferences`1.ThrowContextDisposed()
at Microsoft.AspNetCore.Http.DefaultHttpContext.get_Items()
at Abp.Runtime.Caching.Redis.AbpPerRequestRedisCache.TryGetValueAsync(String key)