diff --git a/Orleans.slnx b/Orleans.slnx
index 14b09df46ac..58a75bb99b7 100644
--- a/Orleans.slnx
+++ b/Orleans.slnx
@@ -103,9 +103,6 @@
-
-
-
@@ -144,6 +141,7 @@
+
@@ -182,7 +180,6 @@
-
diff --git a/docs/site/src/content/docs/resources/nuget-packages.md b/docs/site/src/content/docs/resources/nuget-packages.md
index b610d46bc98..30dca3704f7 100644
--- a/docs/site/src/content/docs/resources/nuget-packages.md
+++ b/docs/site/src/content/docs/resources/nuget-packages.md
@@ -56,11 +56,12 @@ Every multi-silo production cluster needs a shared membership provider.
| [Microsoft.Orleans.Persistence.AzureStorage](https://www.nuget.org/packages/Microsoft.Orleans.Persistence.AzureStorage) | Azure Table and Blob Storage |
| [Microsoft.Orleans.Persistence.Cosmos](https://www.nuget.org/packages/Microsoft.Orleans.Persistence.Cosmos) | Azure Cosmos DB |
| [Microsoft.Orleans.Persistence.DynamoDB](https://www.nuget.org/packages/Microsoft.Orleans.Persistence.DynamoDB) | Amazon DynamoDB |
-| [Microsoft.Orleans.Persistence.FileStorage](https://www.nuget.org/packages/Microsoft.Orleans.Persistence.FileStorage) | Local files for single-silo development and testing |
| [Microsoft.Orleans.Persistence.Firestore](https://www.nuget.org/packages/Microsoft.Orleans.Persistence.Firestore) | Google Cloud Firestore |
| [Microsoft.Orleans.Persistence.Redis](https://www.nuget.org/packages/Microsoft.Orleans.Persistence.Redis) | Redis |
| [Microsoft.Orleans.Persistence.Memory](https://www.nuget.org/packages/Microsoft.Orleans.Persistence.Memory) | Process memory for development and testing |
+File storage for local, single-silo development and testing is included in [Microsoft.Orleans.Runtime](https://www.nuget.org/packages/Microsoft.Orleans.Runtime).
+
Memory persistence distributes records across cluster storage grains but isn't durable or replicated. Use it only when losing records with a hosting process is acceptable.
## Reminders and durable jobs
diff --git a/docs/site/src/data/external-link-allowlist.json b/docs/site/src/data/external-link-allowlist.json
index 67ec3717000..82e8882d8a9 100644
--- a/docs/site/src/data/external-link-allowlist.json
+++ b/docs/site/src/data/external-link-allowlist.json
@@ -12,7 +12,6 @@
"https://www.nuget.org/packages/Microsoft.Orleans.Clustering.Firestore": "The new Firestore clustering package is documented but not yet published; remove this entry and its unpublished API-package entry after publication.",
"https://www.nuget.org/packages/Microsoft.Orleans.GrainDirectory.Firestore": "The new Firestore grain-directory package is documented but not yet published; remove this entry and its unpublished API-package entry after publication.",
"https://www.nuget.org/packages/Microsoft.Orleans.Journaling.Redis": "The new Redis journaling package is documented but not yet published; remove this entry and its unpublished API-package entry after publication.",
- "https://www.nuget.org/packages/Microsoft.Orleans.Persistence.FileStorage": "The new file storage persistence package is documented but not yet published; remove this entry and its unpublished API-package entry after publication.",
"https://www.nuget.org/packages/Microsoft.Orleans.Persistence.Firestore": "The new Firestore persistence package is documented but not yet published; remove this entry and its unpublished API-package entry after publication.",
"https://www.nuget.org/packages/Microsoft.Orleans.Reminders.Firestore": "The new Firestore reminders package is documented but not yet published; remove this entry and its unpublished API-package entry after publication.",
"https://www.nuget.org/packages/Microsoft.Orleans.Streaming.Kinesis": "The new Kinesis streaming package is documented but not yet published; remove this entry and its unpublished API-package entry after publication.",
diff --git a/docs/site/src/data/unpublished-api-packages.json b/docs/site/src/data/unpublished-api-packages.json
index b02adbf910c..c49eb353d4e 100644
--- a/docs/site/src/data/unpublished-api-packages.json
+++ b/docs/site/src/data/unpublished-api-packages.json
@@ -4,7 +4,6 @@
"Microsoft.Orleans.Clustering.Firestore": "The new provider is awaiting its first NuGet publication.",
"Microsoft.Orleans.GrainDirectory.Firestore": "The new provider is awaiting its first NuGet publication.",
"Microsoft.Orleans.Journaling.Redis": "The new provider is awaiting its first NuGet publication.",
- "Microsoft.Orleans.Persistence.FileStorage": "The new provider is awaiting its first NuGet publication.",
"Microsoft.Orleans.Persistence.Firestore": "The new provider is awaiting its first NuGet publication.",
"Microsoft.Orleans.Reminders.Firestore": "The new provider is awaiting its first NuGet publication.",
"Microsoft.Orleans.Streaming.Kinesis": "The new provider is awaiting its first NuGet publication."
diff --git a/src/File/Orleans.Persistence.FileStorage/Orleans.Persistence.FileStorage.csproj b/src/File/Orleans.Persistence.FileStorage/Orleans.Persistence.FileStorage.csproj
deleted file mode 100644
index 7d81a7ab87d..00000000000
--- a/src/File/Orleans.Persistence.FileStorage/Orleans.Persistence.FileStorage.csproj
+++ /dev/null
@@ -1,25 +0,0 @@
-
-
- Microsoft.Orleans.Persistence.FileStorage
- Microsoft Orleans File Persistence Provider
- Microsoft Orleans persistence providers backed by File Storage
- $(PackageTags) FileStorage
- $(DefaultTargetFrameworks)
- true
- README.md
-
-
-
- Orleans.Persistence.FileStorage
- Orleans.Persistence.FileStorage
- $(DefineConstants);PERSISTENCE_FILESTORAGE
-
-
-
-
-
-
-
-
-
-
diff --git a/src/File/Orleans.Persistence.FileStorage/README.md b/src/File/Orleans.Persistence.FileStorage/README.md
deleted file mode 100644
index 42bd194e6e8..00000000000
--- a/src/File/Orleans.Persistence.FileStorage/README.md
+++ /dev/null
@@ -1,64 +0,0 @@
-# Microsoft Orleans persistence for file storage
-
-This package stores Orleans grain state as files in a configured directory. It is intended for local, single-silo development and testing. The provider does not replicate state or coordinate access through shared or network filesystems, so it is not production-ready.
-
-## Install
-
-```shell
-dotnet add package Microsoft.Orleans.Persistence.FileStorage
-```
-
-## Configure the provider
-
-```csharp
-using Microsoft.Extensions.Hosting;
-using Orleans.Hosting;
-using Orleans.Persistence.FileStorage;
-
-var builder = Host.CreateApplicationBuilder(args);
-
-builder.UseOrleans(siloBuilder =>
-{
- siloBuilder
- .UseLocalhostClustering()
- .AddFileGrainStorage(
- providerName: "FileStorage",
- options => options.RootDirectory = Path.Combine(
- AppContext.BaseDirectory,
- "Orleans",
- "GrainState"));
-});
-
-await builder.Build().RunAsync();
-```
-
-Use the same provider name when injecting persistent state:
-
-```csharp
-using Orleans.Runtime;
-
-public sealed class MyGrain(
- [PersistentState("state", "FileStorage")]
- IPersistentState state) : Grain, IMyGrain
-{
- public async Task SetData(string data)
- {
- state.State.Data = data;
- state.State.Version++;
- await state.WriteStateAsync();
- }
-
- public Task GetData() => Task.FromResult(state.State.Data);
-}
-
-public sealed class MyGrainState
-{
- public string Data { get; set; } = string.Empty;
-
- public int Version { get; set; }
-}
-```
-
-The provider stores one binary file per grain state record and uses persisted ETags for basic optimistic concurrency checks. It does not coordinate multiple silos or replicate data.
-
-For Orleans persistence concepts, see [Grain persistence](https://learn.microsoft.com/dotnet/orleans/grains/grain-persistence).
diff --git a/src/File/Orleans.Persistence.FileStorage/FileGrainStorage.cs b/src/Orleans.Runtime/Persistence/FileStorage/FileGrainStorage.cs
similarity index 100%
rename from src/File/Orleans.Persistence.FileStorage/FileGrainStorage.cs
rename to src/Orleans.Runtime/Persistence/FileStorage/FileGrainStorage.cs
diff --git a/src/File/Orleans.Persistence.FileStorage/FileGrainStorageFactory.cs b/src/Orleans.Runtime/Persistence/FileStorage/FileGrainStorageFactory.cs
similarity index 100%
rename from src/File/Orleans.Persistence.FileStorage/FileGrainStorageFactory.cs
rename to src/Orleans.Runtime/Persistence/FileStorage/FileGrainStorageFactory.cs
diff --git a/src/File/Orleans.Persistence.FileStorage/FileGrainStorageOptions.cs b/src/Orleans.Runtime/Persistence/FileStorage/FileGrainStorageOptions.cs
similarity index 100%
rename from src/File/Orleans.Persistence.FileStorage/FileGrainStorageOptions.cs
rename to src/Orleans.Runtime/Persistence/FileStorage/FileGrainStorageOptions.cs
diff --git a/src/File/Orleans.Persistence.FileStorage/FileSiloBuilderExtensions.cs b/src/Orleans.Runtime/Persistence/FileStorage/FileSiloBuilderExtensions.cs
similarity index 100%
rename from src/File/Orleans.Persistence.FileStorage/FileSiloBuilderExtensions.cs
rename to src/Orleans.Runtime/Persistence/FileStorage/FileSiloBuilderExtensions.cs
diff --git a/src/Orleans.Runtime/README.md b/src/Orleans.Runtime/README.md
index 53f07c301ea..522ef5f021b 100644
--- a/src/Orleans.Runtime/README.md
+++ b/src/Orleans.Runtime/README.md
@@ -12,6 +12,20 @@ dotnet add package Microsoft.Orleans.Runtime
This package is automatically included when you reference the Orleans Server metapackage.
+## File grain storage
+
+The runtime includes a file-based grain storage provider for local, single-silo development and testing. It stores one binary file per grain state record and uses persisted ETags for optimistic concurrency.
+
+```csharp
+using Orleans.Persistence.FileStorage;
+
+siloBuilder.AddFileGrainStorage(
+ options: options => options.RootDirectory = Path.Combine(
+ AppContext.BaseDirectory,
+ "Orleans",
+ "GrainState"));
+```
+
## Example - Configuring a Silo
```csharp
diff --git a/src/api/Orleans.Runtime/Orleans.Runtime.cs b/src/api/Orleans.Runtime/Orleans.Runtime.cs
index 1da14d96b50..b8b8d347716 100644
--- a/src/api/Orleans.Runtime/Orleans.Runtime.cs
+++ b/src/api/Orleans.Runtime/Orleans.Runtime.cs
@@ -525,6 +525,40 @@ public GrainClassMap(Serialization.TypeSystem.TypeConverter typeConverter, Syste
}
}
+namespace Orleans.Persistence.FileStorage
+{
+ public sealed partial class FileGrainStorage : Storage.IGrainStorage, ILifecycleParticipant
+ {
+ public FileGrainStorage(string storageName, FileGrainStorageOptions options, Microsoft.Extensions.Options.IOptions clusterOptions, Serialization.Serializers.IActivatorProvider activatorProvider) { }
+
+ public System.Threading.Tasks.Task ClearStateAsync(string stateName, Runtime.GrainId grainId, IGrainState grainState) { throw null; }
+
+ public void Participate(Runtime.ISiloLifecycle lifecycle) { }
+
+ public System.Threading.Tasks.Task ReadStateAsync(string stateName, Runtime.GrainId grainId, IGrainState grainState) { throw null; }
+
+ public System.Threading.Tasks.Task WriteStateAsync(string stateName, Runtime.GrainId grainId, IGrainState grainState) { throw null; }
+ }
+
+ public sealed partial class FileGrainStorageOptions : Storage.IStorageProviderSerializerOptions
+ {
+ public required Storage.IGrainStorageSerializer GrainStorageSerializer { get { throw null; } set { } }
+
+ public required string RootDirectory { get { throw null; } set { } }
+ }
+
+ public static partial class FileSiloBuilderExtensions
+ {
+ public static Microsoft.Extensions.DependencyInjection.IServiceCollection AddFileGrainStorage(this Microsoft.Extensions.DependencyInjection.IServiceCollection services, System.Action options) { throw null; }
+
+ public static Microsoft.Extensions.DependencyInjection.IServiceCollection AddFileGrainStorage(this Microsoft.Extensions.DependencyInjection.IServiceCollection services, string providerName, System.Action options) { throw null; }
+
+ public static Hosting.ISiloBuilder AddFileGrainStorage(this Hosting.ISiloBuilder builder, System.Action options) { throw null; }
+
+ public static Hosting.ISiloBuilder AddFileGrainStorage(this Hosting.ISiloBuilder builder, string providerName, System.Action options) { throw null; }
+ }
+}
+
namespace Orleans.Runtime
{
[GenerateSerializer]
diff --git a/test/Extensions/Orleans.Persistence.FileStorage.Tests/FileGrainStorageBoundaryTests.cs b/test/Orleans.Persistence.FileStorage.Tests/FileGrainStorageBoundaryTests.cs
similarity index 100%
rename from test/Extensions/Orleans.Persistence.FileStorage.Tests/FileGrainStorageBoundaryTests.cs
rename to test/Orleans.Persistence.FileStorage.Tests/FileGrainStorageBoundaryTests.cs
diff --git a/test/Extensions/Orleans.Persistence.FileStorage.Tests/FileGrainStorageConformanceTests.cs b/test/Orleans.Persistence.FileStorage.Tests/FileGrainStorageConformanceTests.cs
similarity index 100%
rename from test/Extensions/Orleans.Persistence.FileStorage.Tests/FileGrainStorageConformanceTests.cs
rename to test/Orleans.Persistence.FileStorage.Tests/FileGrainStorageConformanceTests.cs
diff --git a/test/Extensions/Orleans.Persistence.FileStorage.Tests/FileGrainStorageOptionsTests.cs b/test/Orleans.Persistence.FileStorage.Tests/FileGrainStorageOptionsTests.cs
similarity index 100%
rename from test/Extensions/Orleans.Persistence.FileStorage.Tests/FileGrainStorageOptionsTests.cs
rename to test/Orleans.Persistence.FileStorage.Tests/FileGrainStorageOptionsTests.cs
diff --git a/test/Extensions/Orleans.Persistence.FileStorage.Tests/FileGrainStorageTestFixture.cs b/test/Orleans.Persistence.FileStorage.Tests/FileGrainStorageTestFixture.cs
similarity index 100%
rename from test/Extensions/Orleans.Persistence.FileStorage.Tests/FileGrainStorageTestFixture.cs
rename to test/Orleans.Persistence.FileStorage.Tests/FileGrainStorageTestFixture.cs
diff --git a/test/Extensions/Orleans.Persistence.FileStorage.Tests/FileSiloBuilderExtensionsTests.cs b/test/Orleans.Persistence.FileStorage.Tests/FileSiloBuilderExtensionsTests.cs
similarity index 100%
rename from test/Extensions/Orleans.Persistence.FileStorage.Tests/FileSiloBuilderExtensionsTests.cs
rename to test/Orleans.Persistence.FileStorage.Tests/FileSiloBuilderExtensionsTests.cs
diff --git a/test/Extensions/Orleans.Persistence.FileStorage.Tests/Orleans.Persistence.FileStorage.Tests.csproj b/test/Orleans.Persistence.FileStorage.Tests/Orleans.Persistence.FileStorage.Tests.csproj
similarity index 76%
rename from test/Extensions/Orleans.Persistence.FileStorage.Tests/Orleans.Persistence.FileStorage.Tests.csproj
rename to test/Orleans.Persistence.FileStorage.Tests/Orleans.Persistence.FileStorage.Tests.csproj
index 2a325931a04..469476392a0 100644
--- a/test/Extensions/Orleans.Persistence.FileStorage.Tests/Orleans.Persistence.FileStorage.Tests.csproj
+++ b/test/Orleans.Persistence.FileStorage.Tests/Orleans.Persistence.FileStorage.Tests.csproj
@@ -4,7 +4,7 @@
-
+
diff --git a/test/Extensions/Orleans.Persistence.FileStorage.Tests/RecordingGrainStorageSerializer.cs b/test/Orleans.Persistence.FileStorage.Tests/RecordingGrainStorageSerializer.cs
similarity index 100%
rename from test/Extensions/Orleans.Persistence.FileStorage.Tests/RecordingGrainStorageSerializer.cs
rename to test/Orleans.Persistence.FileStorage.Tests/RecordingGrainStorageSerializer.cs