Skip to content

Commit

Permalink
Merge pull request #3 from erikshafer/project_03_advanced_esdb
Browse files Browse the repository at this point in the history
Project 03: Beginner++ ESDB
  • Loading branch information
erikshafer authored May 23, 2024
2 parents 3ec281c + 5f8f59c commit 960ad6c
Show file tree
Hide file tree
Showing 21 changed files with 326 additions and 56 deletions.
1 change: 0 additions & 1 deletion StudentEnrollment01.InMemory/Events/Event.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,5 @@ namespace StudentEnrollment01.InMemory.Events;
public abstract class Event
{
public abstract Guid StreamId { get; }

public DateTime CreatedAtUtc { get; set; }
}
2 changes: 1 addition & 1 deletion StudentEnrollment01.InMemory/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,6 @@
var student = inMemoryDb.GetStudent(id);

Console.WriteLine(
"StudentId: {0} | FullName: {1} | Email: {2} | DOB: {3} | CreatedAtUtc: {4}",
"StudentId: {0} | FullName: {1} | Email: {2} | DateOfBirth: {3} | CreatedAtUtc: {4}",
student!.Id, student.FullName, student.Email, student.DateOfBirth, student.CreatedAtUtc);
Console.WriteLine();
2 changes: 1 addition & 1 deletion StudentEnrollment01.InMemory/Student.cs
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,6 @@ private void Apply(StudentEnrolled @event)
private void Apply(StudentUnEnrolled @event)
{
if (EnrolledCourses.Contains(@event.CourseName))
EnrolledCourses.Add(@event.CourseName);
EnrolledCourses.Remove(@event.CourseName);
}
}
4 changes: 2 additions & 2 deletions StudentEnrollment02.Esdb/Events/Event.cs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
namespace StudentEnrollment02.Esdb.Events;

public abstract record Event
public abstract class Event
{
public string Id { get; init; } = default!;
public required string StudentId { get; set; }
public DateTime CreatedAtUtc { get; set; }
}
3 changes: 1 addition & 2 deletions StudentEnrollment02.Esdb/Events/StudentCreated.cs
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
namespace StudentEnrollment02.Esdb.Events;

public record StudentCreated : Event
public class StudentCreated : Event
{
public required string FullName { get; init; }
public required string Email { get; init; }
public required DateTime DateOfBirth { get; init; }
public DateTime CreatedAtUtc { get; init; }
}
3 changes: 1 addition & 2 deletions StudentEnrollment02.Esdb/Events/StudentEnrolled.cs
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
namespace StudentEnrollment02.Esdb.Events;

public record StudentEnrolled : Event
public class StudentEnrolled : Event
{
public required string CourseName { get; init; }
public DateTime EnrolledAtUtc { get; init; }
}
7 changes: 7 additions & 0 deletions StudentEnrollment02.Esdb/Events/StudentUpdated.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
namespace StudentEnrollment02.Esdb.Events;

public class StudentUpdated : Event
{
public required string FullName { get; init; }
public required string Email { get; init; }
}
6 changes: 6 additions & 0 deletions StudentEnrollment02.Esdb/Events/StudentWithdrew.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
namespace StudentEnrollment02.Esdb.Events;

public class StudentWithdrew : Event
{
public required string CourseName { get; init; }
}
51 changes: 14 additions & 37 deletions StudentEnrollment02.Esdb/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,21 +3,14 @@
using EventStore.Client;
using StudentEnrollment02.Esdb.Events;

// Register events to a singleton for ease-of-reference
EventTypeMapper.Instance.ToName(typeof(StudentCreated));
EventTypeMapper.Instance.ToName(typeof(StudentEnrolled));
EventTypeMapper.Instance.ToName(typeof(StudentWithdrawn));
EventTypeMapper.Instance.ToName(typeof(StudentEmailChanged));

var id = Guid.Parse("a662d446-4920-415e-8c2a-0dd4a6c58908");
var streamId = $"student-{id}";
var streamId = Guid.Parse("a662d446-4920-415e-8c2a-0dd4a6c58908").ToString();

