Skip to content

Add DocMigrator to handle deserialization and migrations#170

Merged
Timmoth merged 2 commits intoTimmoth:mainfrom
reavessm:migration
Feb 24, 2026
Merged

Add DocMigrator to handle deserialization and migrations#170
Timmoth merged 2 commits intoTimmoth:mainfrom
reavessm:migration

Conversation

@reavessm
Copy link
Contributor

This is currently a WIP as I'm still not exactly sure how to instantiate the migrator and include the prebuilt deserializer. This is a little out of my dotnet depth so it may take me a bit to figure out, but I'm going to go ahead push here to get some more eyes on it

Signed-off-by: Stephen Reaves <reaves735@gmail.com>
@reavessm
Copy link
Contributor Author

Also, this required some version bumps to get working with docmigrator, so I ran dotnet outdated . -u, but because it's currently not building, I'm not sure if that was a little heavy handed. Some of the deps crossed major version boundaries so we may need to roll those back

@Timmoth
Copy link
Owner

Timmoth commented Feb 23, 2026

I would say create a new Deserializer class called RackPeekConfigMigrationDeserializer which implements YamlMigrationDeserializer<YamlRoot>like you see in the Readme of docmigrator https://github.com/Timmoth/DocMigrator

Then register it during startup in DI (it's fine to be a singleton and include the yaml (de)serializer builder config)

// dont forget to use the proper serialization settings from the YamlResourceCollection.cs
builder.Services.AddSingleton<RackPeekConfigMigrationDeserializer>(sp =>
{
    var logger = sp.GetRequiredService<
        ILogger<YamlMigrationDeserializer<YamlRoot>>>();

    var deserializerBuilder = new DeserializerBuilder()
        .WithNamingConvention(CamelCaseNamingConvention.Instance)
        .IgnoreUnmatchedProperties();

    var serializerBuilder = new SerializerBuilder()
        .WithNamingConvention(CamelCaseNamingConvention.Instance);

    return new RackPeekConfigMigrationDeserializer(
        sp,
        logger,
        deserializerBuilder,
        serializerBuilder);
});

ThenYamlResourceCollection should have a RackPeekConfigMigrationDeserializer instance injected into the constructor.

then call

root = _deserializer. Deserialize(yaml)

on line 135 instead of

root = await MigrateAsync(root);

The only missing bit now is to determine if a migration is necessary (prior to deserialization), such that we can decide to save a backup copy. (maybe this should be a feature of doc migrator?)

Something like:

public int GetSchemaVersion(string yaml)
{
    try
    {
        var deserializer = _deserializerBuilder.Build();

        var obj = deserializer.Deserialize<Dictionary<object, object>>(yaml);

        if (obj != null &&
            obj.TryGetValue("schemaVersion", out var value) &&
            value != null)
        {
            if (value is int i)
                return i;

            if (value is string s && int.TryParse(s, out var parsed))
                return parsed;
        }

        return 0;
    }
    catch
    {
        return 0;
    }
}

Signed-off-by: Stephen Reaves <reaves735@gmail.com>
@Timmoth
Copy link
Owner

Timmoth commented Feb 24, 2026

Applied finishing touches and merged with #178

Note I also added the ability to specify the 'schemaVersion' property name to doc migrator, so we can continue to use 'version: 1'

I've also opened #179 To finish by setting up a testing structure for migrations

@Timmoth Timmoth merged commit d5ecf77 into Timmoth:main Feb 24, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants