Repository navigation
feat(google): add Google Cloud Firestore providers - #8462
Conversation
f8617a7 to
3c1a182
Compare
94bb87c to
dc23a2d
Compare
abf6661 to
b18afca
Compare
b18afca to
e8effb8
Compare
There was a problem hiding this comment.
Pull request overview
Adds a new set of Orleans providers backed by Google Cloud Firestore (clustering, reminders, persistence, and grain directory), along with a dedicated test project and CI job to run against local Google emulators.
Changes:
- Introduces new Firestore-backed provider projects under
src/Google/(shared Firestore data manager + provider implementations + hosting extensions). - Adds
Orleans.Tests.Googletest project with emulator helpers and functional/stress tests for the new providers. - Wires the new projects into the solution, package versions, InternalsVisibleTo, and GitHub Actions CI.
Show a summary per file
| File | Description |
|---|---|
| test/TestInfrastructure/TestExtensions/TestExtensions.csproj | Grants internals access to new Orleans.Tests.Google test assembly. |
| test/Orleans.Runtime.Internal.Tests/RemindersTest/ReminderTableTestsBase.cs | Adjusts reminder tests to align with new provider behavior and grain id creation. |
| test/Orleans.Runtime.Internal.Tests/Orleans.Runtime.Internal.Tests.csproj | Grants internals access to new Orleans.Tests.Google test assembly. |
| test/Orleans.Runtime.Internal.Tests/MembershipTests/MembershipTableTestsBase.cs | Makes shared membership test state accessible to derived provider tests. |
| test/Grains/TestInternalGrains/PersistenceTestGrains.cs | Adds Google Firestore storage test grains. |
| test/Grains/TestGrainInterfaces/IPersistenceTestGrains.cs | Adds interfaces for Google Firestore storage test grains. |
| test/Extensions/Google.Tests/Usings.cs | Adds global xUnit using for Google tests project. |
| test/Extensions/Google.Tests/Reminders/FirestoreRemindersTests.cs | Adds reminder table tests for Firestore reminders provider. |
| test/Extensions/Google.Tests/Persistence/FirestoreStorageProviderTests.cs | Adds direct IGrainStorage tests for Firestore storage provider. |
| test/Extensions/Google.Tests/Persistence/FirestorePersistenceGrainTests.cs | Adds cluster-level persistence grain tests using Firestore storage. |
| test/Extensions/Google.Tests/Persistence/Base_PersistenceGrainTests_GoogleStorage.cs | Shared base test suite for Firestore persistence grain tests and perf/stress tests. |
| test/Extensions/Google.Tests/GrainDirectory/FirestoreGrainDirectoryTests.cs | Adds grain directory tests for Firestore grain directory implementation. |
| test/Extensions/Google.Tests/Google.Tests.csproj | New Google tests project wiring provider references and shared linked sources. |
| test/Extensions/Google.Tests/FirestoreDataManagerTests.cs | Unit tests for shared FirestoreDataManager behavior (CRUD/query/batch). |
| test/Extensions/Google.Tests/FirestoreDataManagerStressTest.cs | Stress-style tests for FirestoreDataManager high-volume upserts. |
| test/Extensions/Google.Tests/Emulators/storage.rules | Firebase storage emulator rules used for local test emulators. |
| test/Extensions/Google.Tests/Emulators/GoogleEmulatorHost.cs | Helper to detect emulator availability and set emulator env vars. |
| test/Extensions/Google.Tests/Emulators/firebase.json | Emulator configuration used by firebase tools. |
| test/Extensions/Google.Tests/Emulators/EmulatorTest.cs | Sanity checks that emulator is reachable and Firestore SDK can interact. |
| test/Extensions/Google.Tests/Emulators/Emulators.md | Documentation for running Google emulators locally for tests. |
| test/Extensions/Google.Tests/Emulators/.firebaserc | Firebase emulator project configuration. |
| test/Extensions/Google.Tests/Clustering/FirestoreSiloInstanceManagerTests.cs | Tests for Firestore-based membership manager behavior. |
| test/Extensions/Google.Tests/Clustering/FirestoreMembershipTableTests.cs | Membership/gateway tests for Firestore clustering provider. |
| src/Orleans.TestingHost/Orleans.TestingHost.csproj | Grants internals access to new Orleans.Tests.Google test assembly. |
| src/Orleans.Core/Orleans.Core.csproj | Grants internals access to new Orleans.Tests.Google test assembly. |
| src/Google/Shared/Utils/Utils.cs | Shared helpers (timestamp formatting, id sanitization, grain id encoding). |
| src/Google/Shared/Storage/GoogleCloudOptions.cs | Base options for Google Cloud provider configuration. |
| src/Google/Shared/Storage/FirestoreOptions.cs | Firestore-specific options + validation. |
| src/Google/Shared/Storage/FirestoreEntity.cs | Base Firestore entity abstraction (Id/ETag + update fields). |
| src/Google/Shared/Storage/FirestoreDataManager.cs | Core Firestore CRUD/query/batch/transaction abstraction used by providers. |
| src/Google/Orleans.Reminders.GoogleFirestore/ReminderEntity.cs | Firestore entity model for reminders. |
| src/Google/Orleans.Reminders.GoogleFirestore/Orleans.Reminders.GoogleFirestore.csproj | New Firestore reminders provider project packaging and dependencies. |
| src/Google/Orleans.Reminders.GoogleFirestore/GoogleFirestoreReminderTable.cs | Firestore implementation of IReminderTable. |
| src/Google/Orleans.Reminders.GoogleFirestore/GoogleFirestoreReminderServiceExtensions.cs | Hosting/service collection extensions for Firestore reminders provider. |
| src/Google/Orleans.Persistence.GoogleFirestore/Orleans.Persistence.GoogleFirestore.csproj | New Firestore persistence provider project packaging and dependencies. |
| src/Google/Orleans.Persistence.GoogleFirestore/GrainStateEntity.cs | Firestore entity model for persisted grain state. |
| src/Google/Orleans.Persistence.GoogleFirestore/GoogleFirestoreStorage.cs | Firestore implementation of IGrainStorage with lifecycle participation. |
| src/Google/Orleans.Persistence.GoogleFirestore/FirestoreStorageHostingExtensions.cs | Hosting extensions to register Firestore grain storage provider. |
| src/Google/Orleans.Persistence.GoogleFirestore/FirestoreStateStorageOptions.cs | Persistence options and configuration validator for Firestore storage. |
| src/Google/Orleans.GrainDirectory.GoogleFirestore/Orleans.GrainDirectory.GoogleFirestore.csproj | New Firestore grain directory provider project packaging and dependencies. |
| src/Google/Orleans.GrainDirectory.GoogleFirestore/GrainDirectoryEntity.cs | Firestore entity model for grain directory entries. |
| src/Google/Orleans.GrainDirectory.GoogleFirestore/GoogleFirestoreGrainDirectoryExtensions.cs | Hosting extensions to register Firestore grain directory provider. |
| src/Google/Orleans.GrainDirectory.GoogleFirestore/GoogleFirestoreGrainDirectory.cs | Firestore implementation of IGrainDirectory. |
| src/Google/Orleans.Clustering.GoogleFirestore/SiloInstanceEntity.cs | Firestore entity model for membership entries. |
| src/Google/Orleans.Clustering.GoogleFirestore/OrleansSiloInstanceManager.cs | Firestore membership table manager (version row, conditional updates, cleanup). |
| src/Google/Orleans.Clustering.GoogleFirestore/Orleans.Clustering.GoogleFirestore.csproj | New Firestore clustering provider project packaging and dependencies. |
| src/Google/Orleans.Clustering.GoogleFirestore/MembershipEntity.cs | Base membership entity model (cluster id + fields). |
| src/Google/Orleans.Clustering.GoogleFirestore/GoogleFirestoreMembershipTable.cs | Firestore implementation of IMembershipTable. |
| src/Google/Orleans.Clustering.GoogleFirestore/GoogleFirestoreGatewayListProvider.cs | Firestore implementation of IGatewayListProvider. |
| src/Google/Orleans.Clustering.GoogleFirestore/GoogleFirestoreClusteringExtensions.cs | Hosting extensions to register Firestore clustering provider. |
| src/Google/Orleans.Clustering.GoogleFirestore/ClusterVersionEntity.cs | Firestore entity model for membership table version row. |
| Orleans.slnx | Adds the new Google provider and test projects to the solution. |
| Directory.Packages.props | Adds Firestore/Storage/PubSub package versions and updates PubSub version. |
| .github/workflows/ci.yml | Adds a dedicated CI job to run Google provider tests with emulators. |
Copilot's findings
Suppressed comments (2)
test/Extensions/Google.Tests/FirestoreDataManagerStressTest.cs:72
- The final Task.WhenAll(promises) result is not awaited/observed, so outstanding upserts may still be running when the test logs completion (and failures can be missed).
src/Google/Orleans.Reminders.GoogleFirestore/GoogleFirestoreReminderServiceExtensions.cs:80 - The XML docs say "Azure Table Storage" but this overload configures the Google Firestore reminder service.
/// <summary>
/// Adds reminder storage backed by Azure Table Storage.
/// </summary>
- Files reviewed: 54/54 changed files
- Comments generated: 13
There was a problem hiding this comment.
Copilot's findings
Suppressed comments (11)
test/Extensions/Google.Tests/FirestoreDataManagerStressTest.cs:63
Task.WhenAll(promises)is not awaited, so the batch can still be running (and exceptions can be dropped) when the test proceeds/finishes.
src/Google/Shared/Storage/FirestoreDataManager.cs:260- This log statement is guarded by
IsEnabled(LogLevel.Debug)but usesLogTrace, which will typically be disabled when Debug is enabled (min level Debug). As a result, the message will not be emitted.
if (this.Logger.IsEnabled(LogLevel.Debug)) this.Logger.LogTrace("Entity {id} not found on collection {collection}", id, this._partition);
test/Extensions/Google.Tests/FirestoreDataManagerStressTest.cs:69
- Final
Task.WhenAll(promises)is not awaited, so the method can return before completing outstanding writes (and exceptions can be dropped).
src/Google/Shared/Storage/FirestoreDataManager.cs:357 - This log statement is guarded by
IsEnabled(LogLevel.Debug)but usesLogTrace, so it will not be emitted when the minimum log level is Debug.
if (this.Logger.IsEnabled(LogLevel.Debug)) this.Logger.LogTrace("No entities found on collection {collection}", this._partition);
src/Google/Orleans.Reminders.GoogleFirestore/Orleans.Reminders.GoogleFirestore.csproj:6
- Package metadata refers to "Google Cloud Storage" even though this project is a Firestore-backed reminders provider. This is user-visible (NuGet) and should be corrected to Firestore.
<PackageId>Microsoft.Orleans.Reminders.GoogleFirestore</PackageId>
<Title>Microsoft Orleans Google Cloud Storage Reminders Provider</Title>
<Description>Microsoft Orleans reminders provider backed by Google Cloud Storage</Description>
<PackageTags>$(PackageTags) Google Cloud Storage</PackageTags>
src/Google/Orleans.GrainDirectory.GoogleFirestore/Orleans.GrainDirectory.GoogleFirestore.csproj:5
- Spelling: "GrainD irectory" contains an unintended space.
<Description>Microsoft Orleans GrainD irectory provider backed by Google Firestore</Description>
.github/workflows/ci.yml:1008
- This job installs .NET SDKs 3.1 and 7.0, but the repo’s other CI jobs use
global-json-file: global.jsonand the solution targets newer frameworks. As written, this job is likely to fail or use the wrong SDK.
- name: Setup .NET
uses: actions/setup-dotnet@v3
with:
dotnet-version: |
3.1.x
7.0.x
- name: Setup Google Emulators
src/Google/Shared/Storage/FirestoreDataManager.cs:291
- This log statement is guarded by
IsEnabled(LogLevel.Debug)but usesLogTrace, so it will not be emitted when the minimum log level is Debug.
This issue also appears on line 357 of the same file.
if (this.Logger.IsEnabled(LogLevel.Debug)) this.Logger.LogTrace("No entities found on collection {collection}", this._partition);
src/Google/Orleans.GrainDirectory.GoogleFirestore/GoogleFirestoreGrainDirectory.cs:67
- Catching all
RpcExceptionhere will hide non-contention failures (eg, Unavailable/PermissionDenied) and return potentially stale data fromLookupinstead of surfacing the error. This should only fall back toLookupfor the expected create-contention case.
catch (RpcException)
{
var result = await this.Lookup(address.GrainId);
return result;
}
src/Google/Orleans.Persistence.GoogleFirestore/FirestoreStateStorageOptions.cs:10
- Grammar: "clears it's state" should use the possessive "its".
/// Indicates if grain data should be deleted or reset to defaults when a grain clears it's state.
src/Google/Orleans.Persistence.GoogleFirestore/FirestoreStateStorageOptions.cs:46
FirestoreStateStorageOptionsinheritsFirestoreOptions(which already hasValidate(...)including reserved-name checks), but this validator only checks for whitespace. This can allow invalid configuration through and fail later at runtime.
public void ValidateConfiguration()
{
if (string.IsNullOrWhiteSpace(this.options.ProjectId))
throw new OrleansConfigurationException(
$"Configuration for GoogleFirestoreStorage {this.name} is invalid. {nameof(this.options.ProjectId)} is not valid.");
if (string.IsNullOrWhiteSpace(this.options.RootCollectionName))
throw new OrleansConfigurationException(
$"Configuration for GoogleFirestoreStorage {this.name} is invalid. {nameof(this.options.RootCollectionName)} is not valid.");
}
- Files reviewed: 55/55 changed files
- Comments generated: 0 new
This PR adds Google Cloud (GCP) providers to Orleans:
The documents in Firestore for the Cluster/Storage/Reminder providers follow the structure bellow:
Orleans (Root collection)
-- Clustering (doc)
--> ClusterId (sub-collection)
----> ClusterVersionEntity (doc)
----> SiloInstanceEntity (doc)
-- Persistence (doc)
--> ServiceId (sub-collection)
----> GrainStateEntity (doc)
-- Reminders (doc)
--> ServiceId (sub-collection)
----> ReminderEntity (doc)
-- GrainDirectory (doc)
--> ClusterId (sub-collection)
----> GrainDirectoryEntity (doc)
Microsoft Reviewers: Open in CodeFlow