Skip to main content

Seeking

A handler moves its own file subscription through the seek handle: the driver task runs the client's seek, and what was queued from the old position is dropped.

A seek from a handler: the command, the client's seek, and the deliveries it discardsHandlerseeker.seek(position)Command to the driver taskoutside any select!FilePosition to the client's targeta sequence inclusive, an instant in nsThe client's seekruns to completionMoved:a new generationRefused: a livesubscription ends,a replay staysQueued deliveriesof the old generationare droppedThe next deliveryfrom the new positionA full channel does not hold a seek back: the driverserves seeks while it waits for room
The diagram as text
  1. Handler seeker.seek(position) → Command to the driver task outside any select!: sends
  2. Command to the driver task outside any select! → FilePosition to the client's target a sequence inclusive, an instant in ns
  3. FilePosition to the client's target a sequence inclusive, an instant in ns → The client's seek runs to completion
  4. The client's seek runs to completion → Moved: a new generation: moved
  5. The client's seek runs to completion → Refused: a live subscription ends, a replay stays: refused
  6. Moved: a new generation → Queued deliveries of the old generation are dropped
  7. Queued deliveries of the old generation are dropped → The next delivery from the new position
  8. A full channel does not hold a seek back: the driver serves seeks while it waits for room

The client's seek needs the consumer to itself and cannot be interrupted halfway. So the subscription's driver task owns the consumer, and a seek reaches it as a command. The driver runs the seek to completion, outside any race with the next read, and answers the handler when it is done.

A FilePosition becomes the client's target. The beginning and the tip map directly. A sequence number is inclusive, so seeking to a position read off a delivery delivers that message again. An instant in milliseconds becomes nanoseconds, and a value out of range is refused before the client sees it.

A seek that moved the reader opens a new generation, and the driver publishes it before it answers. The subscription drops every delivery stamped with an older one, so once seek returns, nothing read at the old position reaches the handler.

A refused seek, such as a sequence past the next one the file writes, leaves a replay where it was, with what it had read still queued. A live subscription ends instead: the client reads forward looking for the message and runs out of file. A replay that reached the end of the file can still seek, and it delivers again from the new position.

Seeks are served while the channel is full. The handler that stopped draining the channel may be the one waiting on a seek, so a backlog larger than the channel never blocks it. After shutdown, every seek is refused.

The in-process transport moves a subscription the same way, with the same refusals, inside the subscription's own poll.