Skip to content

feat: add file-based grain storage provider - #9537

Merged
ReubenBond merged 8 commits into
dotnet:mainfrom
BernhardPollerspoeck:FileStorageProvider
Aug 23, 2026
Merged

ReubenBond merged 8 commits into
dotnet:mainfrom
BernhardPollerspoeck:FileStorageProvider

Conversation

@BernhardPollerspoeck

@BernhardPollerspoeck BernhardPollerspoeck commented Jun 2, 2025 •

Copy link
Copy Markdown
Contributor

This pull request introduces a new file-based grain storage provider for Microsoft Orleans. The changes include adding a new project for the provider, implementing its core functionality, and providing documentation and configuration examples.

New File-Based Grain Storage Provider

Project Setup:

  • Added a new project Orleans.Persistence.FileStorage to the solution with the necessary project references and metadata (Orleans.sln, src/File/Orleans.Persistence.FileStorage/Orleans.Persistence.FileStorage.csproj) [1] [2].

Core Implementation:

  • Implemented the FileGrainStorage class, which provides methods for reading, writing, and clearing grain state using a file-based approach (src/File/Orleans.Persistence.FileStorage/FileGrainStorage.cs).
  • Added a factory class FileGrainStorageFactory to create instances of FileGrainStorage (src/File/Orleans.Persistence.FileStorage/FileGrainStorageFactory.cs).
  • Created FileGrainStorageOptions to configure the root directory and serializer for the storage provider (src/File/Orleans.Persistence.FileStorage/FileGrainStorageOptions.cs).
  • Added extension methods in FileSiloBuilderExtensions to simplify the configuration of the file storage provider in Orleans silo builders (src/File/Orleans.Persistence.FileStorage/FileSiloBuilderExtensions.cs).

Documentation and Examples:

  • Added a README.md file with an introduction, setup instructions, and examples for configuring and using the file storage provider (src/File/Orleans.Persistence.FileStorage/README.md).
Microsoft Reviewers: Open in CodeFlow

@BernhardPollerspoeck

Copy link
Copy Markdown
Contributor Author

@dotnet-policy-service agree

@shacal

shacal commented Jun 2, 2025

Copy link
Copy Markdown

👍🏻

Comment thread src/File/Orleans.Persistence.FileStorage/FileGrainStorage.cs Outdated
Comment thread src/File/Orleans.Persistence.FileStorage/FileGrainStorageOptions.cs Outdated
Comment thread src/File/Orleans.Persistence.FileStorage/FileGrainStorage.cs Outdated
@BernhardPollerspoeck

Copy link
Copy Markdown
Contributor Author

I need to find the time to get more information about your suggested changes. i am not that deep into the details you mention and i dont want to submit changes i dont understand.
@shacal @willg1983

@galvesribeiro

Copy link
Copy Markdown
Member

Hey! Interesting.

Is this meant to be used in a single silo or by having shared storage like NFS/SMB/EFS? Or do you plan on have some sort of replication/synchronization/distributed locking on the files itself?

I'm interested on what would happen when silos are scaled. Can you elaborate more on that on the PR itself and/or the README you added?

Thanks!

@BernhardPollerspoeck

Copy link
Copy Markdown
Contributor Author

Hey @galvesribeiro,

in the beginning it was meant to be some more single silo or on prem local smaller solution. I got a few great comments for possible improvements, but they maybe just dont match what this storage provider wants to be. Im gonna need to think and have some talks with @ReubenBond and his team on what we really should aim for.
I had some really bad lack of time but i hope in the course of this week its getting easier and then i plan on getting this PR ready for review.

@ReubenBond ReubenBond changed the title File Based Storage Provider feat: add file-based grain storage provider Aug 21, 2026
@ReubenBond
ReubenBond marked this pull request as ready for review August 21, 2026 22:28
@ReubenBond
ReubenBond self-requested a review as a code owner August 21, 2026 22:28
Copilot AI lite review requested due to automatic review settings August 21, 2026 22:28

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

This PR introduces a new file-based grain storage provider (Orleans.Persistence.FileStorage) for Orleans, including the provider implementation, DI/hosting extensions, packaging metadata, and a README with usage examples.

