FluxFlow.Components.Storage
2.0.0
See the version list below for details.
dotnet add package FluxFlow.Components.Storage --version 2.0.0
NuGet\Install-Package FluxFlow.Components.Storage -Version 2.0.0
<PackageReference Include="FluxFlow.Components.Storage" Version="2.0.0" />
<PackageVersion Include="FluxFlow.Components.Storage" Version="2.0.0" />
<PackageReference Include="FluxFlow.Components.Storage" />
paket add FluxFlow.Components.Storage --version 2.0.0
#r "nuget: FluxFlow.Components.Storage, 2.0.0"
#:package FluxFlow.Components.Storage@2.0.0
#addin nuget:?package=FluxFlow.Components.Storage&version=2.0.0
#tool nuget:?package=FluxFlow.Components.Storage&version=2.0.0
FluxFlow.Components.Storage
Reusable logical storage components for FluxFlow.
The package owns workflow storage node behavior and neutral contracts. Hosts provide the concrete store through an adapter.
Nodes
| Node type | Shape | Purpose |
|---|---|---|
storage.store |
resource | Owns the store lifecycle. Operation nodes reference it by name and borrow the opened store. |
storage.put |
Input → Result, Errors |
Stores or updates a logical record. |
storage.get |
Input → Result, Found, NotFound, Errors |
Reads a logical record and routes found/missing results. |
storage.query |
Input → Result, Records, Errors |
Queries records by collection, key prefix, attributes, time bounds, and limit. |
storage.delete |
Input → Result, Errors |
Deletes a logical record and reports whether it existed. |
Store resource
The storage.store node owns the store. It is a resource: the operation nodes
do not open their own store, they borrow the opened store from a storage.store
by name.
{
"type": "storage.store",
"name": "default",
"storeName": "items-db"
}
Each operation node requires a store that names a storage.store resource.
The reference is mandatory.
{
"type": "storage.put",
"name": "save",
"store": "default",
"collection": "items"
}
Store Ownership
The package does not include a concrete database. Register a store factory from the host:
var registry = new RuntimeNodeFactoryRegistry()
.RegisterStorageComponents(options => options
.UseSharedStore(context => new AppStorageStore(context.StoreName)));
Use StorageStoreLease.Owned(store) when the storage.store resource should
dispose the store. Use StorageStoreLease.Shared(store) when the host owns the
store lifetime.
The factory receives the node address, node type, store name, and default
collection through StorageStoreContext.
Opening (host-driven)
Opening the store is an explicit host decision: there is no auto-open or lazy
open. StartAsync on the storage.store resource is a no-op. The host opens and
closes the store through IStorageStoreHandle.ConnectAsync /
DisconnectAsync (named for cross-protocol consistency even though storage
"opens" a store):
await store.ConnectAsync(cancellationToken);
// ... run the graph ...
await store.DisconnectAsync(cancellationToken);
Operation nodes borrow the opened store at call-time and never open or dispose
it. An operation sent before the store is opened is reported per message on the
Errors port rather than faulting the node.
Runtime Timing
The package uses System.TimeProvider (default TimeProvider.System); there is
no bespoke storage clock interface. Hosts can provide a deterministic
TimeProvider when tests, replay, or deterministic dashboards need stable
timestamps:
var registry = new RuntimeNodeFactoryRegistry()
.RegisterStorageComponents(options => options
.UseClock(storageClock)
.UseSharedStore(context => new AppStorageStore(context.StoreName)));
The configured TimeProvider is also available on StorageStoreContext.Clock,
so backend stores can use the same time source for stored records and expiration
checks.
Put
{
"type": "storage.put",
"store": "default",
"collection": "items",
"mode": "upsert",
"emitStoredRecord": true,
"boundedCapacity": 128
}
storage.put consumes StoragePutRequest and emits StorageResult.
Supported modes are upsert, create, and replace. The request can override
the node mode per item.
Get
{
"type": "storage.get",
"store": "default",
"collection": "items",
"includeExpired": false,
"boundedCapacity": 128
}
storage.get consumes StorageGetRequest and emits StorageResult on
Result. Found records are also routed to Found; missing records are also
routed to NotFound. Missing records are normal results, not processing
errors.
Query
{
"type": "storage.query",
"store": "default",
"collection": "items",
"offset": 0,
"limit": 100,
"includeExpired": false,
"emitRecordsInResult": true,
"emitRecordOutputs": true,
"boundedCapacity": 128
}
storage.query consumes StorageQueryRequest and emits one
StorageQueryResult on Result. The Records port emits each returned
StorageRecord when emitRecordOutputs is true.
Requests can filter by collection, key prefix, exact-match attributes, stored
time bounds, expired-record policy, offset, and limit. Store failures emit
FlowError and the node continues processing later messages.
Delete
{
"type": "storage.delete",
"store": "default",
"collection": "items",
"emitMissingAsResult": true,
"boundedCapacity": 128
}
storage.delete consumes StorageDeleteRequest and emits StorageResult.
Missing deletes can be emitted as normal results or suppressed.
Contracts
Core contracts:
StoragePutRequestStorageGetRequestStorageQueryRequestStorageDeleteRequestStorageQueryResultStorageResultStorageRecordStorageWriteModeIStorageStoreIStorageStoreFactoryIStorageStoreHandleStorageStoreContextStorageStoreLease
StorageRecord.Value is object? in this first slice. Hosts own
serialization and can compose this package with serialization or payload
components before storage.
Per-message store failures emit FlowError and later messages continue.
Opening the store fails clearly when the store cannot be opened.
Design Metadata
This package exposes a package-owned IComponentDesignMetadataProvider for its
node types. Hosts can compose it through ComponentDesignMetadataCatalog to
populate palettes, editors, validation views, and documentation without
duplicating package descriptors.
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.Components.Designer (>= 1.0.1)
- FluxFlow.Engine (>= 1.3.0)
-
net8.0
- FluxFlow.Components.Designer (>= 1.0.1)
- FluxFlow.Engine (>= 1.3.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 | 110 | 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 | 85 | 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 |
2.0 preview: the node's static Create(RuntimeNodeFactoryContext …) factory moves into a dedicated internal *NodeFactory class, removing the public static Create from the node type (breaking). Node registration, options, ports, JSON shape, and runtime behavior are unchanged. Replaces the bespoke IStorageClock abstraction with System.TimeProvider (UseClock now takes a TimeProvider; the old clock interface/implementation are removed). Introduces a separate storage.store resource component that owns the store configuration; storage.put/get/query/delete now reference it by a required store name and no longer open a store directly. For now the store component holds configuration only — no store is opened — so the operations report a not-available result until a later open step. Adds an explicit, host-driven connect lifecycle: storage.store now exposes ConnectAsync/DisconnectAsync (plus a State and a lock-free TryGetStore), opening/owning the IStorageStore via the configured factory (a missing factory reports StoreOpenFailed without faulting the runtime); storage.put/get/query/delete borrow the opened store when connected and report not-available otherwise, never opening or disposing it. No auto-connect.