Event Versioning #21
Replies: 5 comments 1 reply
-
|
My initial thought was something like this, where an event could publish migrations and have the data migrated before hydration (doing it before hydration means that you don't have to worry about typehints on the event object itself). I also like the idea of having the event's version basically being the highest value in keys of the migrations array—this would mean that to add a new version, you would add a new migration. public static function migrations()
{
return [
1 => fn(array $data) => array_merge($data, ['status' => 'backfilled']),
2 => fn(array $data) => array_merge($data, ['status' => StatusEnum::from($data['status'])]),
];
}My next thought was that we could potentially add a public static function migrations()
{
return new Migrations(
v1: fn(array $data) => array_merge($data, ['status' => 'backfilled']),
v2: fn(array $data) => array_merge($data, ['status' => StatusEnum::from($data['status'])]),
);
}The upside of something like this is that we could bind the closures to the class EndedTurnMigrations extends Migrations
{
public function __construct(
protected StateCollection $states
) {}
public function v1(array $data): array {
// ...
}
public function v2(array $data): array {
// ...
}
}Another upside of having a dedicated object is that we could pass things like the associated State into the migrations for backfilling/etc. For this reason, I think that having a method on That said, we may want to support both more dedicated migration objects and arrays of Closures, in which case, we could do whichever we want first. |
Beta Was this translation helpful? Give feedback.
-
|
If we implement this and metadata (see #14) would we use metadata to hold the version number, or include that in its own column? |
Beta Was this translation helpful? Give feedback.
-
|
Really like the idea of having a migrate method on events, but looking at the example where we have an array of closures it does take me a while to understand what's going on. It might just be because I'm used to spaties event versioning system, but having a single method for upcasting/migrating does feel more intuitive to me. Curious if this is just me though. It's very possible, that it's just a matter of getting used to a different syntax. I also like having the event version as an attribute on the class. It makes it easy to catch that versions are modified in pull requests etc. How would you feel about some kind of combination of the two? For example: #[Version(3)]
class UserInfoUpdated extends Event
{
public string $name;
// Let's pretend this was called emailAddress in v1
public string $email;
// Let's pretend this was added in v3
public bool $emailVerified;
public function migrate(int $version, array $params)
{
if ($version < 2) {
$params['email'] = $params['emailAddress'];
}
if ($version < 3) {
$params['emailVerified'] = false;
}
return new self(...$params);
}
}In the example above, This is psudocode, so disregard any bugs i probably threw in there. Not even sure it's possible to do this way, but I hope it makes sense anyway :) |
Beta Was this translation helpful? Give feedback.
-
I think the cool thing about having the version number tied to the migrations is that it's 100% explicit when something is changing. The only way to get a new version is to write a migration for it, which would be part of the PR. I do appreciate some of the questions you bring up about this API not being immediately obvious, though. I want to think about that for a few. I think there's also possibly an attribute-driven approach, where you annotate changes to the event with different PHP attributes… |
Beta Was this translation helpful? Give feedback.
-
|
It'd be nice if |
Beta Was this translation helpful? Give feedback.
Uh oh!
There was an error while loading. Please reload this page.
-
@inxilpro @joshhanley and I have all had some conversations about this.
The general idea is:
Events may change shape over time. Adding, removing, or modifying properties.
We should provide a mechanism for rolling old events forward to the new scheme either on-demand (with a command) or just-in-time when those events are replayed or re-applied to a state.
A few ideas that have been thrown out.
versionfield onverb_eventstable, which could be compared to the number ofmigrationson the event to know if it's "up to date"Beta Was this translation helpful? Give feedback.
All reactions