Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

GitAuto: [FEATURE] Add Saga capability #581

Open
wants to merge 13 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Src/CrispyWaffle/Commands/CommandsConsumer.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System.Threading.Tasks;
using CrispyWaffle.Sagas;
using CrispyWaffle.Composition;
using CrispyWaffle.Log;

Expand Down
130 changes: 65 additions & 65 deletions Src/CrispyWaffle/Events/EventsConsumer.cs
Original file line number Diff line number Diff line change
@@ -1,65 +1,65 @@
using System.Threading.Tasks;
using CrispyWaffle.Composition;
using CrispyWaffle.Log;
namespace CrispyWaffle.Events;
/// <summary>
/// Provides methods to raise events and invoke their handlers.
/// This class supports both synchronous and asynchronous event handling.
/// </summary>
public static class EventsConsumer
{
/// <summary>
/// Raises the specified event synchronously and invokes all registered handlers for the event.
/// Handlers are resolved from the service locator and invoked in the order they are registered.
/// </summary>
/// <typeparam name="TEvent">The type of the event to raise. The event must implement <see cref="IEvent"/>.</typeparam>
/// <param name="event">The event to raise. It will be passed to all the registered handlers.</param>
/// <remarks>
/// This method resolves all synchronous event handlers for the specified event type
/// and calls their <see cref="IEventHandler{TEvent}.Handle(TEvent)"/> method.
/// </remarks>
public static void Raise<TEvent>(TEvent @event)
where TEvent : IEvent
{
var handlers = ServiceLocator.ResolveAll<IEventHandler<TEvent>>();
foreach (var handler in handlers)
{
LogConsumer.Trace(
$"Calling {handler.GetType().FullName} for event {@event.GetType().FullName}"
);
handler.Handle(@event);
}
}
/// <summary>
/// Raises the specified event asynchronously and invokes all registered asynchronous handlers for the event.
/// Handlers are resolved from the service locator and invoked in the order they are registered.
/// </summary>
/// <typeparam name="TEvent">The type of the event to raise. The event must implement <see cref="IEvent"/>.</typeparam>
/// <param name="event">The event to raise. It will be passed to all the registered handlers asynchronously.</param>
/// <returns>A task that represents the asynchronous operation.</returns>
/// <remarks>
/// This method resolves all asynchronous event handlers for the specified event type
/// and calls their <see cref="IEventHandlerAsync{TEvent}.HandleAsync(TEvent)"/> method.
/// The event handlers will be executed asynchronously in parallel.
/// </remarks>
public static async Task RaiseAsync<TEvent>(TEvent @event)
where TEvent : IEvent
{
await Task.Run(() =>
{
var handlers = ServiceLocator.ResolveAll<IEventHandlerAsync<TEvent>>();
foreach (var handler in handlers)
{
LogConsumer.Trace(
$"Calling {handler.GetType().FullName} for event {@event.GetType().FullName}"
);
handler.HandleAsync(@event);
}
});
}
}
using System.Threading.Tasks;
using CrispyWaffle.Composition;
using CrispyWaffle.Log;

namespace CrispyWaffle.Events;

/// <summary>
/// Provides methods to raise events and invoke their handlers.
/// This class supports both synchronous and asynchronous event handling.
/// </summary>
public static class EventsConsumer
{
/// <summary>
/// Raises the specified event synchronously and invokes all registered handlers for the event.
/// Handlers are resolved from the service locator and invoked in the order they are registered.
/// </summary>
/// <typeparam name="TEvent">The type of the event to raise. The event must implement <see cref="IEvent"/>.</typeparam>
/// <param name="event">The event to raise. It will be passed to all the registered handlers.</param>
/// <remarks>
/// This method resolves all synchronous event handlers for the specified event type
/// and calls their <see cref="IEventHandler{TEvent}.Handle(TEvent)"/> method.
/// </remarks>
public static void Raise<TEvent>(TEvent @event)
where TEvent : IEvent
{
var handlers = ServiceLocator.ResolveAll<IEventHandler<TEvent>>();

foreach (var handler in handlers)
{
LogConsumer.Trace(
$"Calling {handler.GetType().FullName} for event {@event.GetType().FullName}"
);

handler.Handle(@event);
}
}

/// <summary>
/// Raises the specified event asynchronously and invokes all registered asynchronous handlers for the event.
/// Handlers are resolved from the service locator and invoked in the order they are registered.
/// </summary>
/// <typeparam name="TEvent">The type of the event to raise. The event must implement <see cref="IEvent"/>.</typeparam>
/// <param name="event">The event to raise. It will be passed to all the registered handlers asynchronously.</param>
/// <returns>A task that represents the asynchronous operation.</returns>
/// <remarks>
/// This method resolves all asynchronous event handlers for the specified event type
/// and calls their <see cref="IEventHandlerAsync{TEvent}.HandleAsync(TEvent)"/> method.
/// The event handlers will be executed asynchronously in parallel.
/// </remarks>
public static async Task RaiseAsync<TEvent>(TEvent @event)
where TEvent : IEvent
{
await Task.Run(() =>
{
var handlers = ServiceLocator.ResolveAll<IEventHandlerAsync<TEvent>>();
foreach (var handler in handlers)
{
LogConsumer.Trace(
$"Calling {handler.GetType().FullName} for event {@event.GetType().FullName}"
);
handler.HandleAsync(@event);
}
});
}
}
23 changes: 23 additions & 0 deletions Src/CrispyWaffle/Sagas/GenericSagaHandler.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
namespace CrispyWaffle.Sagas;