Changes:

  • Added a new persistence provider project/package (Microsoft.Orleans.Persistence.FileStorage) and included it in the solution.
  • Implemented the provider (read/write/clear + factory/options) and exposed AddFileGrainStorage(...) builder/service-collection extensions.
  • Added initial end-user documentation (README.md) with configuration and usage examples.
Show a summary per file
File Description
Orleans.sln Adds the new project to the solution under a new “File” solution folder.
src/File/Orleans.Persistence.FileStorage/Orleans.Persistence.FileStorage.csproj Defines the new package/project metadata and references.
src/File/Orleans.Persistence.FileStorage/FileSiloBuilderExtensions.cs Adds DI/hosting extension methods for configuring the provider.
src/File/Orleans.Persistence.FileStorage/FileGrainStorageOptions.cs Introduces options for root directory + serializer selection.
src/File/Orleans.Persistence.FileStorage/FileGrainStorageFactory.cs Factory to construct provider instances from DI + named options.
src/File/Orleans.Persistence.FileStorage/FileGrainStorage.cs Core file-backed implementation of IGrainStorage + lifecycle init.
src/File/Orleans.Persistence.FileStorage/README.md Documents installation and provides configuration/usage examples.

Review details

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Suppressed comments (2)

src/File/Orleans.Persistence.FileStorage/FileGrainStorage.cs:68

  • ReadStateAsync reads the state file as text (OpenText/ReadToEndAsync) and then constructs BinaryData from a string. Since WriteStateAsync writes raw bytes, this will corrupt non-text payloads and can fail depending on encoding. Also, when the file is missing, ETag/RecordExists should be reset to avoid leaking previous values.
        using var stream = fileInfo.OpenText();
        var storedData = await stream.ReadToEndAsync();

        grainState.State = options.GrainStorageSerializer.Deserialize<T>(new BinaryData(storedData));
        grainState.ETag = fileInfo.LastWriteTimeUtc.ToString(CultureInfo.InvariantCulture);
        grainState.RecordExists = true;

src/File/Orleans.Persistence.FileStorage/FileGrainStorage.cs:96

  • WriteStateAsync updates grainState.ETag but never sets grainState.RecordExists=true after a successful write, and it formats the ETag using DateTime.ToString(InvariantCulture), which can lose precision and cause missed conflict detection.
        if (fileInfo.Exists && fileInfo.LastWriteTimeUtc.ToString(CultureInfo.InvariantCulture) != grainState.ETag)
        {
            throw new InconsistentStateException($"""
                Version conflict (WriteState): ServiceId={_clusterOptions.ServiceId}
                ProviderName={storageName} GrainType={typeof(T)}
                GrainReference={grainId}.
                """);
        }

        await File.WriteAllBytesAsync(path, storedData.ToArray());

        fileInfo.Refresh();
        grainState.ETag = fileInfo.LastWriteTimeUtc.ToString(CultureInfo.InvariantCulture);
    }
  • Files reviewed: 7/7 changed files
  • Comments generated: 7
  • Review effort level: Lite

Comment thread src/File/Orleans.Persistence.FileStorage/FileGrainStorage.cs Outdated
Comment thread src/File/Orleans.Persistence.FileStorage/FileGrainStorage.cs Outdated
Comment thread src/File/Orleans.Persistence.FileStorage/FileGrainStorage.cs Outdated
Comment thread src/File/Orleans.Persistence.FileStorage/README.md Outdated
Comment thread src/File/Orleans.Persistence.FileStorage/README.md Outdated
Comment thread src/File/Orleans.Persistence.FileStorage/FileGrainStorage.cs
@ReubenBond
ReubenBond force-pushed the FileStorageProvider branch from 7126d93 to 068ba21 Compare August 21, 2026 23:21
@ReubenBond
ReubenBond force-pushed the FileStorageProvider branch from d7b554e to a9f6eb1 Compare August 22, 2026 15:40
@github-actions

github-actions Bot commented Aug 22, 2026 •

Copy link
Copy Markdown
Contributor

Code coverage

51.93% line coverage - 52,484 / 101,072 lines

Coverage details

@github-actions github-actions Bot locked and limited conversation to collaborators Sep 22, 2026
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants