oleksandra.nakonechniuk的活动

回答

And one moment I use API and we have API-Key authentication.

回答
public class AssessmentJobsService : DomainService, IAssessmentJobsService
{
    #region Fields

    private readonly IAssessmentDetailRepository _assessmentDetailRepository;
    private readonly IMediaRepository _mediaRepository;
    private readonly IBlobManager _blobManager;
    private readonly IAssessmentRepository _assessmentRepository;

    #endregion

    #region Constructors

    /// <summary>
    /// Initializes a new instance of the <see cref="AssessmentJobsService" /> class.
    /// </summary>
    /// <param name="assessmentDetailRepository">The assessment repository.</param>
    /// <param name="mediaRepository">The media repository.</param>
    /// <param name="blobManager">The blob manager.</param>
    public AssessmentJobsService(
        IAssessmentDetailRepository assessmentDetailRepository,
        IMediaRepository mediaRepository,
        IBlobManager blobManager,
        IAssessmentRepository assessmentRepository)
    {
        _assessmentDetailRepository = assessmentDetailRepository;
        _mediaRepository = mediaRepository;
        _blobManager = blobManager;
        _assessmentRepository = assessmentRepository;
    }

    #endregion

    /// <inheritdoc/>
    public void SheduleAssessmentCleanup(long assessmentId)
    {
        BackgroundJob.Schedule(() => CleanUpAssessment(assessmentId), TimeSpan.FromSeconds(30));
    }

    public void SheduleEmptyAssessmentCleanup(long assessmentId)
    {
        BackgroundJob.Schedule(() => CleanUpEmptyAssessment(assessmentId), TimeSpan.FromHours(4));
    }

    /// <inheritdoc/>
    public void SheduleMediaCleanup(long mediaId)
    {
        BackgroundJob.Schedule(() => CleanUpMedia(mediaId), TimeSpan.FromHours(4));
    }

    /// <inheritdoc/>
    public async Task StartTrackingJob(long assessmentDetailId, bool isOneStepProcess)
    {
        // Create a Hangfire job to finish the job if not all methods are called within 5 minutes
        var jobId = BackgroundJob.Schedule(() => CheckProcessVideoTracking(assessmentDetailId, isOneStepProcess), TimeSpan.FromMinutes(3));
        var assessementDetails = await _assessmentDetailRepository.GetAsync(assessmentDetailId);
        assessementDetails.JobId = jobId;

        // Sets default status
        assessementDetails.ProcessVideoTrackStatus = (int)ProcessVideoTrackingStatus.InProgress;
        assessementDetails.ProcessVideoTrackStatusValue = ProcessVideoTrackingStatus.InProgress.ToString();
        await _assessmentDetailRepository.UpdateAsync(assessementDetails, true);
    }

    /// <inheritdoc/>
    //[AutomaticRetry(Attempts = 5, DelaysInSeconds = new[] { 300, 600, 900, 1800, 3600 })]
    [AutomaticRetry(Attempts = 5, DelaysInSeconds = new[] { 60, 60, 60 })]
    public async Task CheckProcessVideoTracking(long assessmentDetailId, bool isOneStepProcess)
    {
       var assessmentDetails = await _assessmentDetailRepository.GetAsync(assessmentDetailId)
            ?? throw new Exception($"Job failed. Assessment details were not found");
        var status = (ProcessVideoTrackingStatus)assessmentDetails.ProcessVideoTrackStatus;

        if ((isOneStepProcess && status == ProcessVideoTrackingStatus.ProcessData) ||
        (!isOneStepProcess && status == (ProcessVideoTrackingStatus.ProcessData | ProcessVideoTrackingStatus.Report | ProcessVideoTrackingStatus.Overlay)))
        {
            return;
        }

        throw new Exception($"Job failed. Status {status}");
    }

    /// <inheritdoc/>
    public async Task CleanUpMedia(long mediaId)
    {
        var mediaIsInUse = await _mediaRepository.CheckMediaWithAssessmentDetails(mediaId);
        if (!mediaIsInUse)
        {
            var media = await _mediaRepository.FindAsync(mediaId);
            if(media == null)
            {
                return;
            }
            await _mediaRepository.DeleteAsync(mediaId);
            await _blobManager.DeleteBlob(media?.MediaUrl, media?.FileName);
        }
    }

