Skip to content
Reference

Common Component options

Authoritative reference for the pipeline configuration surface every Component shares.

A Component’s pipeline is declared in C# through a builder: ExtractorBuilder, LoaderBuilder, or the transactional integration’s SendPipelineBuilder and ReceivePipelineBuilder. The step methods that define what a pipeline does (deserialize, validate, transform, serialize, send) belong to each Component kind and are documented on its own reference page; Intropy Framework explains the pipeline model they share. The topology library has an unrelated builder that is also called ExtractorBuilder — the concept page opens with a note on telling the two apart. This page documents what is common to all pipeline builders: framework registration, the idempotency check, business incident routing, and build-time validation.

Every Component registers the framework once at startup. AddIntropyFramework binds a FrameworkOptions instance and makes it available to every pipeline built in the process:

Program.cs
builder.Services.AddIntropyFramework(options =>
{
options.ComponentName = "customer-sync";
options.ServiceNamespace = "fluxia";
});

Called without a delegate, AddIntropyFramework() reads both values from environment variables instead. Either way the options are validated at startup: a missing value fails the host before any message is processed.

Option Environment variable Description
ComponentName INTROPY_COMPONENT_NAME Required. Names this Component to the platform services. It scopes idempotency state — the component name is sent with every check and commit, so two Components checking the same message id never share or overwrite each other’s records.
ServiceNamespace INTROPY_SERVICE_NAMESPACE Required. The organization the Component belongs to, e.g. fluxia.

Together the two options identify the Component on every business incident it reports: the incident source is urn:{serviceNamespace}:{componentName}, lowercased.

WithIdempotency adds a check step near the front of the pipeline and a recording step after the send. Idempotency explains why duplicates are normal and what the check compares; Add an idempotency check walks through wiring one.

The call’s shape differs per builder:

Builder Signature Presence
ExtractorBuilder WithIdempotency(idExtractor, dateExtractor, hashGenerator?) Required — Build() throws without it
LoaderBuilder WithIdempotency(hashGenerator?) Required — Build() throws without it
SendPipelineBuilder WithIdempotency(client, idExtractor, dateExtractor, hashGenerator?) Optional — the check is skipped when not configured
ReceivePipelineBuilder Not available

idExtractor and dateExtractor receive the message and the pipeline context and return the message’s business id and business timestamp. The Loader overload takes no extractors: it reads the id from the incoming CloudEvent’s Subject and the timestamp from its Time, and fails the pipeline with a technical failure if either is missing.

The Extractor and Loader builders resolve IIdempotencyServiceClient from the service provider and throw at composition time when it isn’t registered; the send pipeline builder takes the client as its first argument. The send pipeline builder also accepts WithCustomIdempotency(checkStep, recordStep) for custom implementations of both steps.

The check sends four values to the Idempotency Service:

Field Value
Component FrameworkOptions.ComponentName
Id The return value of idExtractor (on a Loader, the CloudEvent Subject)
Hash The content hash — see below
Timestamp The return value of dateExtractor (on a Loader, the CloudEvent Time)

The service answers with an action and a reason:

Action Reason When
Proceed NoPreviousData No record exists for this id
Proceed NewerData A record exists, the content differs, and the timestamp is newer
Ignore SameData A record exists with identical content
Ignore StaleData A record exists, the content differs, and the timestamp is not newer

On Ignore, the check returns Cancelled: the remaining steps are skipped and the run completes as a traceable no-op, not an error. On Proceed, the id, timestamp, and hash travel in the pipeline context, and after a successful send the recording step commits them to the service so the next delivery of the same message is recognised. Records expire 30 days after their last commit.

If the check itself fails (the client isn’t registered with the service, the service is unreachable) the pipeline fails with a technical failure, Failed to check idempotency. The check fails closed: a broken dedup path stops the message rather than risking a duplicate side effect.

By default the hash is a SHA-256 over the JSON-serialized message, base64-encoded. If the message type implements IHashable, the framework hashes the return value of GetHashString() instead. A hashGenerator function passed to WithIdempotency overrides both, and its return value is used as the hash verbatim.

WithBusinessIncidents adds a finalizer that turns business failures into tracked incidents at the Business Incident Service. Business incidents explains what counts as one and who owns it; Route business incidents walks through wiring the transactional pipelines.

Builder Signature Presence
ExtractorBuilder WithBusinessIncidents(messageIdExtractor, subjectExtractor) Required — Build() throws without it
LoaderBuilder WithBusinessIncidents(messageIdExtractor, subjectExtractor) Required — Build() throws without it
SendPipelineBuilder WithBusinessIncidents(client, messageIdExtractor, subjectExtractor) Optional — routing is skipped when not configured
ReceivePipelineBuilder WithBusinessIncidents(client, messageIdExtractor, subjectExtractor) Optional — routing is skipped when not configured

Both extractors receive the pipeline context and return a string. messageIdExtractor must return the same value every time the same message is processed; it is what ties a repeat failure to the existing incident and lets a later success resolve it. subjectExtractor returns the identifier shown to the owning team — a business identifier, not an internal one.

The Extractor and Loader builders resolve IBusinessIncidentServiceClient from the service provider and throw at composition time when it isn’t registered; the send and receive pipeline builders take the client as their first argument and also accept WithCustomBusinessIncidents(routeStep) for a custom routing step.

The finalizer acts on two outcomes: a business failure triggers an incident (or increments the existing one for a repeated message), and a success on a retried message resolves the open incident.

Every builder validates its configuration when Build() is called, not when the first message arrives. A missing required step raises InvalidOperationException naming the call to add — a Component that composes successfully has a complete pipeline. On the Extractor and Loader builders, WithIdempotency and WithBusinessIncidents are among the required steps; on the send and receive pipeline builders both are optional and skipped at runtime when absent.