Base solution for your next web application
Open Closed

Problem with ITempFileCacheManager when running more than 1 instance of App #9606


User avatar
0
ajayak created

.net core/ 9.1.0 / Angular

We are running our App in West Europe and France Central regions on Azure.

In 80% cases, downloading a file with FileDownloadService works perfectly well. In 20% cases, I get the following error in browser with white page:

{"result":"Requested file does not exist!","targetUrl":null,"success":true,"error":null,"unAuthorizedRequest":false,"__abp":true}

15 Answer(s)
  • User Avatar
    0
    zony created
    Support Team

    Hi ajayak, This problem may be caused by cache expiration. After calling ITempFileCacheManager and calling SetFile() method to set temporary files, the effective time of cache is 1 minute. If the front end uses the token to obtain data after more than 1 minute, this exception will be caused.

  • User Avatar
    0
    ajayak created

    Hi @zony, How can I increases the expiration timeout?

  • User Avatar
    0
    ismcagdas created
    Support Team

    Hi @ajayak

    By default, ITempFileCacheManager's default implementation uses in-memory cache. Moving to Redis cache might solve your problem.

  • User Avatar
    0
    ajayak created

    Hi @ismcagdas,

    We switched to Redis cache but still getting the same error.

  • User Avatar
    0
    ismcagdas created
    Support Team

    Hi @ajayak

    Does the request take long time ? Could it timeout on Azure side ? You can also try to increase cache timeout here

  • User Avatar
    0
    ajayak created

    Hi @ismcagdas, U can try setting timeout to 2 minutes.

  • User Avatar
    0
    ajayak created

    Hi @ismcagdas,

    Our client reported the same error today. Failed on first try and worked on second. Any idea?

  • User Avatar
    0
    ismcagdas created
    Support Team

    Hi @ajayak

    1. Can you reproduce this problem yourself ?
    2. Could you explain the use case step by step ? How is the file uploaded etc ...
  • User Avatar
    0
    ajayak created

    Hi @ismcagdas,

    I'm got this problem only once in past 20 days but customer reported it after we switched to Redis cache.

    Backend code:

    public async Task<FileDto> GetReportExcelForDownload(int id)
            {
                var report = await _inventoryReportRepository.GetAsync(id);
                var bytes = await _azureBlobStorageManager.DownloadByteArray(_inventoryReportContainer, report.ExcelFileName);
                var file = new FileDto(report.ExcelFileName, MimeTypeNames.ApplicationVndOpenxmlformatsOfficedocumentSpreadsheetmlSheet);
                _tempFileCacheManager.SetFile(file.FileToken, bytes);
                return file;
            }
    

    Frontend code:

    
    constructor(
            injector: Injector,
            private _inventoryService: InventoryReportServiceProxy,
            private _fileDownloadService: FileDownloadService
        ) {
            super(injector);
        }
        
        
    downloadExcel(id) {
            this._inventoryService.getReportExcelForDownload(id)
                .subscribe(result => this._fileDownloadService.downloadTempFile(result));
        }
    
  • User Avatar
    0
    ismcagdas created
    Support Team

    Hi @ajayak

    Your code seems fine at first look. Do you have the detailed exception message about this problem ? Could it be this line causing the problem ?

    var bytes = await _azureBlobStorageManager.DownloadByteArray(_inventoryReportContainer, report.ExcelFileName);

  • User Avatar
    0
    ajayak created

    Hi @ismcagdas,

    I can't see any error in the logs for the GetReportExcelForDownload function. It must be working fine. If there was an error here, user would be thrown UserFriendlyException.

    The error must be coming from DownloadTempFile .

  • User Avatar
    0
    ismcagdas created
    Support Team

    Hi @ajayak

    Then, it is a bit of a bad approach but;

    1. You can temporarily set the temp file cache duration to 1 day
    2. Log token to log file here https://github.com/aspnetzero/aspnet-zero-core/blob/dev/aspnet-core/src/MyCompanyName.AbpZeroTemplate.Web.Core/Controllers/FileController.cs#L31
    3. And next time when a customer faces such a problem, you can check if a file exist in Redis with that token

    It is hard to find a solution if we can't reproduce the problem on our side.

  • User Avatar
    0
    ajayak created

    Hi @ismcagdas,

    I tried this but our customers are still facing this issue. I'm sharing the code and logs in more details.

    Code:

    protected void Save(XSSFWorkbook excelPackage, FileDto file)
    {
        Logger.Log(LogSeverity.Info, $"Writing memory stream for file - {file.FileName}, token {file.FileToken}");
    
        using (var stream = new MemoryStream())
        {
            Logger.Log(LogSeverity.Info, "Writing to memory stream");
            excelPackage.Write(stream);
            _tempFileCacheManager.SetFile(file.FileToken, stream.ToArray());
            Logger.Log(LogSeverity.Info, "Saved to temp file");
        }
    
        try
        {
            var test = _tempFileCacheManager.GetFile(file.FileToken);
            Logger.Log(LogSeverity.Info, $"Verified by getting file - {file.FileToken}, bytes - {test.Length}");
        }
        catch (Exception)
        {
            Logger.Log(LogSeverity.Error, $"Verification failed for file - {file.FileToken}");
        }
    }
    

    Logs:

    INFO  2020-10-27 12:36:04,170 [36   ] Microsoft.AspNetCore.Hosting.Diagnostics - Request starting HTTP/1.1 GET https://service.primepenguin.com/api/services/app/InventoryReport/GetInventoryListToExcel?Sorting=&MaxResultCount=77&SkipCount=0  
    INFO  2020-10-27 12:36:04,177 [36   ] pNetCore.Cors.Infrastructure.CorsService - CORS policy execution successful.
    INFO  2020-10-27 12:36:04,199 [36   ] uthentication.JwtBearer.JwtBearerHandler - Successfully validated the token.
    INFO  2020-10-27 12:36:04,205 [36   ] ft.AspNetCore.Routing.EndpointMiddleware - Executing endpoint 'PrimePenguin.Technology.Reports.Inventory.InventoryReportAppService.GetInventoryListToExcel (PrimePenguin.Technology.Application)'
    INFO  2020-10-27 12:36:04,214 [36   ] c.Infrastructure.ControllerActionInvoker - Route matched with {area = "app", action = "GetInventoryListToExcel", controller = "InventoryReport"}. Executing controller action with signature System.Threading.Tasks.Task`1[PrimePenguin.Technology.Dto.FileDto] GetInventoryListToExcel(PrimePenguin.Technology.Reports.Inventory.Dto.GetInventoryListInput) on controller PrimePenguin.Technology.Reports.Inventory.InventoryReportAppService (PrimePenguin.Technology.Application).
    INFO  2020-10-27 12:36:04,797 [36   ] Microsoft.AspNetCore.Hosting.Diagnostics - Request starting HTTP/1.1 GET http://service-eu.primepenguin.com/  
    INFO  2020-10-27 12:36:04,799 [36   ] oft.AspNetCore.Rewrite.RewriteMiddleware - Request redirected to HTTPS
    INFO  2020-10-27 12:36:04,800 [36   ] Microsoft.AspNetCore.Hosting.Diagnostics - Request finished in 3.8333ms 301 
    INFO  2020-10-27 12:36:05,136 [36   ] y.Exporting.InventoryReportExcelExporter - Generating file - InventoryList.xlsx
    INFO  2020-10-27 12:36:05,926 [36   ] y.Exporting.InventoryReportExcelExporter - Writing memory stream for file - InventoryList.xlsx, token 151e1d45333744f1a5725739dc01a4cc
    INFO  2020-10-27 12:36:05,930 [36   ] y.Exporting.InventoryReportExcelExporter - Writing to memory stream
    INFO  2020-10-27 12:36:06,114 [36   ] y.Exporting.InventoryReportExcelExporter - Saved to temp file
    INFO  2020-10-27 12:36:06,116 [36   ] y.Exporting.InventoryReportExcelExporter - Verified by getting file - 151e1d45333744f1a5725739dc01a4cc, bytes - 9886
    INFO  2020-10-27 12:36:06,136 [36   ] .Mvc.Infrastructure.ObjectResultExecutor - Executing ObjectResult, writing value of type 'Abp.Web.Models.AjaxResponse'.
    INFO  2020-10-27 12:36:06,138 [36   ] c.Infrastructure.ControllerActionInvoker - Executed action PrimePenguin.Technology.Reports.Inventory.InventoryReportAppService.GetInventoryListToExcel (PrimePenguin.Technology.Application) in 1923.8685ms
    INFO  2020-10-27 12:36:06,139 [36   ] ft.AspNetCore.Routing.EndpointMiddleware - Executed endpoint 'PrimePenguin.Technology.Reports.Inventory.InventoryReportAppService.GetInventoryListToExcel (PrimePenguin.Technology.Application)'
    INFO  2020-10-27 12:36:06,140 [36   ] Microsoft.AspNetCore.Hosting.Diagnostics - Request finished in 1970.2227ms 200 application/json; charset=utf-8
    INFO  2020-10-27 12:36:25,175 [4    ] Microsoft.AspNetCore.Hosting.Diagnostics - Request starting HTTP/1.1 GET https://primepenguinservice-eu.azurewebsites.net/Ui/Login  
    

    Code:

    public ActionResult DownloadTempFile(FileDto file)
    {
    
        var fileBytes = _tempFileCacheManager.GetFile(file.FileToken);
        if (fileBytes == null)
        {
            AsyncHelper.RunSync(() => _errorReporter.CaptureAsync($"Error in getting file - {file.FileName}, token - {file.FileToken}"));
    
            // Optimistic retry
            Thread.Sleep(500);
            fileBytes = _tempFileCacheManager.GetFile(file.FileToken);
    
            if (fileBytes == null)
            {
                return NotFound(L("RequestedFileDoesNotExists"));
            }
        }
    
        return File(fileBytes, file.FileType, file.FileName);
    }
    

    Error:

    {"result":"Requested file does not exist!","targetUrl":null,"success":true,"error":null,"unAuthorizedRequest":false,"__abp":true}
    
    

    I checked redis cache and token was not available.

  • User Avatar
    0
    ismcagdas created
    Support Team

    Hi @ajayak

    Is it possible to share your project via email with [email protected] ? I can check this in details.

    Thanks,

  • User Avatar
    0
    ajayak created

    Hi @ismcagdas,

    I found the problem. Our redis cache configuration was not configured correctly and was not in use. The issue was file was requested from different server where file was not cached. Completely my fault