From b62d25fe7304c4faeb9da3849d53e7ade407289e Mon Sep 17 00:00:00 2001 From: wassim-k Date: Mon, 22 Sep 2025 10:37:35 +1000 Subject: [PATCH] Validate GrainId Type and Key on reminder creation --- .../Multiple/MultipleMembershipCollection.cs | 27 ++++++++++++------- .../Store/Multiple/TableVersionCollection.cs | 10 +++---- .../Orleans.Providers.MongoDB.csproj | 8 +++--- .../Store/MongoReminderCollection.cs | 8 ++++++ .../StorageProviders/MongoGrainStorage.cs | 19 +------------ ...viders.MongoDB.Test.GrainInterfaces.csproj | 6 ++--- ...leans.Providers.MongoDB.Test.Grains.csproj | 6 ++--- ...Orleans.Providers.MongoDB.Test.Host.csproj | 7 +++-- Test/Host/Program.cs | 2 +- .../Orleans.Providers.MongoDB.UnitTest.csproj | 9 ++++--- 10 files changed, 53 insertions(+), 49 deletions(-) diff --git a/Orleans.Providers.MongoDB/Membership/Store/Multiple/MultipleMembershipCollection.cs b/Orleans.Providers.MongoDB/Membership/Store/Multiple/MultipleMembershipCollection.cs index c18532c..0a3d63e 100644 --- a/Orleans.Providers.MongoDB/Membership/Store/Multiple/MultipleMembershipCollection.cs +++ b/Orleans.Providers.MongoDB/Membership/Store/Multiple/MultipleMembershipCollection.cs @@ -49,7 +49,7 @@ public async Task UpsertRow(string deploymentId, MembershipEntry entry, st using var session = await Client.StartSessionAsync(); return await session.WithTransactionAsync(async (sessionHandle, ct) => { - var hasUpsertedTable = await tableVersionCollection.UpsertAsync(session, tableVersion, deploymentId); + var hasUpsertedTable = await tableVersionCollection.UpsertAsync(sessionHandle, tableVersion, deploymentId); if (!hasUpsertedTable) { @@ -106,10 +106,10 @@ public async Task ReadAll(string deploymentId) using var session = await Client.StartSessionAsync(); return await session.WithTransactionAsync(async (sessionHandle, ct) => { - var tableVersion = tableVersionCollection.GetTableVersionAsync(deploymentId); + var tableVersion = tableVersionCollection.GetTableVersionAsync(sessionHandle, deploymentId); var entries = - Collection.Find(x => x.DeploymentId == deploymentId) + Collection.Find(sessionHandle, x => x.DeploymentId == deploymentId) .ToListAsync(cancellationToken: ct); await Task.WhenAll(tableVersion, entries); @@ -123,12 +123,12 @@ public async Task ReadRow(string deploymentId, SiloAddress using var session = await Client.StartSessionAsync(); return await session.WithTransactionAsync(async (sessionHandle, ct) => { - var tableVersion = tableVersionCollection.GetTableVersionAsync(deploymentId); + var tableVersion = tableVersionCollection.GetTableVersionAsync(sessionHandle, deploymentId); var id = ReturnId(deploymentId, address); var entries = - Collection.Find(x => x.Id == id) + Collection.Find(sessionHandle, x => x.Id == id) .ToListAsync(cancellationToken: ct); await Task.WhenAll(tableVersion, entries); @@ -151,12 +151,19 @@ public Task CleanupDefunctSiloEntries(string deploymentId, DateTimeOffset before return Collection.DeleteManyAsync(x => x.DeploymentId == deploymentId && x.Status != (int)SiloStatus.Active && x.Timestamp < beforeUtc); } - public Task DeleteMembershipTableEntries(string deploymentId) + public async Task DeleteMembershipTableEntries(string deploymentId) { - return Task.WhenAll( - Collection.DeleteManyAsync(x => x.DeploymentId == deploymentId), - tableVersionCollection.DeleteAsync(deploymentId) - ); + using var session = await Client.StartSessionAsync(); + + await session.WithTransactionAsync(async (sessionHandle, ct) => + { + await Task.WhenAll( + Collection.DeleteManyAsync(sessionHandle, x => x.DeploymentId == deploymentId), + tableVersionCollection.DeleteAsync(sessionHandle, deploymentId) + ); + + return true; + }); } private static MembershipTableData ReturnMembershipTableData(IEnumerable membershipList, TableVersion tableVersion) diff --git a/Orleans.Providers.MongoDB/Membership/Store/Multiple/TableVersionCollection.cs b/Orleans.Providers.MongoDB/Membership/Store/Multiple/TableVersionCollection.cs index 8d22746..39d9953 100644 --- a/Orleans.Providers.MongoDB/Membership/Store/Multiple/TableVersionCollection.cs +++ b/Orleans.Providers.MongoDB/Membership/Store/Multiple/TableVersionCollection.cs @@ -26,14 +26,14 @@ protected override string CollectionName() return $"{collectionPrefix}OrleansMembershipV3_TableVersion"; } - public Task DeleteAsync(string deploymentId) + public Task DeleteAsync(IClientSessionHandle session, string deploymentId) { - return Collection.DeleteOneAsync(x => x.DeploymentId == deploymentId); + return Collection.DeleteOneAsync(session, x => x.DeploymentId == deploymentId); } - public async Task GetTableVersionAsync(string deploymentId) + public async Task GetTableVersionAsync(IClientSessionHandle session, string deploymentId) { - var deployment = await Collection.Find(x => x.DeploymentId == deploymentId).FirstOrDefaultAsync(); + var deployment = await Collection.Find(session, x => x.DeploymentId == deploymentId).FirstOrDefaultAsync(); if (deployment == null) { @@ -50,7 +50,7 @@ public async Task UpsertAsync(IClientSessionHandle session, TableVersion t try { await Collection.ReplaceOneAsync(session, - x => x.DeploymentId == deploymentId && x.VersionEtag == tableVersion.VersionEtag, + x => x.DeploymentId == deploymentId && x.VersionEtag == tableVersion.VersionEtag, update, UpsertReplace); diff --git a/Orleans.Providers.MongoDB/Orleans.Providers.MongoDB.csproj b/Orleans.Providers.MongoDB/Orleans.Providers.MongoDB.csproj index 658c0ca..a9765d1 100644 --- a/Orleans.Providers.MongoDB/Orleans.Providers.MongoDB.csproj +++ b/Orleans.Providers.MongoDB/Orleans.Providers.MongoDB.csproj @@ -1,11 +1,11 @@ - + net8.0 laredoza,sebastianstehle,wassim-k Orleans.Providers.MongoDB MIT - A MongoDb implementation of the Orleans Providers. This includes custering (IMembershipTable and IGatewayListProvider), reminders (IReminderTable) and storage providers (IGrainStorage). + A MongoDb implementation of the Orleans Providers. This includes clustering (IMembershipTable and IGatewayListProvider), reminders (IReminderTable) and storage providers (IGrainStorage). true false true @@ -18,12 +18,12 @@ - + all runtime; build; native; contentfiles; analyzers; buildtransitive - + diff --git a/Orleans.Providers.MongoDB/Reminders/Store/MongoReminderCollection.cs b/Orleans.Providers.MongoDB/Reminders/Store/MongoReminderCollection.cs index 4d295d9..a2ff118 100644 --- a/Orleans.Providers.MongoDB/Reminders/Store/MongoReminderCollection.cs +++ b/Orleans.Providers.MongoDB/Reminders/Store/MongoReminderCollection.cs @@ -200,6 +200,14 @@ await Collection.ReplaceOneAsync(x => x.Id == id, private static string ReturnId(string serviceId, GrainId grainId, string reminderName) { + var grainType = grainId.Type.ToString(); + var grainKey = grainId.Key.ToString(); + + if (grainType is null || grainKey is null) + { + throw new ArgumentNullException(nameof(grainId)); + } + return $"{serviceId}_{grainId}_{reminderName}"; } } diff --git a/Orleans.Providers.MongoDB/StorageProviders/MongoGrainStorage.cs b/Orleans.Providers.MongoDB/StorageProviders/MongoGrainStorage.cs index ded213e..136cdcc 100644 --- a/Orleans.Providers.MongoDB/StorageProviders/MongoGrainStorage.cs +++ b/Orleans.Providers.MongoDB/StorageProviders/MongoGrainStorage.cs @@ -1,6 +1,5 @@ using System; using System.Collections.Concurrent; -using System.Threading; using System.Threading.Tasks; using Microsoft.Extensions.Logging; using MongoDB.Driver; @@ -12,14 +11,13 @@ namespace Orleans.Providers.MongoDB.StorageProviders { - public class MongoGrainStorage : IGrainStorage, ILifecycleParticipant + public class MongoGrainStorage : IGrainStorage { private readonly ConcurrentDictionary collections = new ConcurrentDictionary(); private readonly MongoDBGrainStorageOptions options; private readonly IMongoClient mongoClient; private readonly ILogger logger; private readonly IGrainStateSerializer serializer; - private IMongoDatabase database; public MongoGrainStorage( IMongoClientFactory mongoClientFactory, @@ -32,21 +30,6 @@ public MongoGrainStorage( this.serializer = options.GrainStateSerializer; } - public void Participate(ISiloLifecycle lifecycle) - { - lifecycle.Subscribe(ServiceLifecycleStage.ApplicationServices, Init); - } - - private Task Init(CancellationToken ct) - { - return DoAndLog(nameof(Init), () => - { - database = mongoClient.GetDatabase(options.DatabaseName); - - return Task.CompletedTask; - }); - } - public Task ReadStateAsync(string stateName, GrainId grainId, IGrainState grainState) { return DoAndLog(nameof(ReadStateAsync), () => diff --git a/Test/GrainInterfaces/Orleans.Providers.MongoDB.Test.GrainInterfaces.csproj b/Test/GrainInterfaces/Orleans.Providers.MongoDB.Test.GrainInterfaces.csproj index 2ce7989..3ff8bd1 100644 --- a/Test/GrainInterfaces/Orleans.Providers.MongoDB.Test.GrainInterfaces.csproj +++ b/Test/GrainInterfaces/Orleans.Providers.MongoDB.Test.GrainInterfaces.csproj @@ -6,9 +6,9 @@ - - - + + + diff --git a/Test/Grains/Orleans.Providers.MongoDB.Test.Grains.csproj b/Test/Grains/Orleans.Providers.MongoDB.Test.Grains.csproj index 994288a..49e911a 100644 --- a/Test/Grains/Orleans.Providers.MongoDB.Test.Grains.csproj +++ b/Test/Grains/Orleans.Providers.MongoDB.Test.Grains.csproj @@ -6,9 +6,9 @@ - - - + + + diff --git a/Test/Host/Orleans.Providers.MongoDB.Test.Host.csproj b/Test/Host/Orleans.Providers.MongoDB.Test.Host.csproj index 3966760..95b5eed 100644 --- a/Test/Host/Orleans.Providers.MongoDB.Test.Host.csproj +++ b/Test/Host/Orleans.Providers.MongoDB.Test.Host.csproj @@ -1,4 +1,4 @@ - + Exe @@ -8,7 +8,10 @@ - + + + + diff --git a/Test/Host/Program.cs b/Test/Host/Program.cs index 0521380..dc8a4b8 100644 --- a/Test/Host/Program.cs +++ b/Test/Host/Program.cs @@ -25,7 +25,7 @@ public static async Task Main(string[] args) { var createShardKey = false; - using var mongoRunner = MongoRunner.Run(new MongoRunnerOptions { KillMongoProcessesWhenCurrentProcessExits = true }); + using var mongoRunner = MongoRunner.Run(); Console.WriteLine("MongoDB ConnectionString: {0}", mongoRunner.ConnectionString); diff --git a/UnitTest/Orleans.Providers.MongoDB.UnitTest.csproj b/UnitTest/Orleans.Providers.MongoDB.UnitTest.csproj index 4b13987..1da9f04 100644 --- a/UnitTest/Orleans.Providers.MongoDB.UnitTest.csproj +++ b/UnitTest/Orleans.Providers.MongoDB.UnitTest.csproj @@ -1,4 +1,4 @@ - + net8.0 true @@ -9,8 +9,11 @@ - - + + + + +