feat: добавил инвалидацию кэшей плагинов
Create and publish a Docker image / Publish image (push) Successful in 1m53s
Create and publish a Docker image / Publish image (push) Successful in 1m53s
This commit is contained in:
1 parent
01bab77900
commit
c590a8a6c7
5 files changed
+51
-4
No files matched your search
@@ -10,4 +10,8 @@ public interface IPlugin
|
||||
|
||||
// Регистрация маршрутов (Minimal API) плагина после Build()
|
||||
void MapEndpoints(IEndpointRouteBuilder endpoints);
|
||||
}
|
||||
|
||||
// Инвалидация или обновление внутренних кэшей плагина.
|
||||
Task InvalidateCacheAsync(IServiceProvider serviceProvider, CancellationToken cancellationToken) =>
|
||||
Task.CompletedTask;
|
||||
}
|
||||
@@ -89,6 +89,7 @@
|
||||
- загружает большой список сотрудников;
|
||||
- группирует записи по ФИО;
|
||||
- сохраняет результат на диск;
|
||||
- после успешного обновления предлагает всем плагинам инвалидировать свои кэши;
|
||||
- повторяет попытки при временных сбоях.
|
||||
|
||||
Если сервис ещё не инициализирован, `GET /api/schedule/searchemployee` возвращает `503`.
|
||||
@@ -131,7 +132,11 @@ Quartz job [UpdateJwtJob](/home/serega404/Рабочий стол/SfeduSchedule/
|
||||
На старте хост ищет все `*.plugin.dll` внутри `data/Plugins` и загружает найденные сборки как плагины. Плагин должен реализовывать интерфейс [IPlugin](/home/serega404/Рабочий стол/SfeduSchedule/ModeusSchedule.Abstractions/IPlugin.cs), чтобы:
|
||||
|
||||
- зарегистрировать свои сервисы в DI через `ConfigureServices`;
|
||||
- добавить minimal API маршруты через `MapEndpoints`.
|
||||
- добавить minimal API маршруты через `MapEndpoints`;
|
||||
- опционально обновить или очистить свои кэши через `InvalidateCacheAsync`.
|
||||
|
||||
`InvalidateCacheAsync` имеет default-реализацию, поэтому плагины, собранные до добавления этого метода,
|
||||
продолжают загружаться. Ошибка инвалидации одного плагина логируется и не мешает вызвать остальные.
|
||||
|
||||
MVC-контроллеры из плагинов тоже подключаются автоматически через `ApplicationPart`.
|
||||
|
||||
|
||||
@@ -12,7 +12,8 @@ namespace SfeduSchedule.Jobs;
|
||||
public class UpdateEmployeesJob(
|
||||
ILogger<UpdateEmployeesJob> logger,
|
||||
ModeusEmployeeService employeeService,
|
||||
ModeusService modeusService) : IJob
|
||||
ModeusService modeusService,
|
||||
PluginCacheInvalidator pluginCacheInvalidator) : IJob
|
||||
{
|
||||
private const int MaxAttempts = 5; // Максимальное число попыток
|
||||
private const int DelaySeconds = 50; // Задержка между попытками в секундах
|
||||
@@ -47,6 +48,7 @@ public class UpdateEmployeesJob(
|
||||
|
||||
await employeeService.SetEmployees(employees);
|
||||
logger.LogInformationHere($"Получено {employees.Count} сотрудников из Modeus.");
|
||||
await pluginCacheInvalidator.InvalidateAsync(jobContext.CancellationToken);
|
||||
return;
|
||||
}
|
||||
catch (OperationCanceledException ex)
|
||||
@@ -75,4 +77,4 @@ public class UpdateEmployeesJob(
|
||||
await Task.Delay(TimeSpan.FromSeconds(DelaySeconds), jobContext.CancellationToken);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -9,6 +9,7 @@ using Microsoft.AspNetCore.HttpOverrides;
|
||||
using Microsoft.AspNetCore.Mvc.ApplicationParts;
|
||||
using Microsoft.Identity.Web;
|
||||
using Microsoft.OpenApi.Models;
|
||||
using ModeusSchedule.Abstractions;
|
||||
using Prometheus;
|
||||
using Quartz;
|
||||
using Quartz.Listener;
|
||||
@@ -133,11 +134,14 @@ foreach (var p in loadedPlugins)
|
||||
|
||||
// DI из плагина
|
||||
p.Instance.ConfigureServices(builder.Services);
|
||||
builder.Services.AddSingleton<IPlugin>(p.Instance);
|
||||
|
||||
// Подключаем контроллеры плагина
|
||||
mvcBuilder.PartManager.ApplicationParts.Add(new AssemblyPart(p.Assembly));
|
||||
}
|
||||
|
||||
builder.Services.AddSingleton<PluginCacheInvalidator>();
|
||||
|
||||
var updateJwtJob = new JobKey("UpdateJWTJob");
|
||||
|
||||
builder.Services.AddQuartz(q =>
|
||||
|
||||
@@ -0,0 +1,32 @@
|
||||
using ModeusSchedule.Abstractions;
|
||||
|
||||
namespace SfeduSchedule.Services;
|
||||
|
||||
public sealed class PluginCacheInvalidator(
|
||||
IEnumerable<IPlugin> plugins,
|
||||
IServiceScopeFactory scopeFactory,
|
||||
ILogger<PluginCacheInvalidator> logger)
|
||||
{
|
||||
public async Task InvalidateAsync(CancellationToken cancellationToken)
|
||||
{
|
||||
foreach (var plugin in plugins)
|
||||
{
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
|
||||
try
|
||||
{
|
||||
await using var scope = scopeFactory.CreateAsyncScope();
|
||||
await plugin.InvalidateCacheAsync(scope.ServiceProvider, cancellationToken);
|
||||
logger.LogInformation("Кэш плагина {PluginName} инвалидирован", plugin.Name);
|
||||
}
|
||||
catch (OperationCanceledException) when (cancellationToken.IsCancellationRequested)
|
||||
{
|
||||
throw;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
logger.LogError(ex, "Не удалось инвалидировать кэш плагина {PluginName}", plugin.Name);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user