-
Notifications
You must be signed in to change notification settings - Fork 1
Releases: redbase-app/redb-route
v3.1.0
Why a minor bump (3.0.x → 3.1.0). This release ships four new
NuGet packages (redb.Route.Llm,redb.Route.Llm.Abstractions,
redb.Route.Llm.Tools,redb.Route.Exec), one new URI scheme
(exec:), a second LLM provider (nativeAnthropicProvider), and
a new persistence extension (AddRedbLlmStorage) that brings five
stores and nine REDB schemas. All additions are backwards-compatible —
no public API on existing packages was removed or renamed — but the
surface area added is too large to bury under a patch bump.
Added
redb.Route.Llm — first public release
The Camel-style LLM connector becomes a published package. From("...")/
To("llm://..."), fluent builder (Llm.Factory("haiku") ...), Camel-style
agent loop with tool dispatch, headers/URI options for system prompt,
conversation id, max tokens, temperature, max iterations, etc. See
redb.Route.Llm/README.md and doc/USER-GUIDE.md for the full surface.
OpenAiProvider— one provider class covering 14 OpenAI-compatible
APIs throughLlmConnectionFactory.Build()aliases:
openai,anthropic(OpenAI-compat endpoint),groq,cerebras,
openrouter,gemini(OpenAI-compat endpoint),github-models,
mistral,together,huggingface,deepseek,ollama,lmstudio,
pluscustomfor any self-hosted gateway. The provider id only switches
the default base URL and a couple of provider-specific headers (e.g.
OpenRouter'sHTTP-Referer+X-Title).AnthropicProvider— native Messages API transport
(POST /v1/messages), separate from the OpenAI-compat path. Maps
LlmRequestto Anthropic'smessages/tools/tool_use/
tool_resultcontent-block model and reassemblesLlmResponsefrom
the standard envelope. Streaming is true SSE —
content_block_start/content_block_delta/content_block_stop
events are reassembled per block; tool-use blocks accumulate
input_json_deltapartial JSON and surface as a single complete
LlmToolUseBlockat end-of-block. Error mapping: HTTP 429 →
LlmRateLimitException(honoursretry-after); HTTP 529
("overloaded") and 5xx →LlmTransientException. JSON serialisation
usesJavaScriptEncoder.UnsafeRelaxedJsonEscapingso Cyrillic /
emoji /&/>/<are emitted as UTF-8, not\uXXXX— fixes
unicode-escaped tool input in[*-TOOL] ▶ in=...route logs.- Reasoning-model fallback in
OpenAiProvider: when the response
message.contentis empty, the provider falls back to
message.reasoningso models like Cerebrasgpt-oss-120bor
zai-glm-4.7still surface a textual answer throughLlmResponse. AddRedbLlmStorage()extension onIServiceCollection— wires
the LLM connector to a named REDB instance through the Tsak registry
key"redb-factory:{name}". Ships five stores backed by
IServiceScopeFactoryper named instance:IConversationStore—RedbConversationStore: persistent multi-turn
memory across runs and processes;AgentEngine.LoadPathAsync
resumes a transcript by id.IApprovalStore—RedbApprovalStore:IApprovalGatedecisions
survive restarts, supports human-in-the-loop tools.ICostBudgetStore—RedbCostBudgetStore: per-tenant spend
tracking, drivesIBudgetEnforcerhard cut-offs.IToolIdempotencyStore—RedbToolIdempotencyStore: dedup of
expensive tool calls across retries.IAgentObserver—RedbAgentObserver: full audit of every
iteration / tool invocation / approval into the store.- Nine REDB schemas (
[RedbScheme]POCOs):
Conversation,Message,Approval,CostBudget,ToolCache,
ToolAudit,KnowledgeChunk,PromptTemplate,EvalRun. See
redb.Route.Llm/doc/STORAGE.mdfor the recipe catalogue
(multi-turn chat, approval gates, hard budget, idempotent retries,
audit, branching, scheduled agents).
#-registry prompts —LlmConnectionFactoryresolves system
prompts from a registry by#nameso prompt text lives in the host's
Tsak config layer, not inline in route code.- Live integration test infrastructure under
tests/redb.Route.Tests.Llm:LiveProviderTests— 5 scenarios (Smoke / NonAscii / ToolUse /
Usage / StopReason) ×ばつ free-tier providers (GitHub Models, Groq,
Cerebras, OpenRouter, Gemini, Mistral, native Anthropic). Live
end-to-end coverage with auto-skip when API keys are absent.LiveEndToEndTests— exercises the full
LlmComponent → LlmEndpoint → LlmProducer → AgentEngine
path against a real provider, including a tool-loop driving
IToolRegistry.LiveDslRouteTests— Apache Camel-style end-to-end routes:
From("direct://...") → Process → To(Llm.Factory(...)) → Process → To("mock://..."), a two-LLM judge chain, and cross-context RPC
overdirect-vm://llm-serviceusing a sharedSharedVmRegistry.ExecShellToolTests— agent +exec:shell tool against live
Anthropic / OpenAI-compat providers.UtilityToolTests— agent +redb.Route.Llm.Tools(HttpFetch /
JsonPath / XPath / MathEval / RegexExtract / Tavily) against live
providers.
[EnvFact("VAR")]xUnit attribute — auto-skips a fact when the
named environment variable is missing, so contributors without API
keys keep a green build while CI with the right secrets runs the full
live matrix.[Collection("LiveLlmSerial")]— shared collection across all
live LLM tests so xUnit parallelism does not multiply free-tier rate
limits.
redb.Route.Llm.Abstractions — first public release
A small, dependency-light contract package. Exists separately from
redb.Route.Llm so any of the 23 transports can expose itself as an
LLM tool by implementing .AsLlmTool(name) on the From(uri) route —
zero connector version bumps, zero transitive dependency on the LLM
provider implementation.
ILlmToolDescriptor— descriptor contract: capability metadata +
endpoint URI the agent dispatches to.LlmToolCapability—Name,Description,InputSchema
(JSON Schema string),LlmToolSafety(SideEffect,
Caching,Cost,RequiresApproval,RequiredClaims).IToolDescriptorRegistry— global registry; populated by
.AsLlmTool(...)at route-build time, queried byAgentEngineat
dispatch time.RouteToolBridge— bridges anyFrom(uri)endpoint into the
LLM tool surface. Forwards the model's JSON input through the host's
producer template, inheriting the parent agent route's transaction
scope, headers, principal and DI scope.[ExposeAsLlmTool]attribute — alternative to the fluent DSL:
decorate a handler class and the bootstrapper turns it into a
registered descriptor..AsLlmTool(name)DSL aspect inLlmToolDsl— Apache-Camel-style
metadata aspect placed immediately after.From(uri). Closes with
.End()or.Then(). Example:Works with any transport:From("direct:order-lookup") .AsLlmTool("get_order") .Description("Returns order details by id.") .Input("""{"type":"object","properties":{"orderId":{"type":"string"}},"required":["orderId"]}""") .SideEffect(ToolSideEffect.ReadOnly) .Cost(ToolCostClass.Cheap) .Then() .Bean<IOrderService>((svc, ex) => svc.HandleAsync(ex));
Direct,Http,Grpc,Sql,
Sftp,File,Redis,Exec, etc. for request-response tools;
Kafka,MQTT,Mail,SignalRfor fire-and-forget action tools.
redb.Route.Llm.Tools — first public release
Six ready-to-use utility tools that live as ordinary RouteBuilder
classes registered by .AsLlmTool(...), so they participate in the
same transaction scope, telemetry, error handling and DI as any other
route. All optional — depend only on what the agent needs.
| Tool | Purpose |
|---|---|
HttpFetchTool |
GET <url> with size cap and host allowlist; returns body + status + headers. Built on redb.Route.Http. |
JsonPathTool |
Evaluate a JSONPath expression against a JSON document. Built on the core compiled-JPath engine. |
XPathTool |
Evaluate an XPath expression against an XML document. Built on the core compiled-XPath engine. |
MathEvalTool |
Safe arithmetic evaluator (integers / decimals / + - * / % ^, parentheses, common functions). |
RegexExtractTool |
Apply a regex to a string; return all matches and named groups. |
TavilyWebSearchTool |
Tavily Search API (https://api.tavily.com/search); returns top-N results with snippets. API key via TAVILY_API_KEY. |
redb.Route.Exec — first public release
Local-process execution transport. New URI scheme exec: with two
operations: exec://run (one-shot producer) and a scheduled consumer
that runs commands on a cron: / qtimer: trigger.
AllowedCommands(params string[])— explicit allowlist. Every
invocation whose command is not on the list is rejected before a
process starts; this is the security envelope for LLM-driven shells.WorkingDirectory(string)— pinned CWD; relative paths in tool
arguments resolve there, files written in one call survive to the
next. Without this, processes inherit the worker's CWD (e.g. the
source tree underdotnet run).TimeoutMs— hard kill on timeout.MaxStdoutBytes/MaxStderrBytes— cap captured output.- Output headers —
redbExec.ExitCode,redbExec.StdoutBytes,
redbExec.StderrBytes, plusredbExec.TimedOut. exec:request schema —{"command":"<name>","args":["..."]};
redbExecheaders,stdout,stderr,exitCodereturned. Designed
to drop straight into.AsLlmTool("shell")for an LLM-driven shell;
the demoredb.Route.DemoHTTP showcase wires ...
Assets 2
v3.0.1
Added
DSL — flat fluent navigation across nested scopes
redb.Route(DSL) — added a new universalEnd()extension method
onIRouteDefinitionand a full set of typedEnd*()extension methods
(EndFilter,EndChoice,EndWhen,EndOtherwise,EndSplit,
EndMulticast,EndAggregate,EndCircuitBreaker,EndThrottle,
EndDebounce,EndLoop,EndTryCatch,EndOnException,EndTransaction,
EndLog,EndResequence,EndTraced,EndMetered,
EndIdempotentConsumer,EndSaga). Each typedEnd*()walks the
Parentchain looking for a scope of the requested type and returns its
parent route. This means a single.EndChoice()call from deep inside
Choice → When → Split → Loglands directly at the route root —
semantically identical to chaining.EndLog().EndSplit().EndChoice()but
more concise when the intermediate scopes do not need extra steps. Each
helper throws a preciseInvalidOperationExceptionwhen called outside
a matching scope.redb.Route(DSL) — addedWhen(...)andOtherwise()as extension
methods onIRouteDefinition. They walk theParentchain to find the
enclosingChoiceDefinitionand dispatch to its instance method, so a
sibling branch can be opened immediately after a sub-scope closes — for
example.Choice().When(p).Split(...).EndSplit().When(p2).Process(...).EndChoice()
now compiles and behaves the same as the equivalent nested-lambda form.
Instance methods onChoiceDefinition/WhenDefinition/
OtherwiseDefinitionkeep precedence over the extensions, so existing
call sites are unaffected.redb.Route(DSL) — added a focused test fixture (DeepNestedDslTests,
five scenarios) coveringChoice/When/Otherwise/Split/RichLog
composition,TryCatchwith rich logging insideDoCatch<T>, mixed
typed and universalEnd*()closers, cascadingEndChoice()from deep
inside, and the diagnosticInvalidOperationExceptionraised when
End*()is called outside any matching scope.
Removed
Legacy RouteStep AST
redb.Route(DSL) — removed the legacyRouteStep/
RouteStepProjectionAST and theRouteDefinition.Stepsprojection. The
ProcessorDefinitiontree built by the fluent DSL is now the single
source of truth for route construction; everything that used to read
Steps(Normalizer, Saga, integration tests) now uses
CreateProcessordirectly. The legacy files have been moved out of the
shipping assembly intotmp/oldRoute/for reference only.
Changed
DSL — single source of truth via CRTP base (RouteDefinitionBase<TSelf>)
redb.Route(DSL) — the leaf DSL (To,Process,ProcessAsync,
SetBody,SetHeader,SetProperty,RemoveHeader,RemoveProperty,
Transform,Validate,Marshal/Unmarshal,ConvertBody,Stop,
Delay,Sample,BeginTransaction/Commit/Rollback,
SetPattern,Respond,Bean,StreamCaching,Throw*,Log*, plus
every scope-opener:Filter,Choice,Split,Multicast,Loop,
Aggregate,IdempotentConsumer,Throttle/Debounce/KeyedThrottle,
Metered,Traced,Resequence,Transaction,Saga,OnException,
OfType<T>,CircuitBreaker,TryCatch, etc.) is now defined exactly
once in a new generic CRTP base,RouteDefinitionBase<TSelf>, instead of
being duplicated across 27 scope-definition classes. Each typed leaf method
returnsTSelf, so chaining always preserves the current scope's concrete
type — e.g..Filter(p).To("a").SetHeader("k","v")keeps you on
FilterDefinition,.Choice().When(p).To("a")keeps you on
WhenDefinition, and only the explicitEnd*()/End()step exits the
scope. There is no behavioural change for end users; the public DSL
surface and route AST shape are identical to 3.0.0.redb.Route(DSL) —RouteDefinitionis now a thin
RouteDefinitionBase<RouteDefinition>subclass that retains only
route-level concerns:RouteId,From,AutoStart,Cluster,
ProcessingTimeout,RoutePolicy,OnExceptionhoisting, and
CreateProcessor. All other behaviour is inherited.redb.Route(DSL) — every pipeline-scope class
(FilterDefinition,ChoiceDefinition/WhenDefinition/
OtherwiseDefinition,CircuitBreakerDefinition/FallbackDefinition,
LoopDefinition,SplitDefinition/MulticastDefinition,
TryCatchDefinition/CatchDefinition/FinallyDefinition,
IdempotentConsumerDefinition,OnExceptionDefinition,
TransactionDefinition,SagaDefinition,MeteredDefinition,
TracedDefinition,ResequenceDefinition,ThrottleDefinition/
DebounceDefinition/KeyedThrottleDefinition,AggregateDefinition,
OfTypeDefinition<T>,OfTypeFilterDefinition<T>) now inherits from
RouteDefinitionBase<TSelf>and contains only its own scope-specific
configuration (options, branch openers,End*()navigation,
CreateProcessoroverride). Per-class duplicates of the leaf DSL have been
removed.redb.Route(DSL) —IRouteDefinitionremains the canonical
cross-version contract;RouteDefinitionBase<TSelf>provides explicit
interface implementations for every leaf method (split into a partial file,
RouteDefinitionBase.IRouteDefinition.cs), so existing extension methods,
test mocks, andAction<IRouteDefinition>configurators continue to bind
unchanged.redb.Route(DSL) — non-pipeline definitions (LoadBalancerDefinition,
ScatterGatherDefinition,NormalizerDefinition,
RichLogScopeDefinition) intentionally remain onProcessorDefinition:
they have no childOutputspipeline and no leaf DSL — they are
configuration builders, and inheriting the CRTP base would have inflated
their public surface with methods (To,Process, ...) that are
semantically invalid in those scopes.
Fixed
redb.Route(DSL) —IRouteDefinition.GetContext()now correctly
returns the owningIRouteContextwhen called on any nested scope
(WhenDefinition,LoopDefinition,TracedDefinition,CatchDefinition,
etc.). Previously it relied onself as RouteDefinition, which only
matched the route root; after the CRTP refactor scope classes inherit from
RouteDefinitionBase<TSelf>(not fromRouteDefinition), and the cast
silently returnednullinside any scope. The accessor now walks the
Parentchain up to the owningRouteDefinitionand returns its
Context. This restoresContext_IsAvailable_In{Choice,Loop,Traced,DoTry}Scope
semantics for extension methods that read context at DSL build time.redb.Route(DSL) —SagaDefinition.SetParentis no longer required:
the parent link is now established uniformly throughAddOutput, which
matches every other scope and removes a small inconsistency in the AST
build path. Existing user code is unaffected.
Assets 2
v3.0.0
Added
DSL — full Camel parity, single canonical RouteDefinition
redb.Route(DSL) — Package A "enterprise EIP closure": the parallel
v2 type tree (IRouteDefinition2,RouteBuilder2,BlockStack,
ExceptionRouteDefinition, the v1OldRouteCompiler, the v1 typed
Abstractions/Typed/IRouteDefinition.cs, etc.) has been collapsed into a
single canonical surface —IRouteDefinition/RouteDefinition/
RouteBuilder. The route AST is now exclusively built from
IProcessorDefinitionnodes, each of which compiles itself via
CreateProcessor(IRouteContext); there is no separate compiler class. The
previous "v2 DSL → bridge → legacy compiler" indirection has been removed.redb.Route(DSL) —IRouteContextis now propagated down the
definition tree via aParentchain, so any nested*Definitioncan reach
the owning context (logger factory, services, idempotent repositories,
policy factories) without explicit threading.redb.Route(DSL) —RouteStepProjection: a read-only canonical
projection of theIProcessorDefinitiontree intoRouteSteprecords,
exposed asRouteDefinition.Steps. Intended for diagnostics, validation,
and tooling (e.g. route visualisers); it is not used by the runtime
compiler.FromStep,ToStep,FilterStep(with optionalSubSteps
body),ChoiceStep,SagaRouteStep, etc. all flow through this
projection.redb.Route(DSL) —RouteBuilder.Definitionsand
RouteBuilder.ExceptionDefinitionsare nowpublic(previously
internal). This unblocks downstream test fixtures and tooling that need
to introspect the route AST afterBuild().redb.Route(DSL) —OnExceptionDefinitiongained the fluent setters
LogStackTrace(bool)andLogExhausted(bool)to match the rest of the
CamelonException(...)builder surface.
Dynamic endpoints (Camel toD() / dynamic wireTap / dynamic enrich)
redb.Route(DSL) —DynamicEndpointResolver: per-instance producer
cache keyed by the URI resolved at runtime. Three constructors accept a
string template (${header.xxx}/${property.yyy}/${body}
placeholders), anIExpressioninstance, or a raw
Func<IExchange, string>. Producers are tracked via
RouteContext.TrackProducer(...)for graceful shutdown.redb.Route(DSL) —ToDynamicProcessor+ToDynamicDefinition
implement Camel'stoD(...)—IRouteDefinition.ToD(string|IExpression|Func).redb.Route(DSL) —WireTapDynamicDefinition,
EnrichDynamicDefinition,PollEnrichDynamicDefinitionand matching
IRouteDefinition.WireTap(...)/Enrich(...)/PollEnrich(...)
overloads that accept a dynamic URI.EnrichProcessorand
PollEnrichProcessorgained an alternate constructor taking a
DynamicEndpointResolver; theirProcesschooses between the resolver
and the cached producer at run time.redb.Route(DSL) — string-template expression DSL:
SetBodyExpression(...),SetHeaderExpression(...),
SetPropertyExpression(...)onIRouteDefinition.redb.Route(DSL) —LogDefinition.LogStaticDefinitionauto-upgrades
toTemplateLogProcessorwhen the configured message contains a
${...}placeholder, so users get template-interpolation without a
separate API.redb.Route(Core) —RouteContextnow registers the current
ILoggerFactoryinto its service collection so processors built from
.Log(...)/ template expressions can resolve their logger without
extra plumbing.
Tests
redb.Route(Tests) — new DSL reference suites that pin Camel
semantics with extensive scenario coverage:
Reference/DslChoiceReferenceTests.cs(~767 lines),
Reference/DslDoTryReferenceTests.cs(~441 lines),
Reference/DslFilterReferenceTests.cs(extended). These are the
authoritative compatibility specs for Choice/When/Otherwise,
TryCatchFinally and Filter scope semantics.redb.Route.Tests.Core— twelve tests (RedbRouteExtensionsTests,
RedbTransactedActionTests) were rewritten on top of the real
RouteDefinition+Exchangepipeline, removing the previous
IRouteDefinitionmock-based scaffolding.
IBM MQ diagnostics
redb.Route.IbmMq— diagnostic timing aroundMQGET. The consumer
emits aDebug-levelMQGET blocked for {N}mslog entry for any blocking
get longer than ~50 ms. This was originally raised atInformationwhile
diagnosing a ~500 ms producer→consumer latency in production; it has been
lowered toDebugso it stays silent under default verbosity and only
lights up when ops explicitly enable IBM MQ diagnostics.
IbmMqProducer/IbmMqMessageHelper/IbmMqEndpoint/
IbmMqComponentreceived the supporting plumbing.
Known limitations
-
redb.Route.IbmMq— ~500 ms minimum end-to-end latency on the managed
client. The managed IBM MQ .NET client (amqmdnetstd.dll) used by this
package is not event-driven onMQGETwithMQGMO_WAIT. It carries
an internal polling tick of ~500 ms that is independent of the
WaitIntervalsupplied inMQGMO:WaitIntervalonly governs the upper
timeout, not the lower delivery-granularity bound. As a result the
typical producer→consumer latency on this transport is ~500 ms even after
channel reconfiguration (we have validatedSHARECNV(1)on
DEV.APP.SVRCONN— it does not change the floor). The native
(unmanaged) client is event-driven but requires the IBM MQ Client
redistributable to be installed on the host, which is not viable for
self-contained .NET deployments and is therefore not used here.Planned fix: rewrite
IbmMqConsumer.ReceiveLoopAsyncto use the
managed async-consume API (MQQueue.Cb(...)+
MQQueueManager.Ctl(MQOP_START, ...)). With the callback path the broker
pushes messages and per-message latency drops to ~0. Tracked for a future
release; the change is non-trivial because the loop becomes
callback-driven (different cancellation, back-pressure and lifecycle
model than the current poll loop). See the in-sourceKNOWN ISSUEblock
inIbmMqConsumer.csfor
details.Field diagnosis recipe. Enable
Debugon
redb.Route.IbmMq.IbmMqConsumerand inspect the
MQGET blocked for {N}mslog line:N ≈ 500 msconsistently → managed-client polling tick; the
MQCB rewrite above is required.N < 50 mswhile end-to-end latency is still ~500 ms → the
bottleneck is on the producer side (PUT missing a flush or an
extra round-trip), not the consumer.
Added — Telemetry (carried over)
redb.Route(Telemetry) — shared telemetry identity. BothMeterand
ActivitySourcenow use a single canonical nameredb.Route, exposed via
theRouteActivitySource.TelemetryNameconstant (also surfaced as
RouteActivitySource.SourceNameandRouteMetrics.MeterName). OTel
collectors can subscribe once and get both signals.redb.Route(Telemetry) —RouteTelemetryExtensions.StartTransportSpan(...)
helper that opens a transport span with the conventional OpenTelemetry
semantic attributes (messaging.system/db.system/http.method/
rpc.system/network.transport, plusredb.route.endpoint,
messaging.destination.name,messaging.operation). Returnsnullwhen
no listener is registered (zero overhead).redb.Route(Telemetry) —ProcessorMetricsgained 16 new instruments
covering the previously-unmeasured EIP processors:- WireTap:
redb.route.wiretap.dispatched,redb.route.wiretap.failed - Multicast:
redb.route.multicast.branches,redb.route.multicast.failed_branches - Recipient List:
redb.route.recipientlist.recipients - Aggregator:
redb.route.aggregator.completed,
redb.route.aggregator.timed_out,redb.route.aggregator.inflight_groups - Idempotent Consumer:
redb.route.idempotent.duplicate,
redb.route.idempotent.passed - Retry:
redb.route.retry.attempts,redb.route.retry.success,
redb.route.retry.exhausted - Saga:
redb.route.saga.completed,redb.route.saga.compensated,
redb.route.saga.failed - Dead Letter:
redb.route.deadletter.sent
- WireTap:
redb.Route(Telemetry) —MeteredProcessornow enriches every metric
point with the new tagsredb.route.endpoint(canonical endpoint URI) and
redb.route.scheme(transport scheme such ashttp,kafka,postgres)
in addition to the existingredb.route.id.- Transport spans — 16 producers now open a transport span via the new
helper, producing OpenTelemetry-compliant span trees from the route pipeline
down to the wire:Http,Sql,Sql(procedure),Grpc,MqttNet,
AzureServiceBus,Redis,Elasticsearch,Tcp,S3,GenericFile
(covers File / Sftp / Ftp),Firebase.Storage,Firebase.Firestore,
Firebase.Fcm,WebSocket,SignalR. The five previously-instrumented
transports (Kafka,RabbitMQ,IbmMq,Amqp,Mail,Ldap) keep their
existing spans unchanged.
Changed
redb.Route(DSL) —IOldRouteDefinitionrenamed toIRouteDefinition
and all consumer projects (redb.Route.Controllers,
redb.Route.Core,redb.Route.Validation.Adapters,
redb.Route.Tests.Core) realigned. The Camel-style canonical name is now
the single name across the public API.redb.Route—MeteredProcessorconstructor signature gained two
optional parametersendpointUriandendpointScheme. Existing call sites
that only pass(inner, routeId)continue to work;RouteContextnow wires
the endpoint URI and scheme so dashboards can slice metrics per endpoint.redb.Route—InstrumentedProcessor.ActivityExtensions.RecordException
uses `Activity....
Assets 2
v2.0.2
redb.Route 2.0.2. See CHANGELOG.md for details. NuGet: https://www.nuget.org/packages?q=redb.Route
Assets 2
v2.0.0
redb.Route 2.0.0 — aligns with RedBase 2.0 train. License migrated MIT → Apache-2.0 for OSS packages. See CHANGELOG.md for details. NuGet: https://www.nuget.org/packages?q=redb.Route
Assets 2
v1.0.4
Changelog
All notable changes to redb.Route will be documented in this file.
This changelog covers the NuGet-published packages:
| Package | Description |
|---|---|
redb.Route |
Core engine: DSL, processors, expressions, telemetry |
redb.Route.Amqp |
AMQP 1.0 transport |
redb.Route.AzureServiceBus |
Azure Service Bus transport |
redb.Route.Controllers |
Transport-agnostic controller dispatch |
redb.Route.Core |
Bridge to redb.Core EAV storage |
redb.Route.Elasticsearch |
Elasticsearch 8.x transport |
redb.Route.File |
File system transport |
redb.Route.Firebase |
Firebase (Firestore, Cloud Storage, FCM) transport |
redb.Route.Ftp |
FTP/FTPS transport |
redb.Route.GenericFile |
Base library for file-based transports |
redb.Route.Grpc |
gRPC transport |
redb.Route.Http |
HTTP/HTTPS transport |
redb.Route.IbmMq |
IBM MQ transport |
redb.Route.Kafka |
Apache Kafka transport |
redb.Route.Ldap |
LDAP / Active Directory transport |
redb.Route.Mail |
Email transport (SMTP, IMAP, POP3) |
redb.Route.MqttNet |
MQTT 5.0 transport |
redb.Route.Quartz |
Quartz.NET scheduling transport |
redb.Route.RabbitMQ |
RabbitMQ transport |
redb.Route.Redis |
Redis transport |
redb.Route.S3 |
AWS S3 / MinIO transport |
redb.Route.Sftp |
SFTP transport |
redb.Route.SignalR |
SignalR transport |
redb.Route.Sql |
SQL database transport |
redb.Route.Tcp |
Raw TCP transport |
redb.Route.Validation.Adapters |
FluentValidation + DataAnnotations adapters |
redb.Route.WebSocket |
WebSocket transport |
The format is based on Keep a Changelog,
and this project adheres to Semantic Versioning.
Note on version history: redb.Route has been running in production since version 1.0.0.
Versions 1.0.0 – 1.0.3 were not published to NuGet (internal deployments only).
The first public NuGet release is 1.0.4.
[1.0.4] — 2026年05月06日
First public NuGet release. The library has been production-tested since 1.0.0.
Added
Core engine (redb.Route)
- Fluent DSL:
From → Process → Topipeline definition viaIRouteDefinition RouteBuilderbase class for encapsulating route logic in dedicated classes- Two-phase architecture: define (record
RouteSteplist) → compile (RouteCompilerbuilds processor chain) - 24 EIP pattern processors: Filter, Choice, Split, Aggregate, WireTap, Multicast, RecipientList, DynamicRouter, Loop, Delay, Resequencer, Enrich, PollEnrich, IdempotentConsumer, Throttle, CircuitBreaker, Retry, DeadLetterChannel, DoTry/DoCatch/DoFinally, Transacted, Respond
- Expression engine:
Body,Header,Property,Constant,JPath,XPath,StringExpression(Expr),Exchange - 17 predicate methods:
isEqualTo,isNotEqualTo,isGreaterThan,isLessThan,isGreaterThanOrEqualTo,isLessThanOrEqualTo,isBetween,contains,startsWith,endsWith,regex,In,isNull,isNotNull,Handled,ExceptionHandled - String expression templates:
${header.name},${body},${property.key} - Built-in components:
Direct,SEDA,Timer,Log,Mock - Validation: JSON Schema (
JsonSchemaValidator), XSD (XsdValidator), predicate (PredicateValidator) - Serialization: JSON and XML marshal/unmarshal
- Error handling:
OnException<T>with max redeliveries, exponential backoff, dead-letter routing - OpenTelemetry: distributed tracing (
Traced) and metrics (Metered) per route and per step - Structured logging DSL:
.Log(LogLevel).Message().Header().ShowRouteId() InOutexchange pattern supportRouteIdfor route identification and introspectionRouteEngineOptionsfor telemetry and metrics configuration- Multi-target:
net8.0,net9.0,net10.0
Transports
redb.Route.Kafka— consumer/producer, consumer groups, SASL/SSL, transactions, Confluent.Kafka 7.xredb.Route.RabbitMQ— queues, exchanges, DLX, priority, TTL, quorum queues, RabbitMQ.Client 7.xredb.Route.Redis— Pub/Sub, Streams (consumer groups), KV, Lists, Sorted Sets, Geo, StackExchange.Redisredb.Route.Sql— ADO.NET polling consumer, query/batch producer, stored procedures, provider-agnosticredb.Route.Http— HttpClient producer, Kestrel consumer, CORS, auth, TLS, named URL parametersredb.Route.Grpc— GrpcChannel client, Kestrel server, binary message exchangeredb.Route.File— polling consumer with glob, read locking, idempotency; atomic producer with temp-fileredb.Route.Sftp— SSH.NET, key/password auth, proxy, glob, chmod, recursive traversalredb.Route.MqttNet— MQTT 5.0, QoS 0/1/2, shared subscriptions, retained, TLS, MQTTnetredb.Route.Amqp— AMQP 1.0 (Artemis, Azure SB, Amazon MQ, Qpid), AMQPNetLiteredb.Route.Mail— SMTP producer, IMAP/POP3 consumers with IDLE push, attachments, OAuth, MailKitredb.Route.Tcp— text-line, length-prefixed, raw framing, TLS, InOut request-replyredb.Route.WebSocket— ClientWebSocket producer, Kestrel server consumer, ping/pong, subprotocolredb.Route.Quartz— Cron expressions, interval timers, Quartz.NET thread poolredb.Route.AzureServiceBus— queues, topics, sessions (FIFO), PeekLock/ReceiveAndDelete, batch sendredb.Route.Elasticsearch— 9 producer operations (index, update, delete, bulk, etc.), polling consumer, Elasticsearch 8.xredb.Route.Firebase— Firestore (CRUD, queries, batch), Cloud Storage, FCM; shared credential providerredb.Route.Ftp— FluentFTP, passive/active, FTPS/TLS, jail-path protection, idempotencyredb.Route.IbmMq— IBM MQI, queues, topics, transactions, RPC, message groups, W3C telemetryredb.Route.Ldap— LDAP/AD search, CRUD, authentication, change tracking, Novell.Directory.Ldapredb.Route.S3— AWS S3 + MinIO, multipart upload, SSE (S3/KMS/C), presigned URLs, versioning, Glacier restoreredb.Route.SignalR— Hub consumer (server), client producer (HubConnection), broadcast producer (IHubContext)
Integration & adapters
redb.Route.Core—RedbIdempotentRepositorybacked by redb.Core EAV;IRedbServiceaccess from routesredb.Route.Controllers—RedbController, attribute routing, parameter binding, 4 dispatchers (generic, HTTP, SignalR, gRPC)redb.Route.GenericFile— shared base for File, FTP, SFTP (abstract consumer/producer, options, file-ops interfaces)redb.Route.Validation.Adapters—FluentValidationMessageValidator<T>,DataAnnotationsValidator, DSL extensions