feat(stjm): support bidirectional migration for blue/green deployments - #32
Conversation
Allow two types to migrate from each other (X implements IMigrateFrom<Y, X> and Y implements IMigrateFrom<X, Y>) without causing infinite recursion. This enables blue/green deployment scenarios where both service versions run side by side, each capable of reading the other's serialized payloads. The fix changes the converter factory's type-exclusion mechanism from tracking a single excluded type to an immutable set of excluded types. Each level of nested converter resolution adds its target type to the set, breaking cycles of any depth while preserving migration-aware converters for unrelated nested migratable types. Agent-Logs-Url: https://github.com/egil/framework/sessions/f329165a-78df-49aa-8b40-c4842a0af701 Co-authored-by: egil <105649+egil@users.noreply.github.com>
…types [skip notes] Replace ImmutableHashSet<Type> with HashSet<Type> for the internal excluded-types tracking in JsonMigratableConverterFactory. HashSet provides O(1) Contains lookups without the structural-sharing overhead of ImmutableHashSet. The set is small (typically 1-2 items) and never mutated after construction, making HashSet the optimal choice. Agent-Logs-Url: https://github.com/egil/framework/sessions/f329165a-78df-49aa-8b40-c4842a0af701 Co-authored-by: egil <105649+egil@users.noreply.github.com>
There was a problem hiding this comment.
Pull request overview
Adds support for bidirectional JSON migration (blue/green deployment scenarios) where IMigrateFrom<X,Y> and IMigrateFrom<Y,X> (and equivalent external IMigrate<,> pairs) can coexist without causing converter resolution recursion.
Changes:
- Extends
JsonMigratableConverterFactoryto track an excluded type set (rather than a single excluded type) when cloningJsonSerializerOptions, preventing infinite recursion in bidirectional setups. - Adds new unit tests covering bidirectional migration for both static (
IMigrateFrom<,>) and external (IMigrate<,>) migrators. - Documents the blue/green bidirectional migration pattern in the authoring recipe docs.
Reviewed changes
Copilot reviewed 3 out of 3 changed files in this pull request and generated 2 comments.
| File | Description |
|---|---|
| Egil.SystemTextJson.Migration/test/Egil.SystemTextJson.Migration.Tests/BidirectionalMigrationTests.cs | Adds test coverage for bidirectional migrations (static + external). |
| Egil.SystemTextJson.Migration/src/Egil.SystemTextJson.Migration/Migrations/JsonMigratableConverterFactory.cs | Switches from single excluded type to HashSet<Type> to prevent recursive converter creation. |
| Egil.SystemTextJson.Migration/docs/recipes/migration-authoring.md | Adds a “Bidirectional migration (blue/green deployments)” documentation section. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
…oc note The HashSet<Type> exclusion mechanism handles cycles of any length, not just two-type bidirectional pairs. Added 4 tests proving A → B → C → A cycles work, and corrected the doc note that incorrectly claimed 3+ type cycles would error. Agent-Logs-Url: https://github.com/egil/framework/sessions/1f81905e-d28a-4dc0-a1a1-53e495bc053c Co-authored-by: egil <105649+egil@users.noreply.github.com>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
egil
left a comment
There was a problem hiding this comment.
Looks good. Squash into a single commit
The |
HashSet<Type>for excluded types