Skip to content

Commit 1ef8773

Browse files
committed
feat: Replace fixed delay with active projection readiness checks and timeout during startup.
1 parent 5717cab commit 1ef8773

1 file changed

Lines changed: 37 additions & 2 deletions

File tree

src/ApiService/BookStore.ApiService/Program.cs

Lines changed: 37 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
using BookStore.ApiService.Infrastructure;
22
using BookStore.ApiService.Infrastructure.Extensions;
3+
using BookStore.ApiService.Projections;
34
using Marten;
45
using Scalar.AspNetCore;
56

@@ -24,16 +25,50 @@
2425
{
2526
using var scope = app.Services.CreateScope();
2627
var store = scope.ServiceProvider.GetRequiredService<IDocumentStore>();
28+
var logger = scope.ServiceProvider.GetRequiredService<ILogger<Program>>();
2729

2830
// Apply schema to create PostgreSQL extensions (pg_trgm, unaccent)
2931
await store.Storage.ApplyAllConfiguredChangesToDatabaseAsync();
3032

3133
var seeder = new DatabaseSeeder(store);
3234
await seeder.SeedAsync();
3335

34-
// Give async projections time to process the seeded events
36+
// Wait for async projections to process the seeded events
3537
// In production, projections run continuously in the background
36-
await Task.Delay(TimeSpan.FromSeconds(2));
38+
await WaitForProjectionsAsync(store, logger);
39+
}
40+
41+
static async Task WaitForProjectionsAsync(IDocumentStore store, ILogger logger)
42+
{
43+
logger.LogInformation("Waiting for async projections to complete...");
44+
45+
var timeout = TimeSpan.FromSeconds(30);
46+
var checkInterval = TimeSpan.FromMilliseconds(100);
47+
var stopwatch = System.Diagnostics.Stopwatch.StartNew();
48+
49+
while (stopwatch.Elapsed < timeout)
50+
{
51+
await using var session = store.QuerySession();
52+
53+
// Check if projections have data by querying the projection tables
54+
var bookCount = await session.Query<BookSearchProjection>().CountAsync();
55+
var authorCount = await session.Query<AuthorProjection>().CountAsync();
56+
var categoryCount = await session.Query<CategoryProjection>().CountAsync();
57+
var publisherCount = await session.Query<PublisherProjection>().CountAsync();
58+
59+
// If all projections have data, we're ready
60+
if (bookCount > 0 && authorCount > 0 && categoryCount > 0 && publisherCount > 0)
61+
{
62+
logger.LogInformation(
63+
"All projections are ready: {BookCount} books, {AuthorCount} authors, {CategoryCount} categories, {PublisherCount} publishers",
64+
bookCount, authorCount, categoryCount, publisherCount);
65+
return;
66+
}
67+
68+
await Task.Delay(checkInterval);
69+
}
70+
71+
logger.LogWarning("Projection initialization timed out after {Timeout}s. Some projections may not be ready.", timeout.TotalSeconds);
3772
}
3873

3974
// Configure the HTTP request pipeline

0 commit comments

Comments
 (0)