var created = new EventData(
Uuid.NewUuid(),
"StudentCreated",
JsonSerializer.SerializeToUtf8Bytes(new StudentCreated
{
Id = streamId,
StudentId = streamId,
FullName = "Erik Shafer",
Email = "erik.shafer@eventstore.com",
DateOfBirth = new DateTime(1987, 1, 1),
Expand All @@ -30,46 +23,47 @@
"StudentEnrolled",
JsonSerializer.SerializeToUtf8Bytes(new StudentEnrolled
{
Id = streamId,
StudentId = streamId,
CourseName = "From Zero to Hero: REST APis in .NET",
EnrolledAtUtc = DateTime.UtcNow
CreatedAtUtc = DateTime.UtcNow
})
);

var emailChanged = new EventData(
Uuid.NewUuid(),
"StudentEmailChanged",
JsonSerializer.SerializeToUtf8Bytes(new StudentEmailChanged
JsonSerializer.SerializeToUtf8Bytes(new StudentUpdated
{
Id = streamId,
StudentId = streamId,
FullName = "Erik Shafer",
Email = "erik.shafer.changed.his.email@eventstore.com",
ChangedAtUtc = DateTime.UtcNow
CreatedAtUtc = DateTime.UtcNow
})
);

// Our EventStoreDB (ESDB)
const string connectionString = "esdb://admin:changeit@localhost:2113?tls=false&tlsVerifyCert=false";
var settings = EventStoreClientSettings.Create(connectionString);
var client = new EventStoreClient(settings);

// Append to ESDB
await client.AppendToStreamAsync(
streamId,
StreamState.Any,
new[] { created, enrolled, emailChanged },
cancellationToken: default
);

// Read from ESDB
var readStreamResult = client.ReadStreamAsync(
var streamResult = client.ReadStreamAsync(
Direction.Forwards,
streamId,
StreamPosition.Start,
cancellationToken: default
);
var eventStream = await readStreamResult.ToListAsync();

// Write out the events from the stream
if (await streamResult.ReadState is ReadState.StreamNotFound)
return;

var eventStream = await streamResult.ToListAsync();

Console.WriteLine("Events from selected stream: ");
foreach (var resolved in eventStream)
{
Expand All @@ -80,28 +74,11 @@ await client.AppendToStreamAsync(
Console.WriteLine("");
}

// Write out all the courses the student enrolled in
var enrolledCourses = eventStream
.Where(re => re.Event.EventType == "StudentEnrolled")
.Select(re => JsonSerializer.Deserialize<StudentEnrolled>(re.Event.Data.ToArray()))
.Select(se => se!.CourseName)
.ToList();
Console.WriteLine("Courses enrolled in: ");
enrolledCourses.ForEach(ec => Console.WriteLine($"\t- {ec}"));
Console.WriteLine("");

// Write out using the mapper
Console.WriteLine("Deserialized events:");
foreach (var resolved in eventStream)
{
var eventType = EventTypeMapper.Instance.ToType(resolved.Event.EventType);

if (eventType == null)
break;

var deserializedEvent = JsonSerializer.Deserialize(Encoding.UTF8.GetString(resolved.Event.Data.Span), eventType);

Console.WriteLine($"\t{deserializedEvent}");
}

Console.WriteLine("");
12 changes: 6 additions & 6 deletions StudentEnrollment02.Esdb/Student.cs
Original file line number Diff line number Diff line change
Expand Up @@ -18,27 +18,27 @@ public void Apply(Event @event)
case StudentCreated created:
Apply(created);
break;
case StudentEmailChanged emailChanged:
case StudentUpdated emailChanged:
Apply(emailChanged);
break;
case StudentEnrolled enrolled:
Apply(enrolled);
break;
case StudentWithdrawn withdrawn:
case StudentWithdrew withdrawn:
Apply(withdrawn);
break;
}
}

private void Apply(StudentCreated @event)
{
Id = @event.Id;
Id = @event.StudentId;
FullName = @event.FullName;
Email = @event.Email;
CreatedAtUtc = @event.CreatedAtUtc;
}

private void Apply(StudentEmailChanged @event)
private void Apply(StudentUpdated @event)
{
Email = @event.Email;
}
Expand All @@ -49,9 +49,9 @@ private void Apply(StudentEnrolled @event)
EnrolledCourses.Add(@event.CourseName);
}

private void Apply(StudentWithdrawn @event)
private void Apply(StudentWithdrew @event)
{
if (EnrolledCourses.Contains(@event.CourseName))
EnrolledCourses.Add(@event.CourseName);
EnrolledCourses.Remove(@event.CourseName);
}
}
6 changes: 6 additions & 0 deletions StudentEnrollment03.Esdb/Events/Event.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
namespace StudentEnrollment03.Esdb.Events;

public abstract record Event
{
public string Id { get; init; } = default!;
}
35 changes: 35 additions & 0 deletions StudentEnrollment03.Esdb/Events/EventTypeMapper.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
using System.Collections.Concurrent;

namespace StudentEnrollment03.Esdb.Events;

public class EventTypeMapper
{
public static readonly EventTypeMapper Instance = new();

private readonly ConcurrentDictionary<string, Type?> _typeMap = new();
private readonly ConcurrentDictionary<Type, string> _typeNameMap = new();

public string ToName<TEventType>() => ToName(typeof(TEventType));

public string ToName(Type eventType) => _typeNameMap.GetOrAdd(eventType, _ =>
{
var eventTypeName = eventType.FullName!;
_typeMap.TryAdd(eventTypeName, eventType);
return eventTypeName;
});

public Type? ToType(string eventTypeName) => _typeMap.GetOrAdd(eventTypeName, _ =>
{
var type = AppDomain.CurrentDomain
.GetAssemblies()
.SelectMany(a => a.GetTypes().Where(x => x.FullName == eventTypeName || x.Name == eventTypeName))
.FirstOrDefault();

if (type == null)
return null;

_typeNameMap.TryAdd(type, eventTypeName);

return type;
});
}
9 changes: 9 additions & 0 deletions StudentEnrollment03.Esdb/Events/StudentCreated.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
namespace StudentEnrollment03.Esdb.Events;

public record StudentCreated : Event
{
public required string FullName { get; init; }
public required string Email { get; init; }
public required DateTime DateOfBirth { get; init; }
public DateTime CreatedAtUtc { get; init; }
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
namespace StudentEnrollment02.Esdb.Events;
namespace StudentEnrollment03.Esdb.Events;

public record StudentEmailChanged : Event
{
Expand Down
8 changes: 8 additions & 0 deletions StudentEnrollment03.Esdb/Events/StudentEnrolled.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
namespace StudentEnrollment03.Esdb.Events;

public record StudentEnrolled : Event
{
public required string CourseName { get; init; }
public required string InstructorName { get; init; }
public DateTime EnrolledAtUtc { get; init; }
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
namespace StudentEnrollment02.Esdb.Events;
namespace StudentEnrollment03.Esdb.Events;

public record StudentWithdrawn : Event
public record StudentWithdrew : Event
{
public required string CourseName { get; init; }
public DateTime WithdrawnAtUtc { get; init; }
Expand Down
Loading

0 comments on commit 960ad6c

Please sign in to comment.