Multi-tenant data migration engine for SaasSuite
$ dotnet add package SaasSuite.MigrationMulti-tenant data migration engine for SaasSuite.
dotnet add package SaasSuite.Migration
dotnet add package SaasSuite.Core
services.AddSaasMigration(options =>
{
options.BatchSize = 10;
options.EnableParallelExecution = true;
options.MaxDegreeOfParallelism = 4;
options.EnableCheckpointing = true;
});
// Register your tenant provider
services.AddScoped<ITenantProvider, YourTenantProvider>();
// Register migration steps
services.AddMigrationStep<Step1>();
services.AddMigrationStep<Step2>();
using SaasSuite.Core.Interfaces;
using SaasSuite.Migration.Interfaces;
public class YourTenantProvider : ITenantProvider
{
private readonly ITenantStore _tenantStore;
public YourTenantProvider(ITenantStore tenantStore)
{
_tenantStore = tenantStore;
}
public async Task<IEnumerable<TenantInfo>> GetAllTenantsAsync(
CancellationToken cancellationToken = default)
{
// Implement your logic to retrieve all tenants
// Example: return await _tenantStore.GetAllAsync(cancellationToken);
}
}
using SaasSuite.Migration.Base;
public class AddNewColumnMigration : MigrationStepBase
{
private readonly IDbContextFactory<AppDbContext> _contextFactory;
public override string Name => "AddNewColumn";
public override string Description => "Adds a new column to the users table";
public AddNewColumnMigration(IDbContextFactory<AppDbContext> contextFactory)
{
_contextFactory = contextFactory;
}
public override async Task ExecuteAsync(string tenantId, CancellationToken cancellationToken)
{
await using var context = await _contextFactory.CreateDbContextAsync(cancellationToken);
// Set tenant context
// Execute migration logic
}
public override async Task<bool> ValidateAsync(string tenantId, CancellationToken cancellationToken)
{
await using var context = await _contextFactory.CreateDbContextAsync(cancellationToken);
// Validate migration can be applied
return true;
}
public override async Task RollbackAsync(string tenantId, CancellationToken cancellationToken)
{
await using var context = await _contextFactory.CreateDbContextAsync(cancellationToken);
// Rollback logic (optional)
}
}
using SaasSuite.Migration;
using SaasSuite.Migration.Interfaces;
public class MigrationService
{
private readonly IMigrationEngine _migrationEngine;
private readonly IEnumerable<IMigrationStep> _migrationSteps;
public MigrationService(
IMigrationEngine migrationEngine,
IEnumerable<IMigrationStep> migrationSteps)
{
_migrationEngine = migrationEngine;
_migrationSteps = migrationSteps;
}
public async Task RunMigrationAsync()
{
// Perform dry run first
var dryRunResult = await _migrationEngine.DryRunAsync(_migrationSteps);
if (!dryRunResult.IsSuccess)
{
Console.WriteLine($"Dry run failed: {dryRunResult.Errors.Count} errors");
return;
}
// Execute actual migration with progress reporting
var progress = new Progress<MigrationProgress>(p =>
{
Console.WriteLine($"Progress: {p.PercentComplete:F2}% - {p.Message}");
});
var result = await _migrationEngine.ExecuteAsync(
_migrationSteps,
progress: progress);
Console.WriteLine($"Migration completed: {result.SuccessfulTenants} successful, " +
$"{result.FailedTenants} failed");
}
}
// Load previous checkpoint
var checkpoint = await LoadCheckpointAsync();
var result = await _migrationEngine.ExecuteAsync(
_migrationSteps,
checkpoint: checkpoint);
var tenantIds = new[] { "tenant-1", "tenant-2", "tenant-3" };
var result = await _migrationEngine.ExecuteAsync(
_migrationSteps,
tenantIds: tenantIds);
var options = new MigrationOptions
{
BatchSize = 5,
EnableParallelExecution = true,
MaxDegreeOfParallelism = 2,
ContinueOnFailure = true,
TenantTimeout = TimeSpan.FromMinutes(10)
};
var result = await _migrationEngine.ExecuteAsync(
_migrationSteps,
options: options);
var affectedTenantIds = new[] { "tenant-1", "tenant-2" };
var result = await _migrationEngine.RollbackAsync(
_migrationSteps,
affectedTenantIds);
Configure the migration engine behavior through MigrationOptions:
BatchSize (default: 10)
Number of tenants to process in each batch. Adjust based on your system resources and tenant data size.
EnableParallelExecution (default: false)
Enable parallel processing of tenants within batches. Improves throughput for independent migrations.
MaxDegreeOfParallelism (default: 4)
Maximum number of parallel operations when parallel execution is enabled. Higher values increase throughput but also resource usage.
EnableCheckpointing (default: true)
Enable automatic checkpointing for resumability. Allows migrations to resume from the last successful checkpoint after interruption.
CheckpointInterval (default: 1)
Number of batches processed between checkpoint saves. Lower values provide more frequent resume points but slightly impact performance.
ContinueOnFailure (default: true)
Continue processing remaining tenants when individual tenant migrations fail. Failed tenants are tracked in the result.
TenantTimeout (default: 5 minutes)
Maximum time allowed for each tenant's migration operation. Prevents hung operations from blocking the entire migration.
EnableProgressReporting (default: true)
Enable progress callbacks for real-time monitoring. Disable to reduce overhead in high-performance scenarios.
This package is licensed under the Apache License 2.0. See the LICENSE file in the repository root for details.