CS2-3: В контроллер репортов добавлено создание репорта

This commit is contained in:
KharchenkoVV 2021-05-19 14:41:27 +05:00
parent 35b24176ff
commit b39be3547c
9 changed files with 138 additions and 52 deletions

View File

@ -1,11 +0,0 @@
using System.IO;
namespace AsbCloudApp.Data
{
public class ReportPropertiesDto
{
public FileStream Filestream { get; set; }
public string ContentType { get; set; }
public string FileName { get; set; }
}
}

View File

@ -0,0 +1,11 @@
using System;
namespace AsbCloudApp.Services
{
public interface IBackgroundQueue
{
int EnqueueTask(Action action);
bool TryDequeue(out (Action action, int id) item);
}
}

View File

@ -5,8 +5,9 @@ namespace AsbCloudApp.Services
{
public interface IReportService
{
string RootPath { get; }
int CreateReport(int wellId, int stepSeconds, int format, DateTime begin, DateTime end);
int GetReportPagesCount(int wellId, DateTime begin, DateTime end, int stepSeconds, int format);
ReportPropertiesDto GetReportFileProperties(string reportName, string rootPath);
DatesRangeDto GetReportsDatesRange(int wellId);
}
}

View File

@ -7,6 +7,7 @@
<ItemGroup>
<PackageReference Include="AutoMapper" Version="10.1.1" />
<PackageReference Include="itext7" Version="7.1.15" />
<PackageReference Include="Microsoft.Extensions.Hosting" Version="5.0.0" />
<PackageReference Include="System.IdentityModel.Tokens.Jwt" Version="6.10.0" />
</ItemGroup>
@ -21,4 +22,19 @@
</Reference>
</ItemGroup>
<ItemGroup>
<None Update="CommonLibs\AsbSaubReport\Resources\logo.jpg">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Update="CommonLibs\AsbSaubReport\Resources\Roboto-Bold.ttf">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Update="CommonLibs\AsbSaubReport\Resources\Roboto-Light.ttf">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Update="CommonLibs\AsbSaubReport\Resources\Roboto-Thin.ttf">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
</ItemGroup>
</Project>

View File

@ -19,9 +19,12 @@ namespace AsbCloudInfrastructure
services.AddScoped<IAsbCloudDbContext>(provider => provider.GetService<AsbCloudDbContext>());
services.AddHostedService<BackgroundWorkerService>();
services.AddSingleton(new MapperConfiguration(AutoMapperConfig));
services.AddSingleton(new CacheDb());
services.AddSingleton<ITelemetryTracker, TelemetryTracker>();
services.AddSingleton<IBackgroundQueue, BackgroundQueue>();
services.AddTransient<IAuthService, AuthService>();
services.AddTransient<IWellService, WellService>();

View File

@ -0,0 +1,26 @@
using System;
using System.Collections.Concurrent;
using AsbCloudApp.Services;
namespace AsbCloudInfrastructure.Services
{
class BackgroundQueue : IBackgroundQueue
{
private ConcurrentQueue<(Action action, int id)> tasks =
new ConcurrentQueue<(Action action, int id)>();
private int id = 0;
public int EnqueueTask(Action action)
{
if (action == null)
throw new ArgumentNullException(nameof(action));
tasks.Enqueue(new(action, id++));
return id;
}
public bool TryDequeue(out (Action action, int id) item)
=> tasks.TryDequeue(out item);
}
}

View File

@ -0,0 +1,40 @@
using System.Threading;
using System.Threading.Tasks;
using Microsoft.Extensions.Hosting;
using AsbCloudApp.Services;
namespace AsbCloudInfrastructure.Services
{
public class BackgroundWorkerService : BackgroundService
{
private readonly IBackgroundQueue tasksQueue;
public BackgroundWorkerService(IBackgroundQueue tasksQueue)
{
this.tasksQueue = tasksQueue;
}
protected override async Task ExecuteAsync(CancellationToken token)
{
try
{
while (!token.IsCancellationRequested)
{
if (tasksQueue.TryDequeue(out var item))
await Task.Run(item.action);
else
await Task.Delay(100, token);
}
}
catch
{
//logger ?
}
}
public override async Task StopAsync(CancellationToken token)
{
await base.StopAsync(token);
}
}
}

View File

