Commit Graph
2 Commits
Author SHA1 Message Date
leonarski_fandClaude Opus 5.5 2981aedd3e Broker: a collection can be followed from /start, its start message comes in the event stream
With a DECTRIS detector the broker starts the writers - and so learned the collection's start
message - only when the detector's own start message arrived, after /start had returned. A reader
started right after /start found no collection (404) and had to wait for, and race with, the
detector.

- /start registers the collection in LiveCollection (Expect) as it is accepted, so GET /live/events
  is accepted from then on. The image pusher fills in the start message when it starts the writers
  (Begin) - at once on the FPGA path, when the detector's start message arrives on the DECTRIS path.
- The event stream's first event is now `start`, carrying that start message (CBOR, base64) with
  run number, file prefix, image count and images per file; it replaces `collection`. Until it is
  known the stream only keeps alive. file and end follow as before.
- However the measurement thread ends, it ends a collection the pusher did not end (EndIfOpen), so a
  cancel or a failure before the detector streamed reaches the reader as `end` with an error. The
  wait is event-driven: it ends with the start message or with the measurement.
- GET /live/start.cbor is removed: the stream carries the start message, one route less.
- rugnux takes the start message from the stream (BrokerFeed::WaitForStart), so it can be started
  right after /start; files reported before it attached the reader are replayed to it.

Tests: LiveCollection_ExpectedAtStart; BrokerFeed_StartFromEventStream (an event stream whose start
message comes late, then a file and the end).

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SVmAWnzCmRKAXVUCdc4iNi
2026-10-08 17:03:09 +02:00
leonarski_fandClaude Opus 5.5 509a54ef92 Broker: tell a reader which data files of the current collection are closed
So that rugnux can process a collection while it is written, the broker reports each data file once
a writer has closed it and renamed it into place:

- Writer: FileWriter takes a callback, called for every closed data file. StreamWriter uses it on TCP
  to send an acknowledgement with ack_for = FILE_CLOSED (new TCPFrameType 10): file number and the
  images the file holds. TCP protocol version 5. Files closed at END are reported before the END
  acknowledgement.
- LiveCollection (image_pusher): the start message the writer of the master file received, the
  closed files, the end. Fed by the TCP pusher (FILE_CLOSED acknowledgements; end once every writer
  acknowledged END) and by the in-process HDF5 pusher (the FileWriter callback). The ZeroMQ pusher
  has no back channel and offers none.
- Two routes, protected by the dataset's bearer tokens like the other dataset routes:
  - GET /live/start.cbor: that start message;
  - GET /live/events: server-sent events (collection, file, end, superseded) with the history first
    and a keepalive every 10 s. One follower at a time; a second gets 409.
  Documented in jfjoch_api.yaml; they add no schema, so the generated C++ model is unchanged.
- The HTTP server's thread pool is set explicitly (16, up to 64): an event stream holds a thread for
  the whole collection.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SVmAWnzCmRKAXVUCdc4iNi
2026-10-08 15:52:21 +02:00