public abstract class GenericSagaHandler : ISagaHandler
{
public abstract void Handle<T>(T message);

public abstract void HandleTimeout<T>(T message);

protected void StartSaga<T>(T message)
{
// Logic to start a saga
}

protected void UpdateSagaState<T>(T message)
{
// Logic to update saga state
}

protected void CompleteSaga()
{
// Logic to complete a saga
}
}
6 changes: 6 additions & 0 deletions Src/CrispyWaffle/Sagas/ISaga.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
namespace CrispyWaffle.Sagas;

public interface ISaga
{
Guid SagaId { get; }

Check failure on line 5 in Src/CrispyWaffle/Sagas/ISaga.cs

View workflow job for this annotation

GitHub Actions / Deep Source Coverage report

The type or namespace name 'Guid' could not be found (are you missing a using directive or an assembly reference?)

Check failure on line 5 in Src/CrispyWaffle/Sagas/ISaga.cs

View workflow job for this annotation

GitHub Actions / Deep Source Coverage report

The type or namespace name 'Guid' could not be found (are you missing a using directive or an assembly reference?)

Check failure on line 5 in Src/CrispyWaffle/Sagas/ISaga.cs

View workflow job for this annotation

GitHub Actions / Deep Source Coverage report

The type or namespace name 'Guid' could not be found (are you missing a using directive or an assembly reference?)
}
6 changes: 6 additions & 0 deletions Src/CrispyWaffle/Sagas/ISagaData.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
namespace CrispyWaffle.Sagas;

public interface ISagaData
{
Guid SagaId { get; set; }

Check failure on line 5 in Src/CrispyWaffle/Sagas/ISagaData.cs

View workflow job for this annotation

GitHub Actions / Deep Source Coverage report

The type or namespace name 'Guid' could not be found (are you missing a using directive or an assembly reference?)
}
7 changes: 7 additions & 0 deletions Src/CrispyWaffle/Sagas/ISagaHandler.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
namespace CrispyWaffle.Sagas;

public interface ISagaHandler
{
void Handle<T>(T message);
void HandleTimeout<T>(T message);
}
15 changes: 15 additions & 0 deletions Src/CrispyWaffle/Sagas/SagaData.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
namespace CrispyWaffle.Sagas;

public class SagaData : ISagaData
{
public Guid SagaId { get; set; }

Check failure on line 5 in Src/CrispyWaffle/Sagas/SagaData.cs

View workflow job for this annotation

GitHub Actions / Deep Source Coverage report

The type or namespace name 'Guid' could not be found (are you missing a using directive or an assembly reference?)
public string State { get; set; }
public DateTime CreatedAt { get; set; }

Check failure on line 7 in Src/CrispyWaffle/Sagas/SagaData.cs

View workflow job for this annotation

GitHub Actions / Deep Source Coverage report

The type or namespace name 'DateTime' could not be found (are you missing a using directive or an assembly reference?)
// Additional properties as needed

public SagaData()
{
SagaId = Guid.NewGuid();
CreatedAt = DateTime.UtcNow;
}
}
22 changes: 22 additions & 0 deletions Src/CrispyWaffle/Sagas/SagaRepository.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
namespace CrispyWaffle.Sagas;

public class SagaRepository
{
private readonly Dictionary<Guid, SagaData> _storage = new Dictionary<Guid, SagaData>();

Check failure on line 5 in Src/CrispyWaffle/Sagas/SagaRepository.cs

View workflow job for this annotation

GitHub Actions / Deep Source Coverage report

The type or namespace name 'Dictionary<,>' could not be found (are you missing a using directive or an assembly reference?)

Check failure on line 5 in Src/CrispyWaffle/Sagas/SagaRepository.cs

View workflow job for this annotation

GitHub Actions / Deep Source Coverage report

The type or namespace name 'Guid' could not be found (are you missing a using directive or an assembly reference?)

public void Save(SagaData sagaData)
{
_storage[sagaData.SagaId] = sagaData;
}

public SagaData Load(Guid sagaId)

Check failure on line 12 in Src/CrispyWaffle/Sagas/SagaRepository.cs

View workflow job for this annotation

GitHub Actions / Deep Source Coverage report

The type or namespace name 'Guid' could not be found (are you missing a using directive or an assembly reference?)
{
_storage.TryGetValue(sagaId, out var sagaData);
return sagaData;
}

public void Delete(Guid sagaId)

Check failure on line 18 in Src/CrispyWaffle/Sagas/SagaRepository.cs

View workflow job for this annotation

GitHub Actions / Deep Source Coverage report

The type or namespace name 'Guid' could not be found (are you missing a using directive or an assembly reference?)
{
_storage.Remove(sagaId);
}
}
Loading