https://github.com/slashdotdash/eventstore-migrator
Copy & transform migration strategy for Elixir EventStore
https://github.com/slashdotdash/eventstore-migrator
Last synced: 11 months ago
JSON representation
Copy & transform migration strategy for Elixir EventStore
- Host: GitHub
- URL: https://github.com/slashdotdash/eventstore-migrator
- Owner: slashdotdash
- Created: 2017-01-08T13:07:53.000Z (over 9 years ago)
- Default Branch: master
- Last Pushed: 2017-01-13T11:48:01.000Z (over 9 years ago)
- Last Synced: 2025-02-28T15:17:55.042Z (over 1 year ago)
- Language: Elixir
- Homepage:
- Size: 26.4 KB
- Stars: 31
- Watchers: 4
- Forks: 1
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
Awesome Lists containing this project
README
# EventStore migrator
Copy & transform migration strategy for [eventstore](https://github.com/slashdotdash/eventstore).
> Copy and transformation transforms every event to a new store. In this technique the old event store stays intact, and a new store is created instead.
## Usage
`EventStore.Migrator` copies an [event store](https://github.com/slashdotdash/eventstore) PostgreSQL database from a source to a target.
It allows you to modify the events during the copy. You can transform, remove, aggregate, and alter the serialization format of the events.
The migrator exposes a single `migrate` function. It expects an anonymous function that receives an event stream. You can use any of the functions from Elixir's [stream](https://hexdocs.pm/elixir/Stream.html) module to mutate the event stream. The modified events are appended to the target event store database.
### Remove an unwanted event
```elixir
EventStore.Migrator.migrate(fn stream ->
Stream.reject(
stream,
fn (event_data) -> event_data.event_type == "UnwantedEvent" end
)
end)
```
### Upgrade an event
```elixir
defmodule OriginalEvent, do: defstruct [uuid: nil]
defmodule UpgradedEvent, do: defstruct [uuid: nil, additional: nil]
EventStore.Migrator.migrate(fn stream ->
Stream.map(
stream,
fn (event) ->
case event.data do
%OriginalEvent{uuid: uuid} ->
%EventStore.RecordedEvent{event |
event_type: "UpgradedEvent",
data: %UpgradedEvent{uuid: uuid, additional: "upgraded #{uuid}"},
}
_ -> event
end
end
)
end)
```
### Aggregate multiple events into one event
```elixir
defmodule SingleEvent, do: defstruct [uuid: nil, group: nil]
defmodule AggregatedEvent, do: defstruct [uuids: [], group: nil]
# aggregate multiple single events for the same group into one aggregated event
defp aggregate([%{data: %SingleEvent{}}] = events), do: events
defp aggregate([%{data: %SingleEvent{group: group}} = source | _] = events) do
[
%EventStore.RecordedEvent{source |
data: %AggregatedEvent{
uuids: Enum.map(events, fn event -> event.data.uuid end),
group: group,
},
event_type: "AggregatedEvent",
},
]
end
defp aggregate(events), do: events
EventStore.Migrator.migrate(fn stream ->
stream
|> Stream.chunk_by(fn event -> {event.stream_id, event.event_type} end)
|> Stream.map(fn events -> aggregate(events) end)
|> Stream.flat_map(fn events -> events end)
end)
```
### Migrate serialization format
Configure the source and target serializers in the environment configuration file (e.g. `config/dev.exs`).
```elixir
config :eventstore, EventStore.Storage,
serializer: JsonSerializer,
# ...
config :eventstore_migrator, EventStore.Migrator,
serializer: AlternateSerializer,
# ...
```
Run the migration without changing the event stream.
```elixir
EventStore.Migrator.migrate(source_config, target_config, fn stream -> stream end)
```
### Remarks
Streams are composable so you can combine multiple transforms in a single migration.