FluxFlow.Components.Storage 3.0.0

There is a newer version of this package available.
See the version list below for details.
dotnet add package FluxFlow.Components.Storage --version 3.0.0
                    
NuGet\Install-Package FluxFlow.Components.Storage -Version 3.0.0
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="FluxFlow.Components.Storage" Version="3.0.0" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="FluxFlow.Components.Storage" Version="3.0.0" />
                    
Directory.Packages.props
<PackageReference Include="FluxFlow.Components.Storage" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add FluxFlow.Components.Storage --version 3.0.0
                    
#r "nuget: FluxFlow.Components.Storage, 3.0.0"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package FluxFlow.Components.Storage@3.0.0
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=FluxFlow.Components.Storage&version=3.0.0
                    
Install as a Cake Addin
#tool nuget:?package=FluxFlow.Components.Storage&version=3.0.0
                    
Install as a Cake Tool

FluxFlow.Components.Storage

Standalone storage nodes for FluxFlow: blockified put/get/query/delete over an injected IStorageStore. No engine required.

Each node is a self-contained TPL Dataflow processor built on FluxFlow.Nodes. Every message travels as a FlowMessage<T> envelope (payload + correlation id), so the correlation id flows request → result for free — and onto the Found/NotFound and Records branches. The host owns the IStorageStore lifetime and injects the opened store into each node; the nodes never open or dispose it (exactly like the HTTP node over an HttpClient).

Nodes

Node Shape Purpose
StoragePutNode Input → Output, Errors, Events Stores or updates a logical record.
StorageGetNode Input → Output, Found, NotFound, Errors, Events Reads a logical record and fans found/missing results.
StorageQueryNode Input → Output, Records, Errors, Events Queries records by collection, key prefix, attributes, time bounds, and limit.
StorageDeleteNode Input → Output, Errors, Events Deletes a logical record and reports whether it existed.
// The host owns the store; the node just borrows it.
IStorageStore store = ...;
await using var put = new StoragePutNode(store);

var request = FlowMessage.Create(new StoragePutRequest
{
    Collection = "items",
    Key = "a",
    Value = "one"
});
await put.Input.SendAsync(request);

var result = await put.Output.ReceiveAsync();      // FlowMessage<StorageResult>
// result.CorrelationId == request.CorrelationId   // the envelope carries it

Output, Found, NotFound, Records, Errors, and Events are all broadcast ports — link each to as many downstream consumers as you like.

Put

await using var put = new StoragePutNode(store, new StoragePutOptions
{
    Collection = "items",
    Mode = StorageWriteMode.Upsert,
    EmitStoredRecord = true,
    BoundedCapacity = 128
});

StoragePutNode consumes StoragePutRequest and emits StorageResult. Supported modes are Upsert, Create, and Replace. The request can override the node mode per item.

Get

await using var get = new StorageGetNode(store, new StorageGetOptions
{
    Collection = "items",
    IncludeExpired = false
});

StorageGetNode consumes StorageGetRequest and emits StorageResult on Output. Found records are also fanned to Found; missing records are also fanned to NotFound. A missing record is a normal result, not a processing error.

Query

await using var query = new StorageQueryNode(store, new StorageQueryOptions
{
    Collection = "items",
    Offset = 0,
    Limit = 100,
    IncludeExpired = false,
    EmitRecordsInResult = true,
    EmitRecordOutputs = true
});

StorageQueryNode consumes StorageQueryRequest and emits one StorageQueryResult on Output. The Records port emits each returned StorageRecord (as a FlowMessage<StorageRecord>) when EmitRecordOutputs is true. Requests can filter by collection, key prefix, exact-match attributes, stored time bounds, expired-record policy, offset, and limit.

Delete

await using var delete = new StorageDeleteNode(store, new StorageDeleteOptions
{
    Collection = "items",
    EmitMissingAsResult = true
});

StorageDeleteNode consumes StorageDeleteRequest and emits StorageResult. Missing deletes can be emitted as normal results or suppressed (EmitMissingAsResult).

Errors and events

A store failure or an invalid request surfaces a FlowError on Errors (stamped with the in-flight correlation id and a Code from StorageErrorCodes) and the node keeps processing later messages. Each node also emits FlowEvent diagnostics on Events (names in StorageDiagnosticNames).

