-
-
Notifications
You must be signed in to change notification settings - Fork 522
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
31cdcf2
commit 3496f86
Showing
64 changed files
with
4,671 additions
and
81 deletions.
There are no files selected for viewing
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
33 changes: 33 additions & 0 deletions
33
Workshops/EventDrivenArchitecture/04-Idempotency/Core/CommandBus.cs
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
using System.Collections.Concurrent; | ||
|
||
namespace Idempotency.Core; | ||
|
||
public class CommandBus | ||
{ | ||
public async ValueTask Send(object[] commands, CancellationToken ct) | ||
{ | ||
foreach (var command in commands) | ||
{ | ||
if (!commandHandlers.TryGetValue(command.GetType(), out var handler)) | ||
continue; | ||
|
||
foreach (var middleware in middlewares) | ||
middleware(command); | ||
|
||
await handler(command, ct); | ||
} | ||
} | ||
|
||
public CommandBus Handle<T>(Func<T, CancellationToken, ValueTask> eventHandler) | ||
{ | ||
commandHandlers[typeof(T)] = (command, ct) => eventHandler((T)command, ct); | ||
|
||
return this; | ||
} | ||
|
||
public void Use(Action<object> middleware) => | ||
middlewares.Add(middleware); | ||
|
||
private readonly ConcurrentDictionary<Type, Func<object, CancellationToken, ValueTask>> commandHandlers = new(); | ||
private readonly List<Action<object>> middlewares = []; | ||
} |
32 changes: 32 additions & 0 deletions
32
Workshops/EventDrivenArchitecture/04-Idempotency/Core/Database.cs
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
using System.Text.Json; | ||
|
||
namespace Idempotency.Core; | ||
|
||
public class Database | ||
{ | ||
private readonly Dictionary<string, object> storage = new(); | ||
|
||
public ValueTask Store<T>(Guid id, T obj, CancellationToken _) where T : class | ||
{ | ||
storage[GetId<T>(id)] = obj; | ||
|
||
return ValueTask.CompletedTask; | ||
} | ||
|
||
public ValueTask Delete<T>(Guid id, CancellationToken _) | ||
{ | ||
storage.Remove(GetId<T>(id)); | ||
return ValueTask.CompletedTask; | ||
} | ||
|
||
public ValueTask<T?> Get<T>(Guid id, CancellationToken _) where T : class => | ||
ValueTask.FromResult( | ||
storage.TryGetValue(GetId<T>(id), out var result) | ||
? | ||
// Clone to simulate getting new instance on loading | ||
JsonSerializer.Deserialize<T>(JsonSerializer.Serialize((T)result)) | ||
: null | ||
); | ||
|
||
private static string GetId<T>(Guid id) => $"{typeof(T).Name}-{id}"; | ||
} |
44 changes: 44 additions & 0 deletions
44
Workshops/EventDrivenArchitecture/04-Idempotency/Core/EventBus.cs
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,44 @@ | ||
using System.Collections.Concurrent; | ||
|
||
namespace Idempotency.Core; | ||
|
||
public class EventBus | ||
{ | ||
public async ValueTask Publish(object[] events, CancellationToken ct) | ||
{ | ||
foreach (var @event in events) | ||
{ | ||
foreach (var middleware in middlewares) | ||
middleware(@event); | ||
|
||
if (!eventHandlers.TryGetValue(@event.GetType(), out var handlers)) | ||
continue; | ||
|
||
foreach (var handler in handlers) | ||
await handler(@event, ct); | ||
} | ||
} | ||
|
||
public EventBus Subscribe<T>(Func<T, CancellationToken, ValueTask> eventHandler) | ||
{ | ||
Func<object, CancellationToken, ValueTask> handler = (@event, ct) => eventHandler((T)@event, ct); | ||
|
||
eventHandlers.AddOrUpdate( | ||
typeof(T), | ||
_ => [handler], | ||
(_, handlers) => | ||
{ | ||
handlers.Add(handler); | ||
return handlers; | ||
} | ||
); | ||
|
||
return this; | ||
} | ||
|
||
public void Use(Action<object> middleware) => | ||
middlewares.Add(middleware); | ||
|
||
private readonly ConcurrentDictionary<Type, List<Func<object, CancellationToken, ValueTask>>> eventHandlers = new(); | ||
private readonly List<Action<object>> middlewares = []; | ||
} |
26 changes: 26 additions & 0 deletions
26
Workshops/EventDrivenArchitecture/04-Idempotency/Core/MessageCatcher.cs
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
using FluentAssertions; | ||
|
||
namespace Idempotency.Core; | ||
|
||
public class MessageCatcher | ||
{ | ||
public List<object> Published { get; } = []; | ||
|
||
public void Catch(object message) => | ||
Published.Add(message); | ||
|
||
public void Reset() => Published.Clear(); | ||
|
||
public void ShouldNotReceiveAnyMessage() => | ||
Published.Should().BeEmpty(); | ||
|
||
public void ShouldReceiveSingleMessage<T>(T message) | ||
{ | ||
Published.Should().HaveCount(1); | ||
Published.OfType<T>().Should().HaveCount(1); | ||
Published.Single().Should().Be(message); | ||
} | ||
|
||
public void ShouldReceiveMessages(object[] messages) => | ||
Published.Should().BeEquivalentTo(messages); | ||
} |
Oops, something went wrong.