@ -3,6 +3,8 @@ using AsbCloudApp.Data;
using AsbCloudDb.Model;
using System;
using System.IO;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Configuration;
using AsbSaubReport;
namespace AsbCloudInfrastructure.Services
@ -10,35 +12,46 @@ namespace AsbCloudInfrastructure.Services
public class ReportService : IReportService
{
private readonly IAsbCloudDbContext db;
private readonly IConfiguration configuration;
private readonly ITelemetryService telemetryService;
private readonly IServiceProvider serviceProvider;
private readonly IBackgroundQueue queue;
public ReportService(IAsbCloudDbContext db, ITelemetryService telemetryService)
public ReportService(IAsbCloudDbContext db, IConfiguration configuration, ITelemetryService telemetryService, IServiceProvider serviceProvider, IBackgroundQueue queue)
{
this.db = db;
this.configuration = configuration;
this.telemetryService = telemetryService;
this.queue = queue;
this.serviceProvider = serviceProvider;
RootPath = "reports";
}
public string RootPath { get ; private set; }
public int CreateReport(int wellId, int stepSeconds, int format, DateTime begin, DateTime end)
{
var newReportId = queue.EnqueueTask(() =>
{
var optionsBuilder = new DbContextOptionsBuilder<AsbCloudDbContext>();
optionsBuilder.UseNpgsql(configuration.GetConnectionString("DefaultConnection"));
using (var context = new AsbCloudDbContext(optionsBuilder.Options))
{
var generator = GetReportGenerator(wellId, begin, end, stepSeconds, format, context);
generator.Make();
}
});
return newReportId;
}
public int GetReportPagesCount(int wellId, DateTime begin, DateTime end, int stepSeconds, int format)
{
var generator = GetReportGenerator(wellId, begin, end, stepSeconds, format);
var generator = GetReportGenerator(wellId, begin, end, stepSeconds, format, (AsbCloudDbContext)db);
return generator.GetPagesCount();
}
public ReportPropertiesDto GetReportFileProperties(string reportName, string rootPath)
{
string path = Path.Combine(rootPath, reportName);
FileStream fs = new FileStream(path, FileMode.Open);
string contentType = Path.GetExtension(path);
string fileName = Path.GetFileName(path);
return new ReportPropertiesDto {
Filestream = fs,
ContentType = contentType,
FileName = fileName
};
}
public DatesRangeDto GetReportsDatesRange(int wellId)
{
var telemetry = telemetryService.GetTelemetryByWellId(wellId);
@ -51,11 +64,11 @@ namespace AsbCloudInfrastructure.Services
return new DatesRangeDto { From = result.From, To = result.To };
}
private IReportGenerator GetReportGenerator(int wellId,DateTime begin, DateTime end, int stepSeconds, int format)
private IReportGenerator GetReportGenerator(int wellId, DateTime begin, DateTime end, int stepSeconds, int format, AsbCloudDbContext context)
{
var dataSource = new ReportDataSourcePgCloud((AsbCloudDbContext)db, wellId);
var dataSource = new ReportDataSourcePgCloud(context, wellId);
var generator = new PdfGenerator(dataSource);
generator.ReportDirectory = Path.Combine(RootPath, $"{wellId}");
generator.Begin = begin;
generator.End = end;
generator.Step = TimeSpan.FromSeconds(stepSeconds);

View File

@ -1,5 +1,4 @@
using System;
using System.Threading.Tasks;
using System.IO;
using Microsoft.AspNetCore.Mvc;
using AsbCloudApp.Data;
@ -35,15 +34,13 @@ namespace AsbCloudWebApi.Controllers
/// <param name="wellId">id скважины</param>
/// <param name="begin">дата начала интервала</param>
/// <param name="end">дата окончания интервала</param>
/// <param name="step">шаг интервала</param>
/// <param name="stepSeconds">шаг интервала</param>
/// <param name="format">формат отчета (0-PDF, 1-LASS)</param>
/// <returns>id фоновой задачи формирования отчета</returns>
[HttpPost]
[Route("{wellId}/report")]
[ProducesResponseType(typeof(string), (int)System.Net.HttpStatusCode.OK)]
// ЭТОТ МЕТОД ПОКА НЕ РЕАЛИЗОВАН
public async Task<IActionResult> CreateReportAsync(int wellId, int stepSeconds, int format, DateTime begin = default, DateTime end = default)
public IActionResult CreateReport(int wellId, int stepSeconds, int format, DateTime begin = default, DateTime end = default)
{
int? idCustomer = User.GetCustomerId();
@ -53,17 +50,9 @@ namespace AsbCloudWebApi.Controllers
if (!wellService.CheckWellOwnership((int)idCustomer, wellId))
return Forbid();
return await Task.Run(() =>
{
// создаем отчет. Это заготовка, пока еще не перенесена в сервис.
var id = reportService.CreateReport(wellId, stepSeconds, format, begin, end);
var taskId = Task.CurrentId;
if (taskId is null)
throw new NullReferenceException("Не удалось получить id задачи");
return Ok(taskId.ToString());
});
return Ok(id);
}
/// <summary>
@ -86,14 +75,12 @@ namespace AsbCloudWebApi.Controllers
if (!wellService.CheckWellOwnership((int)idCustomer, wellId))
return Forbid();
var options = reportService.GetReportFileProperties(reportName, appEnvironment.ContentRootPath);
return File(options.Filestream, options.ContentType, options.FileName);
// TODO: словарь content typoв
return PhysicalFile(Path.Combine(reportService.RootPath, $"{wellId}", reportName), "application/pdf", reportName);
}
catch (FileNotFoundException ex)
{
return NotFound("Файл не найден");
return NotFound($"Файл не найден. Текст ошибки: {ex.Message}");
}
}
@ -103,7 +90,7 @@ namespace AsbCloudWebApi.Controllers
/// <param name="wellId">id скважины</param>
/// <param name="begin">дата начала интервала</param>
/// <param name="end">дата окончания интервала</param>
/// <param name="step">шаг интервала</param>
/// <param name="stepSeconds">шаг интервала</param>
/// <param name="format">формат отчета (0-PDF, 1-LASS)</param>
/// <returns>прогнозируемое кол-во страниц отчета</returns>
[HttpGet]