Skip to content

feat: Orleans 3.x Migration Tooling #9351

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 76 commits into from
Mar 28, 2025

Conversation

DeagleGross
Copy link
Member

@DeagleGross DeagleGross commented Feb 13, 2025

Migration tooling is built as an extension to Orleans3.x, and it is designed to not make a downtime of the application. It should be used temporarily to migrate data and should eventually be replaced by Orleans 7.x+ version. It has capabilities to log and save the progress of migration and control it.

It is in the nature of Orleans that part of grains is touched, used, and their state is updated during the runtime of the application. Tooling is using it by providing a new Storage implementation, which will read and write from/to 2 underlying storages (let's call them "source" and "destination"). That would allow an implicit migration of data to happen.

However, not all of the grains will be touched and updated during runtime of app, meaning there should be a way to force migration for all other grains. Therefore, there is a separate component which encapsulates this logic. It does the following:

  • Iterate through all grains / reminders in the source storage
  • Determine whether grain is already migrated or not (by looking up at the destination storage)
  • If not migrated - do the write into destination storage and mark as migrated

Migration tooling is tested in a way that for some random Grain (implementation below) is written to CosmosDB in expected format, and then a sample app using latest Orleans (8 version) reads the grain from the same CosmosDB.

Details

Fundamental components implemented are MigrationGrainStorage and DataMigrator.

  • MigrationGrainStorage is a component to perform a runtime-migration of grains. It should be registered as a main grainStorage, which redirects the storage calls to underlying source (existing) or destination (targeting migration) storage. It has different options to control the behavior (see GrainMigrationMode: Disabled;ReadSource_WriteBoth;ReadDestinationWithFallback_WriteBoth;ReadDestinationWithFallback_WriteDestination;ReadWriteDestination).

  • DataMigrator is a component to perform a background or explicit migration of those grains, which are not touched during the app runtime. It will run until it ends up the migration, and it logs all the operations performed. There is backoff included and it is built to not conflicts accross the cluster.

Testing

Refer to Tester.AzureUtils.Migration csproj for testing of migration tooling. I was testing against my own cosmos db, and we should start the emulator for cosmos to simulate those tests.

@DeagleGross
Copy link
Member Author

/azp run

Copy link

Azure Pipelines successfully started running 1 pipeline(s).

@DeagleGross
Copy link
Member Author

/azp run

Copy link

Azure Pipelines successfully started running 1 pipeline(s).

@DeagleGross
Copy link
Member Author

/azp run

Copy link

Azure Pipelines successfully started running 1 pipeline(s).

// if not - we simply fail fast with an explicit error message
_sourceStorage = (sourceStorage is IExtendedGrainStorage oldStorageEntriesController)
? oldStorageEntriesController
: throw new ArgumentException($"Implement {nameof(IExtendedGrainStorage)} on grainStorage to support data migration.", paramName: nameof(sourceStorage));
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit, no action needed. Ideally, we should avoid local/private code symbols in messages. We don't always adhere to that, especially not in the past.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i think IExtendedGrainStorage is not private, so it's okay to announce it in the message. But I will avoid this in future.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I meant 'grainStorage'

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed

</PropertyGroup>

<ItemGroup>
<PackageReference Include="Microsoft.Orleans.Serialization" Version="7.2.7" />
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I thought we landed on using v9.x (eg, 9.1.2)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i used a lower version, because 9.1.2 conflicts with other packages requiring a higher version, so even more packages must be updated if 9.1.2 is picked. I decided to have less updates here due to PR size and amount of package changes even.

@DeagleGross DeagleGross merged commit 5fd5eb8 into dotnet:3.x Mar 28, 2025
1 check passed
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.

3 participants