Created
April 12, 2024 11:27
-
-
Save flew2bits/051c67e0c18ef513f3f915c177ed993d to your computer and use it in GitHub Desktop.
FanOut sample for Dates
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using Marten; | |
using Marten.Events.Projections; | |
using Microsoft.Extensions.Configuration; | |
using Microsoft.Extensions.DependencyInjection; | |
using Microsoft.Extensions.Hosting; | |
var builder = Host.CreateApplicationBuilder(); | |
builder.Services.AddMarten(opt => { | |
opt.Connection(builder.Configuration.GetConnectionString("Marten") ?? "Host=localhost; Port=5433; User Id=postgres; Password=pgsql"); | |
opt.Projections.Add<WorkByDayProjection>(ProjectionLifecycle.Inline); | |
}).UseLightweightSessions(); | |
builder.Services.AddHostedService<Runner>(); | |
var app = builder.Build(); | |
await app.RunAsync(); | |
public class Runner : BackgroundService | |
{ | |
private readonly IDocumentSession _session; | |
private readonly IHostApplicationLifetime _lifetime; | |
public Runner(IDocumentSession session, IHostApplicationLifetime lifetime) | |
{ | |
_session = session; | |
_lifetime = lifetime; | |
} | |
protected override Task ExecuteAsync(CancellationToken stoppingToken) | |
=> Task.Run(async () => | |
{ | |
var assignmentId = Guid.NewGuid(); | |
var workerId = Guid.NewGuid(); | |
var today = DateOnly.FromDateTime(DateTime.Today); | |
var tomorrow = today.AddDays(1); | |
var oneWeekFromToday = today.AddDays(7); | |
Console.Write($"{today} {oneWeekFromToday}"); | |
_session.Events.Append(assignmentId, new WorkerAssigned(assignmentId, workerId, today, oneWeekFromToday)); | |
_session.Events.Append(assignmentId, new WorkCompleted(assignmentId, today, "Work completed today")); | |
_session.Events.Append(assignmentId, new WorkCompleted(assignmentId, today, "More work completed today")); | |
_session.Events.Append(assignmentId, new WorkCompleted(assignmentId, tomorrow, "Work completed tomorrow")); | |
await _session.SaveChangesAsync(stoppingToken); | |
_lifetime.StopApplication(); | |
}, stoppingToken); | |
} | |
public record WorkerAssigned(Guid AssignmentId, Guid WorkerId, DateOnly Start, DateOnly End); | |
public record WorkCompleted(Guid AssignmentId, DateOnly Date, string DescriptionOfWork); | |
public record WorkByDay(string Id, Guid AssignmentId, Guid WorkerId, DateOnly Date, string[] WorkCompleted); | |
public record WorkerAssignedForDay(Guid AssignmentId, Guid WorkerId, DateOnly Date); | |
public class WorkByDayProjection : MultiStreamProjection<WorkByDay, string> | |
{ | |
public WorkByDayProjection() | |
{ | |
FanOut<WorkerAssigned, WorkerAssignedForDay>(e => Enumerable.Range(0, e.End.DayNumber - e.Start.DayNumber + 1) | |
.Select(d => new WorkerAssignedForDay(e.AssignmentId, e.WorkerId, e.Start.AddDays(d))), FanoutMode.BeforeGrouping); | |
Identity<WorkerAssignedForDay>(e => IdForEvent(e.AssignmentId, e.Date)); | |
Identity<WorkCompleted>(e => IdForEvent(e.AssignmentId, e.Date)); | |
IncludeType<WorkerAssigned>(); | |
} | |
private static string IdForEvent(Guid assignmentId, DateOnly date) => $"{assignmentId:N}:{date:yyyyMMdd}"; | |
public static WorkByDay Create(WorkerAssignedForDay evt) => new(IdForEvent(evt.AssignmentId, evt.Date), | |
evt.AssignmentId, evt.WorkerId, evt.Date, Array.Empty<string>()); | |
public static WorkByDay Apply(WorkCompleted evt, WorkByDay view) => | |
view with { WorkCompleted = view.WorkCompleted.Append(evt.DescriptionOfWork).ToArray() }; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment