FluxFlow.Components.Storage
3.0.0
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
<PackageReference Include="FluxFlow.Components.Storage" Version="3.0.0" />
<PackageVersion Include="FluxFlow.Components.Storage" Version="3.0.0" />
<PackageReference Include="FluxFlow.Components.Storage" />
paket add FluxFlow.Components.Storage --version 3.0.0
#r "nuget: FluxFlow.Components.Storage, 3.0.0"
#:package FluxFlow.Components.Storage@3.0.0
#addin nuget:?package=FluxFlow.Components.Storage&version=3.0.0
#tool nuget:?package=FluxFlow.Components.Storage&version=3.0.0
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:
StoragePutRequestStorageGetRequestStorageQueryRequestStorageDeleteRequestStorageQueryResultStorageResultStorageRecordStorageWriteModeIStorageStoreIStorageStoreFactoryStorageStoreContextStorageStoreLease
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 | Versions 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. |
-
net10.0
- FluxFlow.Nodes (>= 1.0.0)
-
net8.0
- FluxFlow.Nodes (>= 1.0.0)
- System.Threading.Tasks.Dataflow (>= 9.0.4)
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.