Newer
Older
Undo / BlazorClient / Tweet / UndoPolicy.cs
@Derek Comartin Derek Comartin on 28 Mar 2023 2 KB Init
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);
    }
}