Skip to content
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

feat: wrap-up migration tooling for Azure.Table.Storage -> Azure.CosmosDb.Storage scenario #8

Open
wants to merge 20 commits into
base: proto/state-migration
Choose a base branch
from

Conversation

DeagleGross
Copy link

@DeagleGross DeagleGross commented Nov 29, 2024

Current PR attempts to finish existing draft of migration tooling to support a specific scenario of migration from Azure.Table.Storage to Azure.CosmosDb.Storage (other scenarios such as blob migration is supported as well).

Migration consists of:

  1. migration of grain states from X storage to Y storage
  2. migration of reminders (from Azure Table Storage to another Azure Table Storage)

Migration tooling provides API to control the migration in different phases:

  1. initial phase, where devs can setup DI to redirect writing data into a "new storage" as well
  2. DataMigrator API to invoke a force migration of data from "old storage" to "new storage" (even if grain is not touched from the runtime)
  3. latter phase where old storage is used in readonly mode and updating of grain state happens only in a new storage

In this PR i have moved an existing "forked" Orleans.Persistence.Cosmos implementation.
For each of the Orleans.Persistence.XXX project exists a Orleans.Persistence.XXX.Migration project, which contains new types, which allow writing data in new format, and SiloExtensionHelpers to register those types in DI.

Tests are covering the cases of migration from one to another storage.

@DeagleGross DeagleGross changed the title feat(migration tooling): add offline migration / progress tracking / support Reminder entity feat: wrap-up migration tooling for Azure.Table.Storage -> Azure.CosmosDb.Storage scenario Jan 16, 2025
// options.ContainerName = $"destination{RandomIdentifier}";
options.ContainerName = $"destinationtest";
options.DatabaseName = "Orleans";
options.ConfigureCosmosClient(TestDefaultConfiguration.CosmosConnectionString);
Copy link
Author

Choose a reason for hiding this comment

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

I dont know if we can put an emulator here? I was testing against my own cosmos instance in Azure

@@ -314,18 +315,21 @@ private object ConvertFromStorageFormat(byte[] contents, Type stateType)

public async IAsyncEnumerable<StorageEntry> GetAll([EnumeratorCancellation] CancellationToken cancellationToken)
Copy link
Owner

@benjaminpetit benjaminpetit Jan 27, 2025

Choose a reason for hiding this comment

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

It would have been nice to skip alredy migrated entries, but I guess it's ok since we only get metadata? But we still create a new entry everytime.

EDIT: ah no, you read the entire entry everytime. I wonder if we should so a lazy read, done only if we explicitely read the entry to migrate it. That might need some new types though... Did you tested it with a large collection?

Copy link
Author

Choose a reason for hiding this comment

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

you read the entire entry everytime

that is correct. I did not test with the large collection (it is basically like the implementation existed with AzureBlobStorage - I just added loading the metadata). So you want to do something like that?

var metadata = client.LoadMetadata(entry);
if (metadata is null || metadata.IsNotMigrated())
{
    var blob = client.LoadBlob();
    yield return blob;
}

Copy link
Author

Choose a reason for hiding this comment

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

rename the method to GetNonMigrated entires or smth like that

Copy link
Author

Choose a reason for hiding this comment

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

rename the method to GetNonMigrated entires or smth like that + only fetch the whole entry if it is not migrated (as proposed in previous comment)

return cosmosGrainStorage.WriteStateAsync(grainTypeData, stateName, grainReference, grainState);
}

private GrainStateTypeInfo GetGrainStateTypeInfo(GrainReference grainReference, IGrainState grainState)
Copy link
Author

Choose a reason for hiding this comment

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

maybe move to interface to share the same cache as done in CosmosGrainStorage

return cosmosGrainStorage.WriteStateAsync(grainTypeData, stateName, grainReference, grainState);
}

private GrainStateTypeInfo GetGrainStateTypeInfo(GrainReference grainReference, IGrainState grainState)
Copy link
Author

Choose a reason for hiding this comment

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

maybe move to interface to share the same cache as done in CosmosGrainStorage

@@ -314,18 +315,21 @@ private object ConvertFromStorageFormat(byte[] contents, Type stateType)

public async IAsyncEnumerable<StorageEntry> GetAll([EnumeratorCancellation] CancellationToken cancellationToken)
Copy link
Author

Choose a reason for hiding this comment

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

rename the method to GetNonMigrated entires or smth like that

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