Skip to content

Commit

Permalink
Added sample showing how to apply stream transformations for events v…
Browse files Browse the repository at this point in the history
…ersioning with ESDB
  • Loading branch information
oskardudycz committed Jul 3, 2022
1 parent b83d55f commit 8092343
Show file tree
Hide file tree
Showing 10 changed files with 352 additions and 62 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/samples_events-versioning.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
name: Samples - EventStoreDB Stream Metadata
name: Samples - EventStoreDB Events Versioning

on:
# run it on push to the default repository branch
Expand Down
14 changes: 8 additions & 6 deletions samples/events-versioning/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -344,9 +344,9 @@ public class EventTypeMapping {
and use it as

```java
final String eventTypeV1Name = "shopping_cart_initialized_v1";
final String eventTypeV2Name = "shopping_cart_initialized_v2";
final String eventTypeV3Name = "shopping_cart_initialized_v3";
final String eventTypeV1Name = "shopping_cart_opened_v1";
final String eventTypeV2Name = "shopping_cart_opened_v2";
final String eventTypeV3Name = "shopping_cart_opened_v3";

var mapping = new EventTypeMapping()
.register(ShoppingCartInitializedWithStatus.class,
Expand Down Expand Up @@ -535,20 +535,22 @@ private static EventData toShoppingCartInitializedWithProducts(
);

return new EventData(
"shopping_cart_initialized_v2",
"shopping_cart_opened_v2",
Serializer.serialize(newEvent),
shoppingCartInitialized.metaData
);
}
```

See a full sample in [StreamTransformations.cs](./src/test/java/io/eventdriven/eventsversioning/transformations/StreamTransformationsTests.java).
See a full sample in:
- [StreamTransformations.cs](./src/test/java/io/eventdriven/eventsversioning/transformations/StreamTransformationsTests.java).
- [esdb/StreamTransformations.cs](./src/test/java/io/eventdriven/eventsversioning/transformations/esdb/StreamTransformationsTests.java) showing how to apply them in practice into EventStoreDB.

## Migrations

You can say that, well, those patterns are not migrations. Events will stay as they were, and you'll have to keep the old structure forever. That's quite true. Still, this is fine, as typically, you should not change the past. Having precise information, even including bugs, is a valid scenario. It allows you to get insights and see the precise history. However, pragmatically you may sometimes want to have a "clean" event log with only a new schema.

It appears that composing the patterns described above can support such a case. For example, if you're running EventStoreDB or Marten, you can read/subscribe to the event stream, store events in the new stream, or even a new EventStoreDB cluster or Postgres schema. Having that, you could even rewrite the whole log and switch databases once the new one caught up.
It appears that composing the patterns described above can support such a case. For example, if you're running EventStoreDB, you can read/subscribe to the event stream, store events in the new stream, or even a new EventStoreDB cluster. Having that, you could even rewrite the whole log and switch databases once the new one caught up.

I hope that those samples will show you that you can support many versioning scenarios with basic composition techniques.

Expand Down
7 changes: 2 additions & 5 deletions samples/events-versioning/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -18,16 +18,13 @@ dependencies {
// EventStoreDB client
implementation 'com.eventstore:db-client-java:3.0.0'


// Postgres and JPA for read models
implementation 'junit:junit:4.13.2'

implementation 'org.slf4j:slf4j-log4j13:1.0.1'
// Logging
implementation 'org.apache.logging.log4j:log4j-api:2.17.2'
implementation 'org.apache.logging.log4j:log4j-core:2.17.2'
implementation 'org.apache.logging.log4j:log4j-slf4j-impl:2.17.2'

// Test frameworks
implementation 'junit:junit:4.13.2'
testImplementation 'org.junit.jupiter:junit-jupiter-api:5.8.2'
testImplementation 'org.junit.jupiter:junit-jupiter-engine:5.8.2'
testImplementation 'org.junit.platform:junit-platform-launcher:1.8.2'
Expand Down
31 changes: 0 additions & 31 deletions samples/events-versioning/docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -29,42 +29,11 @@ services:
target: /var/log/eventstore
networks:
- eventstore.db

#######################################################
# Postgres
#######################################################
postgres:
image: clkao/postgres-plv8
container_name: postgres
environment:
POSTGRES_PASSWORD: Password12!
ports:
- "5432:5432"
networks:
- postgres

pgadmin:
image: dpage/pgadmin4
container_name: pgadmin_container
environment:
PGADMIN_DEFAULT_EMAIL: ${PGADMIN_DEFAULT_EMAIL:[email protected]}
PGADMIN_DEFAULT_PASSWORD: ${PGADMIN_DEFAULT_PASSWORD:-admin}
PGADMIN_CONFIG_SERVER_MODE: 'False'
volumes:
- pgadmin:/var/lib/pgadmin
ports:
- "${PGADMIN_PORT:-5050}:80"
networks:
- postgres

networks:
eventstore.db:
driver: bridge
postgres:
driver: bridge

volumes:
eventstore-volume-data:
eventstore-volume-logs:
postgres:
pgadmin:

This file was deleted.

3 changes: 0 additions & 3 deletions samples/events-versioning/src/main/resources/log4j2.xml
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,6 @@
<AppenderRef ref="LogToFile"/>
<AppenderRef ref="LogToConsole"/>
</Logger>
<Logger name="org.springframework.boot" level="error" additivity="false">
<AppenderRef ref="LogToConsole"/>
</Logger>
<Root level="error">
<AppenderRef ref="LogToFile"/>
<AppenderRef ref="LogToConsole"/>
Expand Down
Empty file.
Original file line number Diff line number Diff line change
Expand Up @@ -138,9 +138,9 @@ public Optional<Object> deserialize(String eventTypeName, byte[] json) {
@Test
public void UpcastObjects_Should_BeForwardCompatible() {
// Given
final String eventTypeV1Name = "shopping_cart_initialized_v1";
final String eventTypeV2Name = "shopping_cart_initialized_v2";
final String eventTypeV3Name = "shopping_cart_initialized_v3";
final String eventTypeV1Name = "shopping_cart_opened_v1";
final String eventTypeV2Name = "shopping_cart_opened_v2";
final String eventTypeV3Name = "shopping_cart_opened_v3";

var mapping = new EventTypeMapping()
.register(ShoppingCartInitializedWithStatus.class,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@ private static EventData toShoppingCartInitializedWithProducts(
);

return new EventData(
"shopping_cart_initialized_v2",
"shopping_cart_opened_v2",
Serializer.serialize(newEvent),
shoppingCartInitialized.metaData
);
Expand Down Expand Up @@ -208,7 +208,8 @@ public record EventEnvelope(
public void UpcastObjects_Should_BeForwardCompatible() {
// Given
var mapping = new EventTypeMapping()
.register(ShoppingCartInitializedWithProducts.class, "shopping_cart_initialized_v2")
.register(ShoppingCartEvent.ShoppingCartOpened.class, "shopping_cart_opened_v2")
.register(ShoppingCartInitializedWithProducts.class, "shopping_cart_opened_v2")
.register(ShoppingCartEvent.ProductItemAddedToShoppingCart.class, "product_item_added_v1")
.register(ShoppingCartEvent.ShoppingCartConfirmed.class, "shopping_card_confirmed_v1");

Expand All @@ -229,7 +230,7 @@ public void UpcastObjects_Should_BeForwardCompatible() {

var events = new ArrayList<>(List.of(
new EventEnvelope(
"shopping_cart_initialized_v1",
"shopping_cart_opened_v1",
new ShoppingCartEvent.ShoppingCartOpened(shoppingCardId, clientId),
new EventMetadata(theSameCorrelationId)
),
Expand Down
Loading

0 comments on commit 8092343

Please sign in to comment.