mirror of https://github.com/ErsatzTV/ErsatzTV.git
Browse Source
* unblock startup, show database initialization message * wait on search index to be ready (rebuild) * clean logging and fake delaypull/1326/head
22 changed files with 446 additions and 216 deletions
@ -0,0 +1,33 @@ |
|||||||
|
namespace ErsatzTV.Core; |
||||||
|
|
||||||
|
public class SystemStartup |
||||||
|
{ |
||||||
|
private readonly SemaphoreSlim _databaseStartup = new(0, 100); |
||||||
|
private readonly SemaphoreSlim _searchIndexStartup = new(0, 100); |
||||||
|
|
||||||
|
public event EventHandler OnDatabaseReady; |
||||||
|
public event EventHandler OnSearchIndexReady; |
||||||
|
|
||||||
|
public bool IsDatabaseReady { get; private set; } |
||||||
|
public bool IsSearchIndexReady { get; private set; } |
||||||
|
|
||||||
|
public async Task WaitForDatabase(CancellationToken cancellationToken) => |
||||||
|
await _databaseStartup.WaitAsync(cancellationToken); |
||||||
|
|
||||||
|
public async Task WaitForSearchIndex(CancellationToken cancellationToken) => |
||||||
|
await _searchIndexStartup.WaitAsync(cancellationToken); |
||||||
|
|
||||||
|
public void DatabaseIsReady() |
||||||
|
{ |
||||||
|
_databaseStartup.Release(100); |
||||||
|
IsDatabaseReady = true; |
||||||
|
OnDatabaseReady?.Invoke(this, EventArgs.Empty); |
||||||
|
} |
||||||
|
|
||||||
|
public void SearchIndexIsReady() |
||||||
|
{ |
||||||
|
_searchIndexStartup.Release(100); |
||||||
|
IsSearchIndexReady = true; |
||||||
|
OnSearchIndexReady?.Invoke(this, EventArgs.Empty); |
||||||
|
} |
||||||
|
} |
||||||
@ -1,21 +1,32 @@ |
|||||||
using ErsatzTV.Application.Search; |
using ErsatzTV.Application.Search; |
||||||
|
using ErsatzTV.Core; |
||||||
using MediatR; |
using MediatR; |
||||||
|
|
||||||
namespace ErsatzTV.Services.RunOnce; |
namespace ErsatzTV.Services.RunOnce; |
||||||
|
|
||||||
public class RebuildSearchIndexService : IHostedService |
public class RebuildSearchIndexService : BackgroundService |
||||||
{ |
{ |
||||||
private readonly IServiceScopeFactory _serviceScopeFactory; |
private readonly IServiceScopeFactory _serviceScopeFactory; |
||||||
|
private readonly SystemStartup _systemStartup; |
||||||
|
|
||||||
public RebuildSearchIndexService(IServiceScopeFactory serviceScopeFactory) => |
public RebuildSearchIndexService(IServiceScopeFactory serviceScopeFactory, SystemStartup systemStartup) |
||||||
|
{ |
||||||
_serviceScopeFactory = serviceScopeFactory; |
_serviceScopeFactory = serviceScopeFactory; |
||||||
|
_systemStartup = systemStartup; |
||||||
|
} |
||||||
|
|
||||||
|
protected override async Task ExecuteAsync(CancellationToken cancellationToken) |
||||||
|
{ |
||||||
|
await Task.Yield(); |
||||||
|
|
||||||
public async Task StartAsync(CancellationToken cancellationToken) |
await _systemStartup.WaitForDatabase(cancellationToken); |
||||||
|
if (cancellationToken.IsCancellationRequested) |
||||||
{ |
{ |
||||||
|
return; |
||||||
|
} |
||||||
|
|
||||||
using IServiceScope scope = _serviceScopeFactory.CreateScope(); |
using IServiceScope scope = _serviceScopeFactory.CreateScope(); |
||||||
IMediator mediator = scope.ServiceProvider.GetRequiredService<IMediator>(); |
IMediator mediator = scope.ServiceProvider.GetRequiredService<IMediator>(); |
||||||
await mediator.Send(new RebuildSearchIndex(), cancellationToken); |
await mediator.Send(new RebuildSearchIndex(), cancellationToken); |
||||||
} |
} |
||||||
|
|
||||||
public Task StopAsync(CancellationToken cancellationToken) => Task.CompletedTask; |
|
||||||
} |
} |
||||||
|
|||||||
Loading…
Reference in new issue