diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json index 75fca1e..deef4d8 100644 --- a/.devcontainer/devcontainer.json +++ b/.devcontainer/devcontainer.json @@ -8,7 +8,6 @@ "DOTNET_NOLOGO": "true" }, "onCreateCommand": "chmod +x /workspaces/developer-bootcamp/polyglot-persistence/onCreateCommand.sh && /workspaces/developer-bootcamp/polyglot-persistence/onCreateCommand.sh", - "postCreateCommand": "chmod +x /workspaces/developer-bootcamp/polyglot-persistence/postCreateCommand.sh && /workspaces/developer-bootcamp/polyglot-persistence/postCreateCommand.sh", "forwardPorts": [27017, 5432, 6379, 2113, 1113], "portsAttributes": { "2113": { diff --git a/polyglot-persistence/.devcontainer/Dockerfile b/polyglot-persistence/.devcontainer/Dockerfile deleted file mode 100644 index cfe6e08..0000000 --- a/polyglot-persistence/.devcontainer/Dockerfile +++ /dev/null @@ -1,14 +0,0 @@ -FROM mcr.microsoft.com/vscode/devcontainers/javascript-node:0-14 - -# Install any additional tools or dependencies needed for development -RUN apt-get update && apt-get install -y \ - curl \ - git \ - && apt-get clean \ - && rm -rf /var/lib/apt/lists/* - -# Set the working directory -WORKDIR /workspace - -# Copy any necessary files (if needed) -# COPY . . \ No newline at end of file diff --git a/polyglot-persistence/.devcontainer/devcontainer.json b/polyglot-persistence/.devcontainer/devcontainer.json deleted file mode 100644 index 6b4be9e..0000000 --- a/polyglot-persistence/.devcontainer/devcontainer.json +++ /dev/null @@ -1,14 +0,0 @@ -{ - "name": "My Dev Environment", - "dockerComposeFile": "../docker-compose.yml", - "service": "app", - "workspaceFolder": "/workspace", - "settings": { - "terminal.integrated.shell.linux": "/bin/bash" - }, - "extensions": [ - "ms-azuretools.vscode-docker", - "esbenp.prettier-vscode" - ], - "postCreateCommand": "npm install" -} \ No newline at end of file diff --git a/polyglot-persistence/Common/Common.csproj b/polyglot-persistence/Common/Common.csproj index 6f2149d..4f1a7b9 100644 --- a/polyglot-persistence/Common/Common.csproj +++ b/polyglot-persistence/Common/Common.csproj @@ -1,7 +1,7 @@  - net8.0 + net9.0 enable enable diff --git a/polyglot-persistence/DemoWeb/PostgresService.cs b/polyglot-persistence/DemoWeb/PostgresService.cs index dcd2400..fb7aa5b 100644 --- a/polyglot-persistence/DemoWeb/PostgresService.cs +++ b/polyglot-persistence/DemoWeb/PostgresService.cs @@ -10,8 +10,8 @@ public class PostgresService public PostgresService(IConfiguration configuration, ILogger logger) { _logger = logger; - _connectionString = configuration.GetConnectionString("PostgreSQL") - ?? "Host=localhost;Port=5432;Database=postgres;Username=postgres;Password=postgres"; + var postgresHost = Environment.GetEnvironmentVariable("POSTGRES_HOST") ?? "localhost"; + _connectionString = $"Host={postgresHost};Port=5432;Database=postgres;Username=postgres;Password=postgres"; _logger.LogInformation("PostgreSQL connection string: {ConnectionString}", _connectionString.Replace("Password=", "Password=***")); diff --git a/polyglot-persistence/DemoWeb/Program.cs b/polyglot-persistence/DemoWeb/Program.cs index cb9583f..f2ae663 100644 --- a/polyglot-persistence/DemoWeb/Program.cs +++ b/polyglot-persistence/DemoWeb/Program.cs @@ -11,8 +11,9 @@ builder.Services.AddSignalR(); // Register Redis services +var redisHost = Environment.GetEnvironmentVariable("REDIS_HOST") ?? "localhost"; builder.Services.AddSingleton(sp => - ConnectionMultiplexer.Connect("localhost:6379")); + ConnectionMultiplexer.Connect($"{redisHost}:6379")); builder.Services.AddSingleton(); // Register PostgreSQL service @@ -44,4 +45,6 @@ // Map SignalR hub app.MapHub("/topProductsHub"); -app.Run(); \ No newline at end of file +app.Run(); + +Console.WriteLine($"{AppDomain.CurrentDomain.FriendlyName} started"); \ No newline at end of file diff --git a/polyglot-persistence/DemoWeb/Properties/launchSettings.json b/polyglot-persistence/DemoWeb/Properties/launchSettings.json index 7c54133..2b5a75d 100644 --- a/polyglot-persistence/DemoWeb/Properties/launchSettings.json +++ b/polyglot-persistence/DemoWeb/Properties/launchSettings.json @@ -13,7 +13,7 @@ "commandName": "Project", "dotnetRunMessages": true, "launchBrowser": true, - "applicationUrl": "http://localhost:5108", + "applicationUrl": "http://0.0.0.0:5108", "environmentVariables": { "ASPNETCORE_ENVIRONMENT": "Development" } @@ -22,7 +22,7 @@ "commandName": "Project", "dotnetRunMessages": true, "launchBrowser": true, - "applicationUrl": "https://localhost:7164;http://localhost:5108", + "applicationUrl": "https://0.0.0.0:7164;http://0.0.0.0:5108", "environmentVariables": { "ASPNETCORE_ENVIRONMENT": "Development" } diff --git a/polyglot-persistence/DemoWeb/appsettings.json b/polyglot-persistence/DemoWeb/appsettings.json index 7df6b9b..fb87850 100644 --- a/polyglot-persistence/DemoWeb/appsettings.json +++ b/polyglot-persistence/DemoWeb/appsettings.json @@ -1,7 +1,4 @@ { - "ConnectionStrings": { - "PostgreSQL": "Host=localhost;Port=5432;Database=postgres;Username=postgres;Password=postgres" - }, "Logging": { "LogLevel": { "Default": "Information", diff --git a/polyglot-persistence/MongoProjection/Program.cs b/polyglot-persistence/MongoProjection/Program.cs index a6796a1..cf0a18d 100644 --- a/polyglot-persistence/MongoProjection/Program.cs +++ b/polyglot-persistence/MongoProjection/Program.cs @@ -8,10 +8,12 @@ Console.WriteLine($"{AppDomain.CurrentDomain.FriendlyName} started"); // Connect to MongoDB -var mongoCollection = new MongoClient("mongodb://localhost:27017").GetDatabase("polyglot-persistence").GetCollection("total-payment"); +var mongoHost = Environment.GetEnvironmentVariable("MONGO_HOST") ?? "localhost"; +var mongoCollection = new MongoClient($"mongodb://{mongoHost}:27017").GetDatabase("polyglot-persistence").GetCollection("total-payment"); // Connect to EventStoreDB -var esdb = new EventStoreClient(EventStoreClientSettings.Create("esdb://admin:changeit@localhost:2113?tls=false")); +var esdbHost = Environment.GetEnvironmentVariable("ESDB_HOST") ?? "localhost"; +var esdb = new EventStoreClient(EventStoreClientSettings.Create($"esdb://admin:changeit@{esdbHost}:2113?tls=false")); var checkpointValue = mongoCollection // Get the checkpoint value from MongoDB.. .Find(Builders.Filter.Eq("_id", "total")) // from the total document's.. diff --git a/polyglot-persistence/PostgresProjection/Program.cs b/polyglot-persistence/PostgresProjection/Program.cs index 63148f0..6173700 100644 --- a/polyglot-persistence/PostgresProjection/Program.cs +++ b/polyglot-persistence/PostgresProjection/Program.cs @@ -26,8 +26,11 @@ // Connect to PostgreSQL and EventStoreDB // // -------------------------------------- // -var postgres = new PostgresDataAccess(new NpgsqlConnection("Host=localhost;Port=5432;Database=postgres;Username=postgres")); -var esdb = new EventStoreClient(EventStoreClientSettings.Create("esdb://admin:changeit@localhost:2113?tls=false")); +var postgresHost = Environment.GetEnvironmentVariable("POSTGRES_HOST") ?? "localhost"; +var postgres = new PostgresDataAccess(new NpgsqlConnection($"Host={postgresHost};Port=5432;Database=postgres;Username=postgres")); + +var esdbHost = Environment.GetEnvironmentVariable("ESDB_HOST") ?? "localhost"; +var esdb = new EventStoreClient(EventStoreClientSettings.Create($"esdb://admin:changeit@{esdbHost}:2113?tls=false")); postgres.Execute(CartProjection.GetCreateCartTableCommand()); // Create the checkpoint table if it doesn't exist postgres.Execute(Checkpoint.GetCreateTableCommand()); // Create the checkpoint table if it doesn't exist diff --git a/polyglot-persistence/RedisProjection/Program.cs b/polyglot-persistence/RedisProjection/Program.cs index c250af6..8f52c3e 100644 --- a/polyglot-persistence/RedisProjection/Program.cs +++ b/polyglot-persistence/RedisProjection/Program.cs @@ -6,8 +6,12 @@ Console.WriteLine($"{AppDomain.CurrentDomain.FriendlyName} started"); -var redis = ConnectionMultiplexer.Connect("localhost:6379").GetDatabase(); // Connect to Redis -var esdb = new EventStoreClient(EventStoreClientSettings.Create("esdb://admin:changeit@localhost:2113?tls=false")); // Connect to EventStoreDB +// Program.cs +var redisHost = Environment.GetEnvironmentVariable("REDIS_HOST") ?? "localhost"; +var redis = ConnectionMultiplexer.Connect($"{redisHost}:6379").GetDatabase(); + // Connect to Redis +var esdbHost = Environment.GetEnvironmentVariable("ESDB_HOST") ?? "localhost"; +var esdb = new EventStoreClient(EventStoreClientSettings.Create($"esdb://admin:changeit@{esdbHost}:2113?tls=false")); // Connect to EventStoreDB var checkpointValue = redis.StringGet("checkpoint"); // Get the checkpoint value from redis var streamPosition = long.TryParse(checkpointValue, out var checkpoint) // Check if it exists and convertible to long diff --git a/polyglot-persistence/docker-compose.codespaces-prebuild.yml b/polyglot-persistence/docker-compose.codespaces-prebuild.yml new file mode 100644 index 0000000..0c93d79 --- /dev/null +++ b/polyglot-persistence/docker-compose.codespaces-prebuild.yml @@ -0,0 +1,79 @@ +services: + mongo: + image: mongo:7.0 + container_name: mongo + ports: + - "27017:27017" + + postgres: + image: postgres:16 + container_name: postgres + ports: + - "5432:5432" + environment: + - POSTGRES_HOST_AUTH_METHOD=trust + + redis: + image: redis:7.2 + container_name: redis + ports: + - "6379:6379" + + eventstore: + image: eventstore/eventstore:24.10 + container_name: eventstore + ports: + - "2113:2113" + - "1113:1113" + environment: + - EVENTSTORE_RUN_PROJECTIONS=All + - EVENTSTORE_START_STANDARD_PROJECTIONS=true + - EVENTSTORE_INSECURE=true + - EVENTSTORE_ENABLE_ATOM_PUB_OVER_HTTP=true + + demoweb: + image: mcr.microsoft.com/dotnet/sdk:9.0 + container_name: demoweb + working_dir: /app + volumes: + - ./DemoWeb:/app # Mount the DemoWeb project directory + command: ["dotnet", "build"] + ports: + - "5108:5108" + environment: + - REDIS_HOST=redis + - POSTGRES_HOST=postgres + + postgresprojection: + image: mcr.microsoft.com/dotnet/sdk:9.0 + container_name: postgresprojection + working_dir: /app + volumes: + - ./:/app + command: ["dotnet", "build", "./PostgresProjection"] + environment: + - POSTGRES_HOST=postgres + - ESDB_HOST=eventstore + + redisprojection: + image: mcr.microsoft.com/dotnet/sdk:9.0 + container_name: redisprojection + working_dir: /app + volumes: + - ./:/app + command: ["dotnet", "build", "./RedisProjection"] + environment: + - REDIS_HOST=redis + - ESDB_HOST=eventstore + + mongoprojection: + image: mcr.microsoft.com/dotnet/sdk:9.0 + container_name: mongoprojection + working_dir: /app + volumes: + - ./:/app + command: ["dotnet", "build", "./MongoProjection"] + environment: + - MONGO_HOST=mongo + - ESDB_HOST=eventstore + \ No newline at end of file diff --git a/polyglot-persistence/docker-compose.yml b/polyglot-persistence/docker-compose.yml index 7423764..b0ce631 100644 --- a/polyglot-persistence/docker-compose.yml +++ b/polyglot-persistence/docker-compose.yml @@ -4,7 +4,7 @@ services: container_name: mongo ports: - "27017:27017" - + postgres: image: postgres:16 container_name: postgres @@ -12,13 +12,13 @@ services: - "5432:5432" environment: - POSTGRES_HOST_AUTH_METHOD=trust - + redis: image: redis:7.2 container_name: redis ports: - "6379:6379" - + eventstore: image: eventstore/eventstore:24.10 container_name: eventstore @@ -29,4 +29,59 @@ services: - EVENTSTORE_RUN_PROJECTIONS=All - EVENTSTORE_START_STANDARD_PROJECTIONS=true - EVENTSTORE_INSECURE=true - - EVENTSTORE_ENABLE_ATOM_PUB_OVER_HTTP=true \ No newline at end of file + - EVENTSTORE_ENABLE_ATOM_PUB_OVER_HTTP=true + + demoweb: + image: mcr.microsoft.com/dotnet/sdk:9.0 + container_name: demoweb + working_dir: /app + volumes: + - ./DemoWeb:/app # Mount the DemoWeb project directory + command: ["dotnet", "run"] + ports: + - "5108:5108" + environment: + - REDIS_HOST=redis + - POSTGRES_HOST=postgres + + postgresprojection: + image: mcr.microsoft.com/dotnet/sdk:9.0 + container_name: postgresprojection + working_dir: /app + volumes: + - ./:/app + command: ["dotnet", "run", "--project", "./PostgresProjection"] + environment: + - POSTGRES_HOST=postgres + - ESDB_HOST=eventstore + depends_on: + - postgres + - eventstore + + redisprojection: + image: mcr.microsoft.com/dotnet/sdk:9.0 + container_name: redisprojection + working_dir: /app + volumes: + - ./:/app + command: ["dotnet", "run", "--project", "./RedisProjection"] + environment: + - REDIS_HOST=redis + - ESDB_HOST=eventstore + depends_on: + - redis + - eventstore + + mongoprojection: + image: mcr.microsoft.com/dotnet/sdk:9.0 + container_name: mongoprojection + working_dir: /app + volumes: + - ./:/app + command: ["dotnet", "run", "--project", "./MongoProjection"] + environment: + - MONGO_HOST=mongo + - ESDB_HOST=eventstore + depends_on: + - mongo + - eventstore \ No newline at end of file diff --git a/polyglot-persistence/generate-data.sh b/polyglot-persistence/generate-data.sh index e69de29..d603a2c 100644 --- a/polyglot-persistence/generate-data.sh +++ b/polyglot-persistence/generate-data.sh @@ -0,0 +1,20 @@ +unzip -o /workspaces/developer-bootcamp/polyglot-persistence/data/commerce-data-set.zip -d /workspaces/developer-bootcamp/polyglot-persistence/ + +chmod +x /workspaces/developer-bootcamp/polyglot-persistence/tools/Kurrent.Extensions.Commerce/linux-x64/edb-commerce + +# Wait for EventStoreDB to be ready +echo "Waiting for EventStoreDB to be ready..." +max_attempts=30 +attempt=0 +while ! curl -s http://localhost:2113/ > /dev/null; do + attempt=$((attempt+1)) + if [ $attempt -eq $max_attempts ]; then + echo "EventStoreDB failed to start after $max_attempts attempts. Exiting." + exit 1 + fi + echo "Waiting for EventStoreDB to be ready... (attempt $attempt/$max_attempts)" + sleep 2 +done +echo "EventStoreDB is ready." + +/workspaces/developer-bootcamp/polyglot-persistence/tools/Kurrent.Extensions.Commerce/linux-x64/edb-commerce seed-data-set /workspaces/developer-bootcamp/polyglot-persistence/data.json \ No newline at end of file diff --git a/polyglot-persistence/onCreateCommand.sh b/polyglot-persistence/onCreateCommand.sh index 441eb87..7882b07 100644 --- a/polyglot-persistence/onCreateCommand.sh +++ b/polyglot-persistence/onCreateCommand.sh @@ -4,21 +4,56 @@ unzip -o /workspaces/developer-bootcamp/polyglot-persistence/data/init-data.zip chmod +x /workspaces/developer-bootcamp/polyglot-persistence/tools/Kurrent.Extensions.Commerce/linux-x64/edb-commerce -# Wait for EventStoreDB to be ready -echo "Waiting for EventStoreDB to be ready..." -max_attempts=30 + +max_attempts=60 attempt=0 -while ! curl -s http://localhost:2113/ > /dev/null; do - attempt=$((attempt+1)) - if [ $attempt -eq $max_attempts ]; then - echo "EventStoreDB failed to start after $max_attempts attempts. Exiting." - exit 1 - fi - echo "Waiting for EventStoreDB to be ready... (attempt $attempt/$max_attempts)" - sleep 2 +while ! curl -s -o /dev/null -w "%{http_code}" http://localhost:2113/web/index.html | grep -q "200"; do + if [ "$attempt" -ge "$max_attempts" ]; then # If number of attempts exceeds max_attempts then we exit + echo "EventStoreDB is not available. Exiting" + exit 1 + fi + echo "Waiting for EventStoreDB to start... (attempt $attempt)" + attempt=$((attempt+1)) # Increment the attempt count + sleep 2 # Wait for a few seconds before checking again +done + +echo "EventStoreDB is running." + +max_attempts=60 +attempt=0 +while ! curl -s -o /dev/null -w "%{http_code}" http://localhost:5108/carts | grep -q "200"; do + if [ "$attempt" -ge "$max_attempts" ]; then # If number of attempts exceeds max_attempts then we exit + echo "DemoWeb is not available. Exiting" + exit 1 + fi + echo "Waiting for DemoWeb to start... (attempt $attempt)" + attempt=$((attempt+1)) # Increment the attempt count + sleep 2 # Wait for a few seconds before checking again done -echo "EventStoreDB is ready." + +echo "DemoWeb is running." /workspaces/developer-bootcamp/polyglot-persistence/tools/Kurrent.Extensions.Commerce/linux-x64/edb-commerce seed-data-set /workspaces/developer-bootcamp/polyglot-persistence/data.json -dotnet build /workspaces/developer-bootcamp/polyglot-persistence/polyglot-persistence.sln \ No newline at end of file +echo "Updated EventStoreDB with initial data." + +# Wait for the required projection messages to be detected +echo "Waiting for 'MongoProjection started', 'RedisProjection started' and 'DemoWeb started' messages..." +max_attempts=60 +attempt=0 +while true; do + logs=$(docker compose -f /workspaces/developer-bootcamp/polyglot-persistence/docker-compose.yml logs 2>&1) + if echo "$logs" | grep -q "MongoProjection started" && \ + echo "$logs" | grep -q "RedisProjection started" && \ + echo "$logs" | grep -q "PostgresProjection started"; then + echo "All required messages detected." + break + fi + attempt=$((attempt+1)) + if [ $attempt -ge $max_attempts ]; then + echo "Required projections did not start after $max_attempts attempts. Exiting." + exit 1 + fi + echo "Waiting for required projections... (attempt $attempt/$max_attempts)" + sleep 2 +done \ No newline at end of file diff --git a/polyglot-persistence/postCreateCommand.sh b/polyglot-persistence/postCreateCommand.sh deleted file mode 100644 index 5f05671..0000000 --- a/polyglot-persistence/postCreateCommand.sh +++ /dev/null @@ -1,9 +0,0 @@ -# docker compose -f /workspaces/developer-bootcamp/polyglot-persistence/docker-compose.yml up -d - -# dotnet run --project /workspaces/developer-bootcamp/polyglot-persistence/DemoWeb & - -# dotnet run --project /workspaces/developer-bootcamp/polyglot-persistence/PostgresProjection & - -# dotnet run --project /workspaces/developer-bootcamp/polyglot-persistence/RedisProjection & - -# dotnet run --project /workspaces/developer-bootcamp/polyglot-persistence/MongoProjection & \ No newline at end of file diff --git a/polyglot-persistence/start.sh b/polyglot-persistence/start.sh new file mode 100644 index 0000000..552d377 --- /dev/null +++ b/polyglot-persistence/start.sh @@ -0,0 +1,43 @@ +max_attempts=30 +attempt=0 +while ! docker ps > /dev/null 2>&1; do # While docker fails to run (e.g. Docker daemon is not running) + if [ "$attempt" -ge "$max_attempts" ]; then # If number of attempt exceeds the max_attempts then we exit + echo "Docker daemon is not available. Exiting" + exit 1 + fi + echo "Waiting for Docker daemon to start... (attempt $attempt)" + attempt=$((attempt+1)) # Increment the attempt count + sleep 2 # Wait for few seconds before we check again +done + +echo "Docker daemon is running." + +docker compose -f /workspaces/developer-bootcamp/polyglot-persistence/docker-compose.yml up -d + +max_attempts=30 +attempt=0 +while ! curl -s -o /dev/null -w "%{http_code}" http://localhost:2113/web/index.html | grep -q "200"; do + if [ "$attempt" -ge "$max_attempts" ]; then # If number of attempts exceeds max_attempts then we exit + echo "EventStoreDB is not available. Exiting" + exit 1 + fi + echo "Waiting for EventStoreDB to start... (attempt $attempt)" + attempt=$((attempt+1)) # Increment the attempt count + sleep 2 # Wait for a few seconds before checking again +done + +echo "EventStoreDB is running." + +max_attempts=30 +attempt=0 +while ! curl -s -o /dev/null -w "%{http_code}" http://localhost:5108/carts | grep -q "200"; do + if [ "$attempt" -ge "$max_attempts" ]; then # If number of attempts exceeds max_attempts then we exit + echo "DemoWeb is not available. Exiting" + exit 1 + fi + echo "Waiting for DemoWeb to start... (attempt $attempt)" + attempt=$((attempt+1)) # Increment the attempt count + sleep 2 # Wait for a few seconds before checking again +done + +echo "DemoWeb is running." \ No newline at end of file