    /// <inheritdoc/>
    public async Task CleanUpMediaMedBridge()
    {
        try
        {
            // Get details from assessment where externalAssessmentId != null
            var mediaIds = await _assessmentDetailRepository.GetListMediaIdAndCleanDetailsMedbridgeAsync();
            if (mediaIds != null)
            {
                var mediaQueryable = await _mediaRepository.GetQueryableAsync();
                var medias = mediaQueryable.Where(m => mediaIds.Contains(m.Id)).ToList();
                if (medias == null)
                {
                    return;
                }

                await _mediaRepository.DeleteManyAsync(mediaIds, true);
                foreach (var media in medias)
                {
                    await _blobManager.DeleteBlob(media?.MediaUrl, media?.FileName);
                }
            }
        }
        catch (Exception ex)
        {
            throw new Exception(ex.Message);
        }
    }


    /// <inheritdoc/>
    public async Task CleanUpAssessment(long assessmentId)
    {
        var details = await _assessmentDetailRepository.GetListAsync(x => x.AssessmentId == assessmentId);
        var mediaIds = details.Select(x => x.MediaId).ToList();
        await _assessmentDetailRepository.DeleteManyAsync(details);

        var medias = await _mediaRepository.GetListAsync(x => mediaIds.Contains(x.Id));
        await _mediaRepository.DeleteManyAsync(medias);

        foreach (var media in medias)
        {
            await _blobManager.DeleteBlob(media.MediaUrl, media.FileName);
        }
    }

    public async Task CleanUpEmptyAssessment(long assessmentId)
    {
        if (!await _assessmentDetailRepository.CheckAssessmentWithAssessmentDetails(assessmentId))
        {
            var assessment = await _assessmentRepository.FindAsync(assessmentId);
            if (assessment != null)
            {
                await _assessmentRepository.DeleteAsync(assessment);
            }
        }
    }
}

and in HttpHostModule

 private void ConfigureHangfire(ServiceConfigurationContext context, IConfiguration configuration)
 {
     context.Services.AddHangfire(config =>
     {
         GlobalConfiguration.Configuration.UsePostgreSqlStorage(configuration.GetConnectionString("Default"));
     });
 }
问题

We are using MultiTenancy. When I created scheduled job and it was executed it doesn't work as expected. It doesn't have the correct context - TenantId is null. But when I was calling job Tenat was not null. Does it mean that hangfire jobs doesn't work with multiTenancy. Or if you can suggest some approach please write.

  • ABP Framework version: vX.X.X
  • UI Type: Angular
  • Database System: EF Core ( PostgreSQL, etc..)
    • Auth Server Separated (for Angular)**: yes
  • Exception message and full stack trace:
  • Steps to reproduce the issue:
回答

Is it enough for stack trace. Or we need to add this code and we will have more information?

回答

13:40:27 INF] Executed endpoint 'Health checks' [13:40:27 INF] Event dropped by processor CustomSentryProcessor [13:40:27 INF] Request finished HTTP/1.1 GET http://10.244.6.75:80/health-status - - - 200 - application/json 4.1482ms [13:40:27 INF] Executed endpoint 'Health checks' [13:40:27 INF] Event dropped by processor CustomSentryProcessor [13:40:27 INF] Request finished HTTP/1.1 GET http://10.244.6.75:80/health-status - - - 200 - application/json 3.0396ms [13:40:27 ERR] ---------- RemoteServiceErrorInfo ---------- { "code": null, "message": "An internal error occurred during your request!", "details": null, "data": {}, "validationErrors": null }

