redb.Route.GenericFile
4.1.0
Prefix Reserved
dotnet add package redb.Route.GenericFile --version 4.1.0
NuGet\Install-Package redb.Route.GenericFile -Version 4.1.0
<PackageReference Include="redb.Route.GenericFile" Version="4.1.0" />
<PackageVersion Include="redb.Route.GenericFile" Version="4.1.0" />
<PackageReference Include="redb.Route.GenericFile" />
paket add redb.Route.GenericFile --version 4.1.0
#r "nuget: redb.Route.GenericFile, 4.1.0"
#:package redb.Route.GenericFile@4.1.0
#addin nuget:?package=redb.Route.GenericFile&version=4.1.0
#tool nuget:?package=redb.Route.GenericFile&version=4.1.0
redb.Route.GenericFile
Shared base library for file-based transports in the redb.Route ESB framework.
Provides abstract consumer, producer, options, and file-operations interfaces that concrete transports (File, FTP, SFTP) inherit from. Not used directly — include one of the transport-specific packages instead.
Architecture
GenericFileEndpointOptions ← base options (polling, filtering, producer write)
└─ RemoteFileEndpointOptions ← + host/port/auth/reconnect
GenericFileConsumer<TOptions> ← template-method poll loop
└─ RemoteFileConsumer<TOptions> ← + connect/reconnect lifecycle
GenericFileProducer<TOptions> ← template-method write flow
└─ RemoteFileProducer<TOptions> ← + connect/reconnect lifecycle
IFileOperations ← protocol abstraction (list, read, write, move, delete)
└─ IRemoteFileOperations ← + connect/disconnect
Transport implementations (File, Ftp, Sftp) provide concrete IFileOperations and transport-specific headers/DSL. All polling logic, filtering, idempotency, post-processing, atomic write, and file-exist strategies are implemented in this base library.
Consumer Pipeline
The GenericFileConsumer runs a poll loop with the following steps:
- List files in the base directory (optionally recursive)
- Filter — exclude temp/internal files (
.redb_*, temp prefix), apply globinclude/excludepatterns - Sort — by name, date, or size (ascending or descending)
- Limit — apply
maxMessagesPerPoll - Eligibility checks —
minAge,maxAge, done-file presence - Read lock — transport-specific claim on the file (local file only)
- Idempotency — skip files already in the repository
- Pre-move — optionally move to a staging directory before processing
- Read body — as
byte[](default) orStream(streamBody=true) - Invoke processor — pass exchange to the downstream pipeline
- Post-process —
Noop(leave in place) /Delete/MoveTo - Confirm — mark idempotent key, delete done file
The read lock is taken before the idempotency claim: a consumer that loses the lock race must not consume the idempotent key, or the file would never be picked up again by anyone.
On processing failure: remove idempotent key, leave the file in place, move to moveFailed
directory (if configured). A file that cannot be read is treated the same way — it is
never delivered as an empty message.
Producer Pipeline
The GenericFileProducer writes files with atomic temp-then-rename:
- Resolve body — from
exchange.Out(if set) orexchange.In - Resolve target path — from
FileNameoption / header / auto-generated GUID - Validate path — jail-directory check (transport-specific)
- Create directories — if
autoCreate=true - Write to temp file — using
tempPrefixortempFileName - Handle existing — apply
fileExiststrategy (Override / Append / Fail / Ignore / Move / TryRename) - Atomic rename — move temp file to target
- Cleanup — delete temp file on failure
Options Reference
GenericFileEndpointOptions (Base)
Consumer / Polling
| Property | Type | Default | Description |
|---|---|---|---|
Delay |
int |
500 |
Poll interval (ms) |
InitialDelay |
int |
0 |
Delay before first poll (ms) |
Include |
string |
"" |
Glob include pattern (*.csv,*.xml) — file name only |
Exclude |
string |
"" |
Glob exclude pattern — file name only |
AntInclude |
string |
"" |
Ant patterns over the path relative to the polled directory (TYPE_A/outbox/*.csv): * stops at a separator, ** spans levels |
AntExclude |
string |
"" |
Ant patterns over the relative path that drop a file (archive/**) |
AntFilterCaseSensitive |
bool |
true |
Whether the Ant patterns respect case |
FilterDirectory |
string |
"" |
Condition over a subdirectory, evaluated before it is listed |
FilterFile |
string |
"" |
Condition over a polled file, evaluated before it is read or moved |
Filter |
string |
"" |
Registry name of an IGenericFileFilter (#myFilter) |
Recursive |
bool |
false |
Recurse subdirectories |
MaxDepth |
int |
0 |
Max recursion depth (0 = unlimited) |
MinDepth |
int |
0 |
Min depth for file selection |
SortBy |
GenericFileSortBy |
None |
Sort: Name, NameDesc, Modified, ModifiedDesc, Size, SizeDesc |
MaxMessagesPerPoll |
int |
0 |
Max files per poll (0 = unlimited) |
MinAge |
long |
0 |
Min file age (ms) |
BackoffMultiplier |
int |
0 |
Skip this many polls once a threshold is hit (0 = backoff off) |
BackoffIdleThreshold |
int |
0 |
Consecutive idle polls (no exchange created) that arm the skip |
BackoffErrorThreshold |
int |
0 |
Consecutive failed polls (the poll itself threw) that arm the skip |
BackoffOnFailedExchanges |
bool |
false |
Beyond Camel: count a poll whose every exchange failed as an error for BackoffErrorThreshold |
Poll backoff follows Apache Camel ScheduledPollConsumer: after BackoffIdleThreshold idle
polls or BackoffErrorThreshold error polls, the next BackoffMultiplier polls are skipped (no
listing, no connect), then the counters reset. A skipped poll still waits Delay, so stopping the
consumer during a skip resolves within Delay. Entering backoff logs one warning; resuming logs one
info line. BackoffMultiplier requires at least one threshold, and a threshold requires a multiplier —
otherwise the endpoint refuses the configuration.
A file that fails in the route. By default (Camel parity) a poll that created exchanges counts as
success even if the route failed them, so a deterministically-bad file, or every file while the
downstream is down, is retried every Delay. Two remedies:
- Poison file →
OnException<T>().MaximumRedeliveries(n).RedeliveryDelay(...)and/orMoveFailedto quarantine it out of the poll directory. - Downstream down (every file fails) → set
BackoffOnFailedExchanges = true(with an error threshold + multiplier): a poll whose every created exchange failed unhandled then counts as an error and the consumer backs off instead of hammering the downstream. A poll with any success still counts as success.
Consumer / Post-Processing
| Property | Type | Default | Description |
|---|---|---|---|
Noop |
bool |
false |
Leave file in place after processing |
Delete |
bool |
false |
Delete file after processing |
MoveTo |
string |
"" |
Move after processing. Supports ${file:name} / ${file:name.noext} |
MoveExisting |
GenericFileExistStrategy |
Override |
Strategy at move target |
PreMove |
string |
"" |
Move before processing. Supports ${file:name} / ${file:name.noext} |
Only one of Noop, Delete, MoveTo can be set.
Consumer / Idempotency
| Property | Type | Default | Description |
|---|---|---|---|
Idempotent |
bool |
false |
Enable idempotent consumer |
IdempotentKey |
string |
"" |
Custom key. Supports ${file:name} / ${file:name.noext} only |
DoneFileName |
string |
"" |
Done-file pattern (${file:name}.done) |
Default idempotent key: "{fullPath}|{lastModifiedUtc:O}|{length}".
Consumer / Body
| Property | Type | Default | Description |
|---|---|---|---|
StreamBody |
bool |
false |
false → byte[], true → Stream |
Charset |
string |
utf-8 |
Character encoding |
Producer
| Property | Type | Default | Description |
|---|---|---|---|
FileName |
DynamicValue<string>? |
— | Target file name (expression) |
FileExist |
GenericFileExistStrategy |
Override |
Override, Append, Fail, Ignore, Move, TryRename |
TempPrefix |
DynamicValue<string>? |
— | Temp file prefix |
TempFileName |
DynamicValue<string>? |
— | Full temp file name |
AutoCreate |
bool |
true |
Auto-create parent directories |
AllowNullBody |
bool |
false |
Allow null body (empty file) |
EagerDeleteTargetFile |
bool |
true |
Delete target before writing |
AppendChars |
string? |
— | Chars appended after each write |
RemoteFileEndpointOptions (extends Base)
Connection
| Property | Type | Default | Description |
|---|---|---|---|
Host |
string |
localhost |
Server hostname |
Port |
int |
(transport-specific) | Server port |
Username |
string? |
— | Auth username |
Password |
string? |
— | Auth password |
ConnectionTimeout |
int |
30000 |
Connection timeout (ms) |
OperationTimeout |
int |
60000 |
Operation timeout (ms) |
Reconnection
| Property | Type | Default | Description |
|---|---|---|---|
MaximumReconnectAttempts |
int |
3 |
Max reconnect attempts on failure |
ReconnectDelay |
int |
1000 |
Delay between attempts (ms) |
Disconnect |
bool |
false |
Disconnect after each poll/write |
Consumer-Specific
| Property | Type | Default | Description |
|---|---|---|---|
MaxAge |
long |
0 |
Max file age (ms, 0 = unlimited) |
MoveFailed |
string |
"" |
Move on failure. Supports ${file:name} / ${file:name.noext} |
StartingDirectoryMustExist |
bool |
false |
Fail if base dir doesn't exist |
SendEmptyMessageWhenIdle |
bool |
false |
Send empty exchange when no files |
Enums
GenericFileExistStrategy
| Value | Description |
|---|---|
Override |
Overwrite existing file |
Append |
Append to existing file |
Fail |
Throw exception |
Ignore |
Skip silently |
Move |
Rename existing file before writing |
TryRename |
Try alternate names |
GenericFileSortBy
| Value | Description |
|---|---|
None |
No sorting |
Name / NameDesc |
Sort by name |
Modified / ModifiedDesc |
Sort by last modified |
Size / SizeDesc |
Sort by size |
File Operations Interface
Transport implementations provide IFileOperations (or IRemoteFileOperations for network transports):
ListFilesAsync— enumerate files in a directoryReadAllBytesAsync/OpenReadAsync— read file contentsWriteAsync(byte[] / Stream) /AppendAsync/AppendTextAsync— writeExistsAsync/DeleteAsync/MoveAsync— file operationsCreateDirectoryAsync/DirectoryExistsAsync— directory operations- Path helpers:
CombinePath,GetParentPath,GetFileName,GetExtension, etc.
Glob Patterns
Include/exclude patterns support comma-separated values and */? wildcards:
*.csv — all CSV files
*.csv,*.xml — CSV and XML files
report_* — files starting with "report_"
data?.txt — data1.txt, dataA.txt, etc.
Path Filters
A glob sees only the file name, so it cannot say which directory a recursive poll should take. Four options decide by path, in the order the poll applies them (Apache Camel parity):
antInclude=TYPE_A/outbox/*.csv,TYPE_B/outbox/*.csv — Ant patterns over the path relative to the
antExclude=archive/** polled directory; '*' stops at a separator,
'**' spans levels, ',' separates patterns
filterDirectory=header.redbSftp.Name != 'archive' — asked per subdirectory BEFORE it is listed
filterFile=header.redbSftp.Length > 1024 — asked per file before it is read or moved
filter=#partnerFilter — an IGenericFileFilter from the registry,
for both files and directories
filterDirectory and the bean's AcceptDirectory decide while the listing is still walking, so a
directory they turn down costs nothing — no listing, no round trip. That is what makes one consumer
over a partner tree of two hundred directories affordable, and it is the only way to keep one
connection when the server allows only one.
Everything these filters reject is left exactly as it was found: no exchange is created for it, so
delete, move and preMove never touch it. Polling a parent recursively and sorting it out in
the route does the opposite — the file is downloaded and post-processed first.
Done File Substitutions
| Variable | Description |
|---|---|
${file:name} |
Full file name with extension |
${file:name.noext} |
File name without extension |
Requirements
- .NET 8.0 / 9.0 / 10.0
redb.Route(core) — no external dependencies
| 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 is compatible. 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
- redb.Route (>= 4.1.0)
-
net8.0
- redb.Route (>= 4.1.0)
-
net9.0
- redb.Route (>= 4.1.0)
NuGet packages (3)
Showing the top 3 NuGet packages that depend on redb.Route.GenericFile:
| Package | Downloads |
|---|---|
|
redb.Route.Sftp
SFTP transport for redb.Route ESB framework. Polling consumer and atomic producer with SSH.NET — key/password auth, proxy, idempotency, glob filtering, temp-file upload, chmod, recursive directories. |
|
|
redb.Route.File
File system transport for redb.Route ESB framework. Provides polling consumer and atomic file producer with locking, idempotency, and glob filtering. |
|
|
redb.Route.Ftp
FTP/FTPS transport for redb.Route ESB framework. Polling consumer and atomic producer with FluentFTP — passive/active mode, TLS, glob filtering, idempotency, temp-file upload, recursive directories. |
GitHub repositories
This package is not used by any popular GitHub repositories.
| Version | Downloads | Last Updated |
|---|---|---|
| 4.1.0 | 0 | 9/21/2026 |
| 4.0.1 | 58 | 9/18/2026 |
| 4.0.0 | 140 | 9/11/2026 |
| 3.7.2 | 149 | 8/26/2026 |
| 3.7.1 | 152 | 8/26/2026 |
| 3.6.0 | 145 | 8/13/2026 |
| 3.5.1 | 145 | 8/9/2026 |
| 3.5.0 | 155 | 8/6/2026 |
| 3.4.0 | 169 | 7/27/2026 |
| 3.3.3 | 174 | 7/16/2026 |
| 3.3.1 | 181 | 7/10/2026 |
| 3.3.0 | 177 | 7/8/2026 |
| 3.2.0 | 192 | 6/29/2026 |
| 3.1.0 | 185 | 6/6/2026 |
| 3.0.1 | 173 | 6/3/2026 |
| 3.0.0 | 191 | 5/29/2026 |
| 2.0.2 | 184 | 5/16/2026 |
| 2.0.0 | 83 | 5/6/2026 |