mbproxy: initial commit through Phase 9 (TxId multiplexing)
Adds the mbproxy service end-to-end. Phases 00-08 implement the production-ready single-listener / 1:1-backend transparent Modbus TCP proxy with bidirectional BCD rewriting for the ~54-PLC DL205/DL260 fleet. Phase 9 replaces the connection layer with a single backend socket per PLC plus MBAP TxId rewriting, lifting the H2-ECOM100's 4-concurrent-client cap as an operational ceiling. Phase 9 additions of note: - PlcMultiplexer + UpstreamPipe + TxIdAllocator + CorrelationMap - InFlightRequest with IReadOnlyList<InterestedParty> (load-bearing for Phase 10 read coalescing — do not collapse to a single field) - Per-request watchdog: surfaces Modbus exception 0x0B to upstream on BackendRequestTimeoutMs, defending against lost responses, dead-PLC paths, and pymodbus 3.13.0's concurrent-multiplexed- request bug (its ServerRequestHandler.last_pdu state race) - Status DTO + HTML gain inFlight / maxInFlight / txIdWraps / disconnectCascades / queueDepth (Tier 1.6 in docs/kpi.md) Tests: 263 unit + 38 E2E. Multiplexer correctness under truly concurrent backend traffic is proved against a stub backend in PlcMultiplexerTests; MultiplexerE2ETests paces requests so pymodbus 3.13's single-PDU framer stays in known-good mode. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,32 @@
|
||||
namespace Mbproxy.Bcd;
|
||||
|
||||
/// <summary>Discriminates the class of validation failure in a resolved BCD tag list.</summary>
|
||||
public enum BcdValidationError
|
||||
{
|
||||
/// <summary>Two or more entries share the same Modbus register address.</summary>
|
||||
DuplicateAddress,
|
||||
|
||||
/// <summary>
|
||||
/// A 32-bit entry's high register (Address+1) collides with another entry's address.
|
||||
/// </summary>
|
||||
OverlappingHighRegister,
|
||||
|
||||
/// <summary>An entry has a Width that is not 16 or 32.</summary>
|
||||
InvalidWidth,
|
||||
}
|
||||
|
||||
/// <summary>A hard validation failure that prevents the map from being used.</summary>
|
||||
public sealed record BcdError(BcdValidationError Kind, string Message, ushort? Address);
|
||||
|
||||
/// <summary>A non-fatal advisory that rides along with the map.</summary>
|
||||
public sealed record BcdWarning(string Message, ushort? Address);
|
||||
|
||||
/// <summary>
|
||||
/// Result of a <see cref="BcdTagMapBuilder.Build"/> call.
|
||||
/// When <see cref="Errors"/> is non-empty the map is partial (only valid entries are included).
|
||||
/// Callers should treat any error as a fatal configuration problem at startup.
|
||||
/// </summary>
|
||||
public sealed record ValidationResult(
|
||||
BcdTagMap Map,
|
||||
IReadOnlyList<BcdError> Errors,
|
||||
IReadOnlyList<BcdWarning> Warnings);
|
||||
Reference in New Issue
Block a user