[13:40:27 ERR] Undefined feature: risk Volo.Abp.AbpException: Undefined feature: risk at Volo.Abp.Features.FeatureDefinitionManager.GetAsync(String name) at Volo.Abp.FeatureManagement.FeatureManager.GetOrNullInternalAsync(String name, String providerName, String providerKey, Boolean fallback) at Volo.Abp.FeatureManagement.FeatureManager.GetOrNullWithProviderAsync(String name, String providerName, String providerKey, Boolean fallback) at Volo.Abp.FeatureManagement.FeatureAppService.GetAsync(String providerName, String providerKey) at Castle.DynamicProxy.AsyncInterceptorBase.ProceedAsynchronous[TResult](IInvocation invocation, IInvocationProceedInfo proceedInfo) at Volo.Abp.Castle.DynamicProxy.CastleAbpMethodInvocationAdapterWithReturnValue1.ProceedAsync() at Volo.Abp.Authorization.AuthorizationInterceptor.InterceptAsync(IAbpMethodInvocation invocation) at Volo.Abp.Castle.DynamicProxy.CastleAsyncAbpInterceptorAdapter1.InterceptAsync[TResult](IInvocation invocation, IInvocationProceedInfo proceedInfo, Func3 proceed) at Castle.DynamicProxy.AsyncInterceptorBase.ProceedAsynchronous[TResult](IInvocation invocation, IInvocationProceedInfo proceedInfo) at Volo.Abp.Castle.DynamicProxy.CastleAbpMethodInvocationAdapterWithReturnValue1.ProceedAsync() at Volo.Abp.GlobalFeatures.GlobalFeatureInterceptor.InterceptAsync(IAbpMethodInvocation invocation) at Volo.Abp.Castle.DynamicProxy.CastleAsyncAbpInterceptorAdapter1.InterceptAsync[TResult](IInvocation invocation, IInvocationProceedInfo proceedInfo, Func3 proceed) at Castle.DynamicProxy.AsyncInterceptorBase.ProceedAsynchronous[TResult](IInvocation invocation, IInvocationProceedInfo proceedInfo) at Volo.Abp.Castle.DynamicProxy.CastleAbpMethodInvocationAdapterWithReturnValue1.ProceedAsync() at Volo.Abp.Auditing.AuditingInterceptor.ProceedByLoggingAsync(IAbpMethodInvocation invocation, AbpAuditingOptions options, IAuditingHelper auditingHelper, IAuditLogScope auditLogScope) at Volo.Abp.Auditing.AuditingInterceptor.InterceptAsync(IAbpMethodInvocation invocation) at Volo.Abp.Castle.DynamicProxy.CastleAsyncAbpInterceptorAdapter1.InterceptAsync[TResult](IInvocation invocation, IInvocationProceedInfo proceedInfo, Func3 proceed) at Castle.DynamicProxy.AsyncInterceptorBase.ProceedAsynchronous[TResult](IInvocation invocation, IInvocationProceedInfo proceedInfo) at Volo.Abp.Castle.DynamicProxy.CastleAbpMethodInvocationAdapterWithReturnValue1.ProceedAsync() at Volo.Abp.Validation.ValidationInterceptor.InterceptAsync(IAbpMethodInvocation invocation) at Volo.Abp.Castle.DynamicProxy.CastleAsyncAbpInterceptorAdapter1.InterceptAsync[TResult](IInvocation invocation, IInvocationProceedInfo proceedInfo, Func3 proceed) at Castle.DynamicProxy.AsyncInterceptorBase.ProceedAsynchronous[TResult](IInvocation invocation, IInvocationProceedInfo proceedInfo) at Volo.Abp.Castle.DynamicProxy.CastleAbpMethodInvocationAdapterWithReturnValue1.ProceedAsync() at Volo.Abp.Uow.UnitOfWorkInterceptor.InterceptAsync(IAbpMethodInvocation invocation) at Volo.Abp.Castle.DynamicProxy.CastleAsyncAbpInterceptorAdapter1.InterceptAsync[TResult](IInvocation invocation, IInvocationProceedInfo proceedInfo, Func3 proceed) at lambda_method3149(Closure, Object) at Microsoft.AspNetCore.Mvc.Infrastructure.ActionMethodExecutor.AwaitableObjectResultExecutor.Execute(ActionContext actionContext, IActionResultTypeMapper mapper, ObjectMethodExecutor executor, Object controller, Object[] arguments) at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.<InvokeActionMethodAsync>g__Awaited|12_0(ControllerActionInvoker invoker, ValueTask1 actionResultValueTask) at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.<InvokeNextActionFilterAsync>g__Awaited|10_0(ControllerActionInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted) at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.Rethrow(ActionExecutedContextSealed context) at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.Next(State& next, Scope& scope, Object& state, Boolean& isCompleted) at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.<InvokeInnerFilterAsync>g__Awaited|13_0(ControllerActionInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted) at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeNextExceptionFilterAsync>g__Awaited|26_0(ResourceInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted) [13:40:27 INF] Executing ObjectResult, writing value of type 'Volo.Abp.Http.RemoteServiceErrorResponse'. [13:40:27 INF] Executed action Volo.Abp.FeatureManagement.FeaturesController.GetAsync (Volo.Abp.FeatureManagement.HttpApi) in 251.6018ms [13:40:27 INF] Executed endpoint 'Volo.Abp.FeatureManagement.FeaturesController.GetAsync (Volo.Abp.FeatureManagement.HttpApi)' [13:40:27 INF] Envelope queued up: 'd86a37c4329848568ba1fa8efc199355' [13:40:27 INF] Request finished HTTP/1.1 GET http://api-dev.3motionai.com/api/feature-management/features?providerName=T - - - 500 - application/json;+charset=utf-8 274.8530ms [13:40:27 INF] Envelope 'd86a37c4329848568ba1fa8efc199355' successfully sent. [13:40:34 INF] Start processing HTTP request GET http://3m-backend-api-webhost-dev2-55cd8c9cd4-qkxzs/health-status [13:40:34 INF] Sending HTTP request GET http://3m-backend-api-webhost-dev2-55cd8c9cd4-qkxzs/health-status [13:40:34 INF] Request starting HTTP/1.1 GET http://3m-backend-api-webhost-dev2-55cd8c9cd4-qkxzs/health-status - - [13:40:34 INF] Started transaction with span ID 'f1cd941c0dff465c' and trace ID '86a44028d26f496a91756b61b7026d02'. [13:40:34 INF] Executing endpoint 'Health checks' [13:40:34 INF] Executed endpoint 'Health checks' [13:40:34 INF] Received HTTP response headers after 3.8044ms - 200 [13:40:34 INF] End processing HTTP request after 3.9389ms - 200 [13:40:34 INF] Event dropped by processor CustomSentryProcessor [13:40:34 INF] Request finished HTTP/1.1 GET http://3m-backend-api-webhost-dev2-55cd8c9cd4-qkxzs/health-status - - - 200 - application/json 3.7909ms [13:40:42 INF] Request starting HTTP/1.1 GET http://10.244.6.75:80/health-status - - [13:40:42 INF] Request starting HTTP/1.1 GET http://10.244.6.75:80/health-status - - [13:40:42 INF] Sentry trace header is null. Creating new Sentry Propagation Context. [13:40:42 INF] Sentry trace header is null. Creating new Sentry Propagation Context. [13:40:42 INF] Started transaction with span ID 'e3d7716683cd4290' and trace ID '46a9a0a8ae604a9fa92fa0bda97e34b8'. [13:40:42 INF] Started transaction with span ID '57415cff88434c49' and trace ID '92d5b63d8cbe40d79d0872310c55d61e'. [13:40:42 INF] Executing endpoint 'Health checks'

