From 7107ba6c34ca61e7689843ff094f57f517d801c5 Mon Sep 17 00:00:00 2001 From: Erik Shafer Date: Thu, 23 May 2024 11:23:55 -0500 Subject: [PATCH 1/6] updated project numbers --- README.md | 32 +++++++++++++++----------------- 1 file changed, 15 insertions(+), 17 deletions(-) diff --git a/README.md b/README.md index 8b1bae1..4649745 100644 --- a/README.md +++ b/README.md @@ -47,35 +47,29 @@ Ideally on my birthday, May 22nd! ## 🏃 Running -### 0️⃣ Project: StudentEnrollment00 +### 0️⃣1️⃣ StudentEnrollment01.InMemory + +#### AKA the in-memory event store version Like the other programs that are .NET console application, the database is a glorified key-value store that's in-memory. To run it, enter the project directory through your shell's associated Change Directory (`cd`) command from the solution root, such as: ```bash -cd .\StudentEnrollment01 -``` - -and then build the project - -```bash +cd .\StudentEnrollment01.InMemory dotnet build -``` - -and run it - -```bash dotnet run ``` Alternatively, you can do all this from the solution's root by targeting the project with `--project` and `run` it immediately, such as: ```bash -dotnet run --project .\StudentEnrollment00\StudentEnrollment00.csproj +dotnet run --project .\StudentEnrollment01.InMemory\StudentEnrollment01.InMemory.csproj ``` -### 1️⃣ Project: StudentEnrollment01 +### 0️⃣2️⃣ StudentEnrollment02.Esdb + +#### AKA with EventStoreDB While still a .NET console app, we're now going to use the Event Store database. So be sure to launch EventStoreDB through Docker. With a terminal / command prompt execute: @@ -83,12 +77,14 @@ While still a .NET console app, we're now going to use the Event Store database. docker-compose up ``` +**NOTE**: You will need to have ESDB running via Docker for the third (03) project as well. + Like before, you can change directory into the project or run it from the root. Run the console application of your choice, change direction to that particular project directory and then execute: ```bash -cd .\StudentEnrollment01 +cd .\StudentEnrollment02.Esdb dotnet build dotnet run ``` @@ -96,10 +92,12 @@ dotnet run Or alternatively: ```bash -dotnet run --project .\StudentEnrollment01\StudentEnrollment01.csproj +dotnet run --project .\StudentEnrollment02.Esdb\StudentEnrollment02.Esdb.csproj ``` -### 2️⃣ TBD +### 0️⃣3️⃣ StudentEnrollment03.Esdb + +#### AKA with EventStoreDB, plus a few changes Instructions will go here, but will basically be the same as above! From f7d0044d2c2f659f70aad8f082bcd4b864574e1a Mon Sep 17 00:00:00 2001 From: Erik Shafer Date: Thu, 23 May 2024 11:24:18 -0500 Subject: [PATCH 2/6] if StreamNotFound exit early with print statement --- StudentEnrollment02.Esdb/Program.cs | 5 ++++- StudentEnrollment03.Esdb/Program.cs | 4 ++++ 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/StudentEnrollment02.Esdb/Program.cs b/StudentEnrollment02.Esdb/Program.cs index fe4b0b7..a5d3330 100644 --- a/StudentEnrollment02.Esdb/Program.cs +++ b/StudentEnrollment02.Esdb/Program.cs @@ -60,11 +60,14 @@ await client.AppendToStreamAsync( ); if (await streamResult.ReadState is ReadState.StreamNotFound) +{ + Console.WriteLine($"The fetched stream (id: {streamId}) that was read was in StreamNotFound state"); return; +} var eventStream = await streamResult.ToListAsync(); -Console.WriteLine("Events from selected stream: "); +Console.WriteLine($"Events (total: {eventStream.Count}) from selected stream: "); foreach (var resolved in eventStream) { Console.WriteLine($"\tEventId: {resolved.Event.EventId}"); diff --git a/StudentEnrollment03.Esdb/Program.cs b/StudentEnrollment03.Esdb/Program.cs index f2caef9..62a2266 100644 --- a/StudentEnrollment03.Esdb/Program.cs +++ b/StudentEnrollment03.Esdb/Program.cs @@ -102,11 +102,15 @@ await client.AppendToStreamAsync( ); if (await streamResult.ReadState is ReadState.StreamNotFound) +{ + Console.WriteLine($"The fetched stream (id: {streamId}) that was read was in StreamNotFound state"); return; +} var eventStream = await streamResult.ToListAsync(); var student = new Student(); +Console.WriteLine($"Events (total: {eventStream.Count}) from selected stream: "); foreach (var @event in eventStream) { switch (DeserializeEvent(@event.Event)) From 031d06adbff900e2a3414998baa92aa28125b48f Mon Sep 17 00:00:00 2001 From: Erik Shafer Date: Thu, 23 May 2024 15:22:46 -0500 Subject: [PATCH 3/6] quick-push; dockerfile, console clarity --- .dockerignore | 25 +++++++++++++++++++++++++ StudentEnrollment01.InMemory/Dockerfile | 21 +++++++++++++++++++++ StudentEnrollment01.InMemory/Program.cs | 6 ++++++ StudentEnrollment02.Esdb/Program.cs | 4 ++-- docker-compose.yml | 9 ++++++++- 5 files changed, 62 insertions(+), 3 deletions(-) create mode 100644 .dockerignore create mode 100644 StudentEnrollment01.InMemory/Dockerfile diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000..cd967fc --- /dev/null +++ b/.dockerignore @@ -0,0 +1,25 @@ +**/.dockerignore +**/.env +**/.git +**/.gitignore +**/.project +**/.settings +**/.toolstarget +**/.vs +**/.vscode +**/.idea +**/*.*proj.user +**/*.dbmdl +**/*.jfm +**/azds.yaml +**/bin +**/charts +**/docker-compose* +**/Dockerfile* +**/node_modules +**/npm-debug.log +**/obj +**/secrets.dev.yaml +**/values.dev.yaml +LICENSE +README.md \ No newline at end of file diff --git a/StudentEnrollment01.InMemory/Dockerfile b/StudentEnrollment01.InMemory/Dockerfile new file mode 100644 index 0000000..79c55d5 --- /dev/null +++ b/StudentEnrollment01.InMemory/Dockerfile @@ -0,0 +1,21 @@ +FROM mcr.microsoft.com/dotnet/runtime:8.0 AS base +USER $APP_UID +WORKDIR /app + +FROM mcr.microsoft.com/dotnet/sdk:8.0 AS build +ARG BUILD_CONFIGURATION=Release +WORKDIR /src +COPY ["StudentEnrollment01.InMemory/StudentEnrollment01.InMemory.csproj", "StudentEnrollment01.InMemory/"] +RUN dotnet restore "StudentEnrollment01.InMemory/StudentEnrollment01.InMemory.csproj" +COPY . . +WORKDIR "/src/StudentEnrollment01.InMemory" +RUN dotnet build "StudentEnrollment01.InMemory.csproj" -c $BUILD_CONFIGURATION -o /app/build + +FROM build AS publish +ARG BUILD_CONFIGURATION=Release +RUN dotnet publish "StudentEnrollment01.InMemory.csproj" -c $BUILD_CONFIGURATION -o /app/publish /p:UseAppHost=false + +FROM base AS final +WORKDIR /app +COPY --from=publish /app/publish . +ENTRYPOINT ["dotnet", "StudentEnrollment01.InMemory.dll"] diff --git a/StudentEnrollment01.InMemory/Program.cs b/StudentEnrollment01.InMemory/Program.cs index d6a4c0c..d7f1858 100644 --- a/StudentEnrollment01.InMemory/Program.cs +++ b/StudentEnrollment01.InMemory/Program.cs @@ -22,6 +22,12 @@ "StudentId: {0}\nFullName: {1}\nEmail: {2}\nDateOfBirth: {3}\nCreatedAtUtc: {4}", student!.Id, student.FullName, student.Email, student.DateOfBirth, student.CreatedAtUtc); Console.WriteLine("Enrolled courses:"); +if (student.EnrolledCourses.Count is 0) +{ + Console.WriteLine("No enrolled courses"); + return; +} + foreach (var enrolledCourse in student.EnrolledCourses) Console.WriteLine($"\t- {enrolledCourse}"); Console.WriteLine(); \ No newline at end of file diff --git a/StudentEnrollment02.Esdb/Program.cs b/StudentEnrollment02.Esdb/Program.cs index a5d3330..0f02fb7 100644 --- a/StudentEnrollment02.Esdb/Program.cs +++ b/StudentEnrollment02.Esdb/Program.cs @@ -82,6 +82,6 @@ await client.AppendToStreamAsync( .Select(re => JsonSerializer.Deserialize(re.Event.Data.ToArray())) .Select(se => se!.CourseName) .ToList(); -Console.WriteLine("Courses enrolled in: "); -enrolledCourses.ForEach(ec => Console.WriteLine($"\t- {ec}")); +Console.WriteLine("Enrolled courses found in the stream: "); +enrolledCourses.ForEach(ec => Console.WriteLine($"\t- {ec}")); // run the app multiple times ;) Console.WriteLine(""); \ No newline at end of file diff --git a/docker-compose.yml b/docker-compose.yml index cea2e4a..81a92cb 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -1,6 +1,12 @@ version: "3.4" services: + app01-inmemory: + build: + dockerfile: StudentEnrollment01.InMemory/Dockerfile + context: . + container_name: app01-inmemory + student-enrollment-esdb: image: eventstore/eventstore:24.2.0-jammy environment: @@ -15,4 +21,5 @@ services: networks: - student-enrollment-esdb-net networks: - student-enrollment-esdb-net: \ No newline at end of file + student-enrollment-esdb-net: + driver: bridge \ No newline at end of file From 82ac80d2b9ab6a41efec7be9ced579d3688fb251 Mon Sep 17 00:00:00 2001 From: Erik Shafer Date: Thu, 23 May 2024 15:23:05 -0500 Subject: [PATCH 4/6] quick push for sharing progress --- .../StudentEnrollment01.InMemory.csproj | 6 ++++++ StudentEnrollment03.Esdb/Program.cs | 9 ++++++++- 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/StudentEnrollment01.InMemory/StudentEnrollment01.InMemory.csproj b/StudentEnrollment01.InMemory/StudentEnrollment01.InMemory.csproj index e407cdc..4fa8577 100644 --- a/StudentEnrollment01.InMemory/StudentEnrollment01.InMemory.csproj +++ b/StudentEnrollment01.InMemory/StudentEnrollment01.InMemory.csproj @@ -8,4 +8,10 @@ Linux + + + .dockerignore + + + diff --git a/StudentEnrollment03.Esdb/Program.cs b/StudentEnrollment03.Esdb/Program.cs index 62a2266..388f735 100644 --- a/StudentEnrollment03.Esdb/Program.cs +++ b/StudentEnrollment03.Esdb/Program.cs @@ -90,7 +90,14 @@ await client.AppendToStreamAsync( streamId, StreamState.Any, - new[] { created, enrolled, enrolled2, enrolled3, emailChanged, withdrawn }, + new[] { created, enrolled, enrolled2, enrolled3, emailChanged }, + cancellationToken: default +); + +await client.AppendToStreamAsync( + streamId, + new StreamRevision(), // StreamState.StreamExists, // TODO + new[] { withdrawn }, cancellationToken: default ); From 9161c2d503a7472fa1bc00bfbd4894dca41933f9 Mon Sep 17 00:00:00 2001 From: Erik Shafer Date: Thu, 23 May 2024 15:42:24 -0500 Subject: [PATCH 5/6] revision check implemented --- StudentEnrollment03.Esdb/Program.cs | 22 +++++++++++++++------- 1 file changed, 15 insertions(+), 7 deletions(-) diff --git a/StudentEnrollment03.Esdb/Program.cs b/StudentEnrollment03.Esdb/Program.cs index 388f735..16b0b43 100644 --- a/StudentEnrollment03.Esdb/Program.cs +++ b/StudentEnrollment03.Esdb/Program.cs @@ -87,6 +87,7 @@ var settings = EventStoreClientSettings.Create(connectionString); var client = new EventStoreClient(settings); +// Append the initial batch of events. await client.AppendToStreamAsync( streamId, StreamState.Any, @@ -94,13 +95,7 @@ await client.AppendToStreamAsync( cancellationToken: default ); -await client.AppendToStreamAsync( - streamId, - new StreamRevision(), // StreamState.StreamExists, // TODO - new[] { withdrawn }, - cancellationToken: default -); - +// Read from the stream we just appended to. var streamResult = client.ReadStreamAsync( Direction.Forwards, streamId, @@ -108,13 +103,26 @@ await client.AppendToStreamAsync( cancellationToken: default ); +// Optional safety check, but here we're ensuring the stream was found. if (await streamResult.ReadState is ReadState.StreamNotFound) { Console.WriteLine($"The fetched stream (id: {streamId}) that was read was in StreamNotFound state"); return; } +// Okay, taking that StreamResult we're going to make it a List of ResolvedEvents. var eventStream = await streamResult.ToListAsync(); +// Get the last event's event number. +var lastEventInStream = eventStream.Last().Event.EventNumber.ToUInt64(); + +// Append another event. This time let's make sure no one has appended to (AKA updated) the stream. +await client.AppendToStreamAsync( + streamId, + new StreamRevision(lastEventInStream), // checking against expected revision number + new[] { withdrawn }, + cancellationToken: default +); + var student = new Student(); Console.WriteLine($"Events (total: {eventStream.Count}) from selected stream: "); From 229e19ea047aa6febda7517da799261c3b085697 Mon Sep 17 00:00:00 2001 From: Erik Shafer Date: Thu, 23 May 2024 16:04:52 -0500 Subject: [PATCH 6/6] =?UTF-8?q?can=20now=20showcase=20revision=20checks=20?= =?UTF-8?q?from=20ESDB!=201337=20=F0=9F=98=8E?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- StudentEnrollment03.Esdb/Program.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/StudentEnrollment03.Esdb/Program.cs b/StudentEnrollment03.Esdb/Program.cs index 16b0b43..ebb48d8 100644 --- a/StudentEnrollment03.Esdb/Program.cs +++ b/StudentEnrollment03.Esdb/Program.cs @@ -113,12 +113,12 @@ await client.AppendToStreamAsync( // Okay, taking that StreamResult we're going to make it a List of ResolvedEvents. var eventStream = await streamResult.ToListAsync(); // Get the last event's event number. -var lastEventInStream = eventStream.Last().Event.EventNumber.ToUInt64(); +var lastEventNumFromStream = eventStream.Last().Event.EventNumber.ToUInt64(); // Append another event. This time let's make sure no one has appended to (AKA updated) the stream. await client.AppendToStreamAsync( streamId, - new StreamRevision(lastEventInStream), // checking against expected revision number + new StreamRevision(lastEventNumFromStream), // checking against expected revision number new[] { withdrawn }, cancellationToken: default );