FluxFlow.Components.Journal 2.3.6

dotnet add package FluxFlow.Components.Journal --version 2.3.6
                    
NuGet\Install-Package FluxFlow.Components.Journal -Version 2.3.6
                    
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.Journal" Version="2.3.6" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="FluxFlow.Components.Journal" Version="2.3.6" />
                    
Directory.Packages.props
<PackageReference Include="FluxFlow.Components.Journal" />
                    
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.Journal --version 2.3.6
                    
#r "nuget: FluxFlow.Components.Journal, 2.3.6"
                    
#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.Journal@2.3.6
                    
#: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.Journal&version=2.3.6
                    
Install as a Cake Addin
#tool nuget:?package=FluxFlow.Components.Journal&version=2.3.6
                    
Install as a Cake Tool

FluxFlow.Components.Journal

Reusable event journal contracts for FluxFlow hosts.

What It Provides

  • JournalRecord for normalized runtime event storage.
  • JournalEventInput and JournalRecordMapper for mapping host event data into journal records without depending on a runtime package.
  • JournalEventInputBuilder for fluent neutral event authoring and direct mapping through the existing record mapper.
  • JournalQuery and JournalQueryMatcher for type, status, source, subject, channel, attribute, time range, and severity matching.
  • IJournalStore for host-owned persistence.
  • IJournalStoreFactory, JournalStoreContext, and JournalStoreLease for explicit host-owned store opening and ownership.
  • JournalComponentOptions for direct hosts that need to configure journal store factories and clocks.
  • InMemoryJournalStore for local runtime use and focused verification.
  • InMemoryJournalStoreFactory for named shared in-memory stores.
  • Retention options for cutoff and maximum-record pruning.

Example

var store = new InMemoryJournalStore();

var record = JournalEventInputBuilder
    .Create(DateTimeOffset.Parse("2026-01-01T00:00:00Z"))
    .WithType("job.completed")
    .WithSource("worker")
    .WithSubject("job/42")
    .WithStatus("ok")
    .WithWorkflow("orders", "Orders")
    .WithNode("complete-job")
    .WithSummary("Job completed")
    .AddAttribute("tenant", "primary")
    .BuildRecord("evt-1");

await store.AppendAsync(record);

var result = await store.QueryAsync(new JournalQuery
{
    TypePrefix = "job.",
    Attributes = new Dictionary<string, string>
    {
        ["tenant"] = "primary"
    },
    Limit = 10
});

Store Factories

Hosts that need deferred store opening can use an explicit factory and lease:

var factory = new InMemoryJournalStoreFactory(new JournalRetentionOptions
{
    MaxRecords = 1000
});

await using var lease = await factory.OpenAsync(new JournalStoreContext
{
    StoreName = "default",
    Clock = TimeProvider.System
});

await lease.Store.AppendAsync(record);

JournalStoreContext.StoreName is trimmed and blank values are treated as the default store. JournalStoreLease.Owned(...) disposes stores when the lease is disposed; JournalStoreLease.Shared(...) leaves lifetime with the host.

Direct host configuration can use JournalComponentOptions:

var options = new JournalComponentOptions()
    .UseStoreFactory(new InMemoryJournalStoreFactory())
    .UseClock(TimeProvider.System);

Hosts using keyed DI can register host-owned direct stores or store factories without adding composition behavior:

services
    .AddFluxFlowJournalStore("journal", store)
    .AddFluxFlowJournalStoreFactory("journal-factory", factory);

Keyed DI helper names are trimmed before registration, matching the normalization used by JournalStoreContext.StoreName and InMemoryJournalStoreFactory.

The direct registration overloads validate the service collection and key before captured stores or store factories. Provider overloads receive the current IServiceProvider, reject null delegates, and fail with clear diagnostics if they return null. All keyed registration overloads reject blank keys and null service collections at the package boundary.

Composition

This package does not expose standalone nodes or FluxFlow.Composition factories. It is a support package for host-owned journal persistence; workflow nodes that emit events remain in their owning component packages.

Journal is runtime-neutral. Hosts that use another runtime should adapt runtime events into JournalEventInput before calling JournalRecordMapper. JournalEventInputBuilder is an authoring helper over the same contracts. It does not own runtime event collection, persistence, retention, or store lifetime; it creates normalized JournalEventInput snapshots and can map them to JournalRecord through JournalRecordMapper.

Journal contracts normalize incoming text so record ids, optional fields, query filters, and attribute keys/values are trimmed before storage or matching. Blank attribute values and duplicate attribute keys after trimming are rejected to keep query matching deterministic.

Record, event, and query attribute maps are copied on assignment. Query result record lists are copied on assignment. Later caller mutations do not change already-created records, queries, event inputs, or query results. Null query result record collections become empty results, while null record entries are rejected at the public result boundary.

JournalQueryMatcher.Validate() owns structural query validation. It rejects negative offsets, non-positive limits, and time ranges where From is later than To; InMemoryJournalStore.QueryAsync() uses the same validator before matching records.

JournalRetentionOptions rejects negative MaxRecords values and non-positive MaxAge values when assigned. InMemoryJournalStore.PruneAsync() still owns cross-field retention validation, including requiring ReferenceTime when MaxAge is configured.

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

This package is not used by any NuGet packages.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
2.3.6 146 7/3/2026
2.3.5 116 7/2/2026
1.1.0 128 6/12/2026
1.0.0 127 6/4/2026
0.1.0-alpha.1 82 6/3/2026

Adds the shared FluxFlow package icon. No source, API, or dependency changes.