Skip to content

investigate: per-device operation serialization for concurrent consumers #342

Description

@tylerkron

Type: Investigation
Priority: Medium

Description

Core serializes concurrent text exchanges (_textExchangeLock, #186) but nothing else: concurrent calls into EnableChannel/SetDioValue/StartStreaming/network-config from multiple threads interleave SCPI writes with no device-level mutual exclusion.

The in-repo MCP server had to solve this itself because the MCP transport dispatches tool calls concurrently: it keeps a ConcurrentDictionary registry plus a SemaphoreSlim _gate that serializes every mutating operation, along with stale-handle detection and eviction (src/Daqifi.Mcp/DaqifiAgent.cs:28-29, 77-110, 467-482). Any multi-threaded consumer — a desktop UI, a web service — must reinvent the same gate to avoid corrupting device state.

Worth investigating rather than assuming a design: options range from (a) documenting "one operation at a time per device" as the consumer's contract, to (b) an internal per-device operation lock around command-sending members, to (c) a small session/connection-manager type that owns serialization + reconnect. Option (b) is likely the simplest meaningful step, but it interacts with streaming callbacks and the existing text-exchange lock, so it needs a careful look first.

Acceptance Criteria

  • Decide and document the concurrency contract for DaqifiDevice/DaqifiStreamingDevice (thread-safety section in DEVICE_INTERFACES.md is updated to match reality)
  • If Core takes ownership: mutating operations are serialized per device, and the MCP server's hand-rolled _gate shrinks or disappears
  • If consumers keep ownership: the contract is stated loudly in docs, with the MCP pattern as the reference implementation

Value

Today the concurrency contract is implicit and every concurrent consumer discovers it the hard way; either outcome of the investigation removes that trap.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions