Managed SRT pull
Start and supervise an SRT source connection from this node.
input.srt.pull
input.srt.pull dials an SRT source as a caller. The API and startup list are independent: api.enabled exposes /api/v1/pulls, while static applies entries once during process startup.
A transport disconnect keeps the logical pull alive during bounded retry. Exhausting the retry deadline is terminal until an API request or process restart creates the pull again.
When traditional HLS output is enabled, reconnecting transport sessions share one process-local sequence and discontinuity lineage for the logical pull. The public playlist path stays unchanged, while each successor session publishes segments from a new incarnation namespace. An explicit DELETE followed by a new PUT creates a new lineage.
"pull": {
"api": {"enabled": true},
"maxActivePulls": 8,
"static": [{
"streamId": "${STREAM_ID}",
"source": "${SOURCE_SRT_URL}",
"srtStreamId": "${SOURCE_STREAM_ID}",
"passphrase": "${SOURCE_PASSPHRASE}"
}]
}
Static entries are startup input rather than continuous reconciliation. Deleting a static pull through the API does not recreate it until the process starts again.
Fenced operation API
The operation API is the control-plane contract for a scheduler that must
recover after losing an HTTP response. It is process-local. A different
originIncarnation never proves that an operation against the previous
process stopped; the caller must keep that outcome unresolved until the old
process is proven dead.
GET /api/v1/pull-control/capabilities returns:
{
"schemaVersion": 1,
"operationContract": "v1",
"originIncarnation": "00000000-0000-4000-8000-000000000001",
"writerEpoch": "",
"lastSequence": "0",
"maxRetainedOperations": 128
}
The UUID values in this page are shape examples. Each process and writer must
use newly generated random UUIDs. PUT /api/v1/pull-control/writer performs a
global compare-and-swap with originIncarnation, expectedWriterEpoch, and
newWriterEpoch. The process-wide decimal lastSequence never resets when the
writer changes. A writer fence and every operation commit use the same
controller ownership lock.
PUT /api/v1/pull-operations/{operationId} accepts:
{
"originIncarnation": "00000000-0000-4000-8000-000000000001",
"writerEpoch": "00000000-0000-4000-8000-000000000002",
"sequence": "1",
"kind": "start",
"streamId": "tenant:stream",
"expectedInstanceId": null,
"spec": {"source": "srt://source.example:9000"}
}
A start requires explicit expectedInstanceId: null and a pull spec. A stop
requires the exact instanceId reported by the pull inventory and forbids a
spec. The instance ID is stable for the logical pull while transport
generations change on reconnect. All decimal sequence strings are canonical:
1 is valid, while +1, 01, and 0 are rejected.
The result contains operationId, originIncarnation, writerEpoch,
sequence, kind, streamId, state, and optional instanceId and
errorCode. A start returns committed. A stop first returns draining, then
becomes fully_drained only after dial, media worker, sink, output scope, and
registry ownership have all been released. A registry release error produces
failed with drain_failed and keeps its admission budget quarantined. An
exact stop can also clear a retained terminal-failure tombstone as
fully_drained when its registry ownership was released. A mismatched
instance ID is rejected, and a tombstone whose registry ownership remains
reserved returns failed with drain_failed.
Process shutdown seals new legacy and operation admission, stops active pulls,
and waits within the shutdown context for pulls that an earlier stop already
removed from inventory. A context timeout remains a reported shutdown error;
it never turns an outstanding drain into fully_drained.
An expected-instance mismatch and a pull-limit rejection happen before any
pull side effect. Their retained result is not_committed with the exact
operation identity and stable error code. A recovering writer may use that
proof only after fencing the writer epoch that submitted it; a current writer
must still allow for a delayed request.
GET /api/v1/pull-operations/{operationId} requires the exact
originIncarnation, writerEpoch, and sequence query tuple. A retained exact
record remains queryable after a later writer fence. A missing operation from
an older fenced writer with a sequence above the process watermark returns
fenced. A missing sequence at or below the watermark returns failed with
unknown_retention. A missing operation for the current writer returns
failed with operation_unknown, because a delayed request may still arrive.
The synthetic results omit kind and streamId. Retained committed,
fully_drained, and not_committed results carry the complete operation
identity. Unknown, retention, and incarnation-mismatch outcomes are
fail-closed.
The ledger retains at most 128 records. Terminal records are evicted in
sequence order. A draining record cannot be evicted; if every slot is
non-terminal, a new operation is rejected before its sequence or side effect
commits. An identical operation ID and canonical request replays the retained
result. Reusing an ID with different input, or reusing a consumed sequence
under another ID, is rejected.
New committed starts return HTTP 201, newly accepted stops return HTTP 202, and retained or queried results return HTTP 200. Errors use the normal JSON error envelope with these stable codes:
| HTTP | Code | Meaning |
|---|---|---|
| 400 | invalid_request |
The operation envelope, UUID, sequence, or shape is invalid. |
| 400 | invalid_pull_spec |
The nested start spec is invalid. |
| 409 | stale_origin |
The requested origin incarnation is not this process. |
| 409 | fenced |
The writer epoch is no longer current. |
| 409 | operation_conflict |
A retained operation ID has different input. |
| 409 | sequence_reused |
The process watermark already consumed the sequence. |
| 409 | instance_precondition_failed |
Expected absence or exact instance ownership did not match. |
| 429 | operation_capacity |
Every retained ledger slot is non-terminal. |
| 429 | pull_limit |
Active and draining pull ownership reached its configured limit. |
| 500 | operation_failed |
An internal operation step failed before a safe result was available. |
| 503 | control_closed |
Process shutdown permanently closed mutation admission. |
See the shared input contract and complete configuration.
Configuration reference
The complete field reference covers every accepted option; the maximal composition shows how modules fit together.