回答

I can send You stackTrace [13:39:47 INF] Request starting HTTP/1.1 GET http://api-dev.3motionai.com/api/app/assessment-types/movements - - [13:39:47 INF] Sentry trace header is null. Creating new Sentry Propagation Context. [13:39:47 INF] Started transaction with span ID '3407bb84c47c4acd' and trace ID '18271856ff714539a8b97737c3b2da46'. [13:39:47 INF] Executing endpoint '_3M.AssessmentTypes.AssessmentTypesAppService.GetMovements (_3M.Application)' [13:39:47 INF] Route matched with {action = "GetMovements", controller = "AssessmentTypes", area = "", page = ""}. Executing controller action with signature System.Threading.Tasks.Task1[System.Collections.Generic.List1[_3M.AssessmentTypes.AssessmentTypeDto]] GetMovements() on controller _3M.AssessmentTypes.AssessmentTypesAppService (_3M.Application). [13:39:48 ERR] ---------- RemoteServiceErrorInfo ---------- { "code": null, "message": "An internal error occurred during your request!", "details": null, "data": {}, "validationErrors": null }

[13:39:48 ERR] Undefined feature: Sports Volo.Abp.AbpException: Undefined feature: Sports at Volo.Abp.Features.FeatureDefinitionManager.GetAsync(String name) at Volo.Abp.Features.FeatureChecker.GetOrNullAsync(String name) at Volo.Abp.Features.FeatureCheckerBase.IsEnabledAsync(String name) at _3M.AssessmentTypes.AssessmentTypesAppService.GetListAssessmentTypesWithCheckedFeatures(List1 asmtypes) in /azp/_work/1/s/src/_3M.Application/AssessmentTypes/AssessmentTypesAppService.cs:line 80 at _3M.AssessmentTypes.AssessmentTypesAppService.GetMovements() in /azp/_work/1/s/src/_3M.Application/AssessmentTypes/AssessmentTypesAppService.cs:line 58 at lambda_method2576(Closure, Object) at Microsoft.AspNetCore.Mvc.Infrastructure.ActionMethodExecutor.AwaitableObjectResultExecutor.Execute(ActionContext actionContext, IActionResultTypeMapper mapper, ObjectMethodExecutor executor, Object controller, Object[] arguments) at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.<InvokeActionMethodAsync>g__Awaited|12_0(ControllerActionInvoker invoker, ValueTask1 actionResultValueTask) at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.<InvokeNextActionFilterAsync>g__Awaited|10_0(ControllerActionInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted) at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.Rethrow(ActionExecutedContextSealed context) at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.Next(State& next, Scope& scope, Object& state, Boolean& isCompleted) at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.<InvokeInnerFilterAsync>g__Awaited|13_0(ControllerActionInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted) at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeNextExceptionFilterAsync>g__Awaited|26_0(ResourceInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted) [13:39:48 INF] Executing ObjectResult, writing value of type 'Volo.Abp.Http.RemoteServiceErrorResponse'. [13:39:48 INF] Executed action _3M.AssessmentTypes.AssessmentTypesAppService.GetMovements (_3M.Application) in 450.3411ms [13:39:48 INF] Executed endpoint '_3M.AssessmentTypes.AssessmentTypesAppService.GetMovements (_3M.Application)' [13:39:48 INF] Enve

