Connector framework — architecture (arc42)

Architecture documentation for the connector framework, structured per the arc42 template (12 sections) and encoded with sphinx-needs using the useblocks “x-as-code” conventions (https://x-as-code.useblocks.com/how-to-guides/arc42/index.html).

Each architectural element :refines: or :implements: a parent requirement from Connector framework so the trace is preserved end-to-end.

This chapter is split across pages (see the toctree): the framing sections §1–§3 (goals, constraints, context and scope — including the system-context mermaid) live here on the index; the solution strategy and its ADRs (§4) live in Solution strategy; the building-block decomposition (§5) lives in Building block view; the runtime scenarios (§6) live in Runtime view; the two deployment shapes (§7) live in Deployment view; the crosscutting concepts (§8) and the cross-cutting traceability tables live in Crosscutting concepts; the architecture-decision and quality-requirement pointers (§9–§10) live in Architecture decisions; the risks and glossary (§11–§12) live in Risks and glossary; the crate implementations (§13) live in Implementations; and the connector cycle telemetry design lives in Connector cycle telemetry.


1. Introduction and goals

The connector framework’s reason-to-exist is fault isolation: keep messy network protocol code (MQTT, OPC UA, gRPC, fieldbus) outside the taktora-executor application’s deterministic core, while preserving zero-copy data flow. Quality goals capture the qualities that the architecture is optimised for.

Quality Goal: Fault isolation between protocol stack and app QG_0001
status: open
refines: FEAT_0030

A panic, hang, or crash in a protocol stack (rumqttc, opcua, tonic, ADS) shall not be able to crash, deadlock, or stall the taktora-executor application that uses the framework. This goal is what motivates the gateway-as-separate-process deployment shape and the single-direction control plane.

Quality Goal: Compile-time type safety end-to-end QG_0002
status: open
refines: FEAT_0030

Plugin code that targets a specific protocol shall be checked at compile time for routing correctness, codec compatibility, and payload-size compliance. Runtime “config-as-strings” indirection shall be avoided; type errors are caught by cargo check.

Quality Goal: Zero-copy data flow on the publish path QG_0003
status: open
refines: FEAT_0031

Outbound messages from the application to the broker shall not be copied into any intermediate buffer between the codec’s encode call and the iceoryx2 publish. The iceoryx2 Publisher::loan mechanism carries the codec’s output directly to shared memory.

Quality Goal: Uniform observable health across connectors QG_0004
status: open
refines: FEAT_0034

Every connector — regardless of which protocol stack owns its reconnect mechanism — shall report the same four health states (Up / Connecting / Degraded / Down) on a single observable channel, so monitoring and alerting code is connector-agnostic.


2. Constraints

Constraints come from the surrounding workspace and the iceoryx2 ecosystem; they are non-negotiable inputs to the architecture.

Constraint: Built on taktora-executor's WaitSet CON_0001
status: open
refines: FEAT_0030
is refined by: ADR_0007

The plugin and gateway shall be taktora-executor consumers (ExecutableItem-based, WaitSet-driven). The framework shall not introduce a second reactor model running alongside taktora-executor.

Constraint: iceoryx2 0.8.x as the IPC layer CON_0002
status: open
refines: FEAT_0030
links incoming: RISK_0002

The framework shall use the workspace’s pinned iceoryx2 version (0.8 per Cargo.toml workspace dependencies). Migration to a later iceoryx2 series is a follow-on effort outside this spec.

Constraint: Rust 2024 edition / MSRV 1.85 CON_0003
status: open
refines: FEAT_0030

All new crates shall target edition 2024 with MSRV 1.85, matching the workspace’s rust-toolchain.toml and [workspace.package].

Constraint: Single-threaded test discipline CON_0004
status: open
refines: FEAT_0030

Workspace tests run with --test-threads=1 because each iceoryx2 service must own a unique name in shared memory. New crates’ integration tests shall be safe under this discipline (per-test Node names + per-test tokio runtimes).

Constraint: Tokio sidecar contained per connector crate CON_0005
status: open
refines: FEAT_0030

Where async protocol stacks (rumqttc, tonic) require tokio, each connector crate shall host its own tokio runtime sidecar; tokio shall not appear as a dependency of taktora-connector-core, taktora-connector-transport-iox, or taktora-connector-codec.


3. Context and scope

Architecture View: System context ARCH_0001
status: open
refines: FEAT_0030

The connector framework sits between a taktora-executor application and one or more external systems (brokers, servers, PLCs). Internally, the boundary is split between a plugin (in-app side) and a gateway (out-of-app side); externally, the gateway is the only component that touches network I/O.

        flowchart LR
  APP["taktora-executor application<br/>(plugin uses Connector trait)"]
  SHM[("iceoryx2 shared memory<br/>+ event service")]
  GW["taktora-connector gateway<br/>(tokio + protocol stack)"]
  EXT[("external system<br/>e.g. MQTT broker")]
  APP -- ConnectorEnvelope --> SHM
  SHM -- ConnectorEnvelope --> APP
  SHM -- ConnectorEnvelope --> GW
  GW -- ConnectorEnvelope --> SHM
  GW -- protocol native --> EXT
  EXT -- protocol native --> GW
    

In-process deployment collapses the SHM hop to a single-process shared-memory transport but preserves the same envelope contract; see In-process gateway deployment (ARCH_0020) and Separate-process gateway de... (ARCH_0021).