-
Notifications
You must be signed in to change notification settings - Fork 0
Closed
Description
Overview
Implement the migration function registration and execution pipeline for transforming component data between versions.
Parent Issue
- Component Schema Evolution (Phase 16.2) #352 (Component Schema Evolution)
- ADR: docs/adr/015-component-schema-migrations.md
- Depends on: feat: Component version infrastructure #697 (Version Infrastructure)
Requirements
MigrateFrom Attribute
- Create
[MigrateFrom(int version, string methodName)]attribute - Support multiple
[MigrateFrom]attributes on single component - Validate migration method signature at compile time
- Error if migration method not found or wrong signature
Source Generator
- Generate
ComponentMigrationRegistryclass - Build migration delegate lookup table
-
Migrate<T>(object source, int fromVersion)method - Compile migration functions as delegates (no reflection)
Serialization Integration
- Hook into
IComponentSerializer.Deserialize<T>() - Check version, invoke migration if needed
- Return migrated component to caller
Error Handling
-
MigrationNotFoundExceptionfor missing migration path -
MigrationExceptionfor migration function failures - Include source version, target version, component type in errors
Example
[Component(Version = 2)]
[MigrateFrom(1, nameof(MigrateFromV1))]
public partial struct Health
{
public int Current;
public int Max;
public int Shield;
private static Health MigrateFromV1(HealthV1 old)
{
return new Health
{
Current = old.Current,
Max = old.Max,
Shield = 0
};
}
}
// Generated:
public static partial class ComponentMigrationRegistry
{
private static readonly Dictionary<(Type, int, int), Delegate> migrations = new()
{
[(typeof(Health), 1, 2)] = (Func<HealthV1, Health>)Health.MigrateFromV1,
};
public static T Migrate<T>(object source, int fromVersion) where T : struct, IComponent
{
var key = (typeof(T), fromVersion, fromVersion + 1);
if (migrations.TryGetValue(key, out var migration))
{
return (T)migration.DynamicInvoke(source)!;
}
throw new MigrationNotFoundException(...);
}
}Acceptance Criteria
- Migration functions registered via attribute
- Migrations execute during deserialization
- Clear errors for missing migrations
- Migration failures include diagnostic info
- Unit tests for single-step migrations
- Integration tests with serialization
Technical Notes
- Migration delegates are
Func<TOld, TNew> - Old version types must be preserved (e.g.,
HealthV1) - Consider making old types
readonly structfor safety
Metadata
Metadata
Assignees
Labels
No labels