回答

This part x => await _featureChecker.IsEnabledAsync(x.Code) will not work it needs WhenAll but this works with repository and I had some problems with WhenAll and asynchronous calls to db.

回答

My public class AssessmentFeatureDefinitionProvider : FeatureDefinitionProvider { private readonly IAssessmentTypeRepository _assessmentTypeRepository; private const string FeatureNameForSingleMovements = "Tasks"; private const string FeatureNameForProtocols = "Protocols";

public AssessmentFeatureDefinitionProvider(IAssessmentTypeRepository assessmentTypeRepository)
{
    _assessmentTypeRepository = assessmentTypeRepository;
}

public override async void Define(IFeatureDefinitionContext context)
{
    var tasksGroup = context.AddGroup(FeatureNameForSingleMovements);
    var protocolGroup = context.AddGroup(FeatureNameForProtocols);
    await DefineFeaturesForAssessmentType(tasksGroup, AssessmentTypeNames.Movement);
    await DefineFeaturesForAssessmentType(protocolGroup, AssessmentTypeNames.Protocol);
}

private async Task DefineFeaturesForAssessmentType(FeatureGroupDefinition contextGroup, AssessmentTypeNames assessmentTypeName)
{
    var assessmentTypes = await _assessmentTypeRepository.GetAssessmentTypes(assessmentTypeName);

    foreach (var assessmentType in assessmentTypes)
    {
        var feature = contextGroup.AddFeature(assessmentType.Code, defaultValue: "true", displayName: L($"DisplayName:AssessmentType.{assessmentType.Code}"));

        var movements = assessmentType.AssessmentTypeMovements.Select(x => x.AssessmentMovement).ToList();
        foreach (var movement in movements)
        {
            feature.CreateChild(movement.Code, defaultValue: "true", displayName: L($"DisplayName:AssessmentMovement.{movement.Code}"));
        }
    }
}

private static LocalizableString L(string name)
{
    return LocalizableString.Create&lt;_3MFeatureResource&gt;(name);
}

}

回答

And is it ok that I have FeatureDefinitionProvider in the domain project

回答

I will try. But what about get features it fell down two. And can You answer me can feature has a name with white spaces?

显示 13 个条目中的 1 到 10 个.
Made with ❤️ on ABP v8.2.0-preview Updated on 三月 25, 2024, 15:11