Store Ownership

The package does not include a concrete database. A host supplies an IStorageStore — see the FileSystem and SqlFile adapter packages — and injects it into the nodes.

Adapter packages register a store factory through StorageComponentOptions:

var options = new StorageComponentOptions()
    .UseFileSystemStorage("./data");      // adapter extension
IStorageStore store = (await options.StoreFactory
    .OpenAsync(new StorageStoreContext { StoreName = "items-db" })).Store;

StorageStoreLease.Owned(store) marks a store the lease should dispose; StorageStoreLease.Shared(store) marks a host-owned store that must not be disposed. The factory receives the store name, default collection, and clock through StorageStoreContext.

Runtime Timing

Each node uses System.TimeProvider (default TimeProvider.System) for result timestamps. Pass a deterministic TimeProvider (for example Microsoft.Extensions.Time.Testing.FakeTimeProvider) when tests, replay, or deterministic dashboards need stable timestamps:

await using var put = new StoragePutNode(store, clock: fakeTimeProvider);

The same clock can be supplied to a backend store through StorageStoreContext.Clock so stored records and expiration checks share one time source.

Contracts

Core contracts:

  • StoragePutRequest
  • StorageGetRequest
  • StorageQueryRequest
  • StorageDeleteRequest
  • StorageQueryResult
  • StorageResult
  • StorageRecord
  • StorageWriteMode
  • IStorageStore
  • IStorageStoreFactory
  • StorageStoreContext
  • StorageStoreLease

StorageRecord.Value is object?: hosts own serialization and can compose this package with serialization or payload components before storage.

Composition Guidance

Use this package as one part of a host-composed graph. See Component Composition for recommended host boundaries, package boundaries, and extraction timing.

Product Compatible and additional computed target framework versions.
.NET net8.0 is compatible.  net8.0-android was computed.  net8.0-browser was computed.  net8.0-ios was computed.  net8.0-maccatalyst was computed.  net8.0-macos was computed.  net8.0-tvos was computed.  net8.0-windows was computed.  net9.0 was computed.  net9.0-android was computed.  net9.0-browser was computed.  net9.0-ios was computed.  net9.0-maccatalyst was computed.  net9.0-macos was computed.  net9.0-tvos was computed.  net9.0-windows was computed.  net10.0 is compatible.  net10.0-android was computed.  net10.0-browser was computed.  net10.0-ios was computed.  net10.0-maccatalyst was computed.  net10.0-macos was computed.  net10.0-tvos was computed.  net10.0-windows was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages (3)

Showing the top 3 NuGet packages that depend on FluxFlow.Components.Storage:

Package Downloads
FluxFlow.Components.Storage.FileSystem

File-system-backed storage adapter for FluxFlow storage components.

FluxFlow.Components.Storage.SqlFile

Single-file SQL storage adapter for FluxFlow storage components.

FluxFlow.Components.Storage.Composition

Optional canonical exact-content storage registrations over host-owned keyed stores or factories.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
8.0.0-rc.1 111 9/5/2026
7.0.0 254 8/3/2026
3.0.10 181 7/3/2026
3.0.9 231 7/2/2026
3.0.0 170 6/19/2026
2.0.0 194 6/18/2026
1.1.0 484 6/5/2026
1.0.0 180 6/4/2026
0.4.0-alpha.1 86 6/3/2026
0.3.0-alpha.1 264 6/2/2026
0.2.1-alpha.1 100 6/2/2026
0.2.0-alpha.1 101 6/2/2026
0.1.0-alpha.1 98 6/1/2026

Rebuilt as standalone storage.put/get/query/delete nodes over an injected IStorageStore: request in, result broadcast out, failures on the error port, diagnostics on the event port. Every message travels as a FlowMessage<T> envelope so the correlation id flows request -> result (and onto the Found/NotFound and Records branches). The storage.store resource node and its connect/disconnect lifecycle are removed — the host owns the IStorageStore lifetime and injects the opened store into each node, exactly like the HTTP node over an HttpClient. The engine factory/module/registration/designer-metadata glue is removed; the nodes depend only on FluxFlow.Nodes and run without the engine. The IStorageStore contract, all request/result/record DTOs, options, error codes, and the store factory/lease/context types are unchanged, so the FileSystem and SqlFile adapters keep working.