using BlazorClient; using Microsoft.AspNetCore.SignalR; namespace UndoExample; public record TweetWithDelay(Guid TweetId, string Message) : ICommand; public record UndoTweet(Guid TweetId) : ICommand; public record TweetUndone(Guid TweetId) : IEvent; public class UndoTweetState : ContainSagaData { public Guid TweetId { get; set; } public string Message { get; set; } } public class TweetUndoTimeout { } public class UndoTweetPolicy : Saga<UndoTweetState>, IAmStartedByMessages<TweetWithDelay>, IHandleMessages<UndoTweet>, IHandleTimeouts<TweetUndoTimeout> { private readonly ILogger<UndoTweetPolicy> _logger; public UndoTweetPolicy(ILogger<UndoTweetPolicy> logger) { _logger = logger; } protected override void ConfigureHowToFindSaga(SagaPropertyMapper<UndoTweetState> mapper) { mapper.MapSaga(saga => saga.TweetId) .ToMessage<TweetWithDelay>(x => x.TweetId) .ToMessage<UndoTweet>(x => x.TweetId); } public async Task Handle(TweetWithDelay message, IMessageHandlerContext context) { _logger.LogInformation($"Delayed Tweet {message.TweetId}"); Data.Message = message.Message; await RequestTimeout(context, TimeSpan.FromSeconds(10), new TweetUndoTimeout()); } public async Task Handle(UndoTweet message, IMessageHandlerContext context) { _logger.LogInformation($"Undo Tweet {message.TweetId}"); await context.Publish(new TweetUndone(message.TweetId)); MarkAsComplete(); } public async Task Timeout(TweetUndoTimeout state, IMessageHandlerContext context) { var tweet = new Tweet(Data.TweetId, Data.Message); await context.Send(tweet); MarkAsComplete(); } } public class UndoSignalRHandler : IHandleMessages<TweetUndone> { private readonly IHubContext<TweetHub> _hubContext; public UndoSignalRHandler(IHubContext<TweetHub> hubContext) { _hubContext = hubContext; } public async Task Handle(TweetUndone message, IMessageHandlerContext context) { await _hubContext.Clients.All.SendAsync("undone", message.TweetId, context.CancellationToken); } }