Radiator Server Documentation — v10.34.2

gate

Use gate in a pipeline to serialize requests sharing a gate name and composite key. Different names or keys can run concurrently. Use the same gate name and canonical key values to coordinate different authentication pipelines. Acquisition preserves the previous action result.

@authentication {
    gate "OTP_AUTH" {
        key {
            aaa.identity;
        }
        timeout 2s {
            reject "Authentication busy. Try again.";
        }
        scope cluster;
    }

    backend {
        name "OTP_USERS";
        query "FIND_USER";
    }

    totp {
        secret_type "base32";
    }

    backend {
        name "OTP_USERS";
        query "UPDATE_TOTP_TIMESTEP";
    }
}
SettingDefaultMeaning
Gate nameRequiredQuoted name following gate.
keyRequiredNonempty block of ordered scalar expressions.
timeoutNoneOptional block specifying an acquisition deadline and the actions to run when it expires.
scopeclusterlocal coordinates this process; cluster also coordinates reachable configured peers.

Gate names must not be empty. Evaluate keys once, when the action runs. Each expression must return exactly one nonmissing scalar value. Supported values are strings, integers, and IP addresses. Types, expression order, and component boundaries participate in gate identity. UTF-8 binary strings and text strings containing the same text identify the same component. Raw bytes and binary strings containing invalid UTF-8 are not accepted directly. Use filters to explicitly convert other values into supported keys. For example, vars.binary_key | hex produces a string key from binary data. Add separate expressions for multiple key components; no string interpolation is required.

timeout accepts duration units. Bare numbers represent milliseconds. Omit the block to wait until the gate becomes available. 0s attempts immediate acquisition. The duration limits acquisition across all participants, not the duration of protected work. On expiry, run the timeout block and return its result from the owning pipeline. Subsequent actions in that pipeline do not run, including in an until end body. Other acquisition errors, such as invalid keys or peer authentication failures, remain action errors.

Ownership

The pipeline containing gate holds ownership through its remaining actions. Completion, rejection, error, and cancellation release its gates. Nested pipelines own their own acquisitions and release them when they exit. This includes a named @pipeline called with invoke. A gate acquired there releases when that pipeline exits, before the caller continues. Reacquiring an ancestor's gate with the same scope keeps the ancestor's ownership without waiting again. Exiting the nested pipeline does not release a gate already owned by its caller. Changing the scope of an already held gate produces an error. An until body's gates release before its when or else pipeline starts.

Other hooks, including @post_authentication, execute outside a gate acquired in @authentication. For OTP replay protection, keep the state read, validation, and successful state write inside the gated pipeline. The gate does not store OTP replay state itself.

Local cache updates

Use scope local to serialize cache fills for the same cache entry within one Radiator Server process. Different keys can fill concurrently. Separate processes on the same host have separate local gates.

Put the cache-fill operation in a named @pipeline and use the cache entry's identity as the gate key:

  1. Check the cache before invoking the pipeline. Use a cached value immediately when available.
  2. On a miss, invoke the pipeline and acquire the local gate.
  3. Check the cache again after acquisition. Another request may have populated it while this request waited.
  4. If the entry exists, finish the pipeline. Otherwise, perform the lookup, populate the cache, and finish the pipeline.

Use the cache action for the write so publication completes before the pipeline releases its gate. Assignments to cache.<name>[<key>] queue asynchronous writes and do not wait for publication.

Waiting requests acquire the gate in turn, see the populated entry, and finish without repeating the lookup. Populating the cache does not itself release the gate. The pipeline that acquired it must exit. Keep subsequent request processing outside that pipeline so it does not extend gate ownership. If a failed lookup leaves the cache empty, successive waiting requests can repeat the lookup.

Cluster scope

Without management cluster configuration, cluster behaves as local. With a cluster configured, select peers using heartbeat checks. Acquire ownership on this process and eligible peers in node-name order. Use matching peer membership, gate names, and gate keys on participating instances.

Known unreachable or stale peers are skipped before making a network request. Unobserved peers are tried until their first health probe completes; connection failures during acquisition are also skipped. A reachable peer holding the gate causes the request to wait. Peer authentication failures and unsupported gate endpoints produce errors rather than falling back to local execution. During a network partition, separate islands can acquire the same gate independently. This can allow the same OTP to be accepted in separate islands.

Peer ownership lasts for an authenticated streaming connection with a renewable lease. Requesters renew the lease every second, including while queued. After 3 seconds without a renewal, the peer releases the lock or queue position even if its response writer is blocked. An expired lease cannot be revived. Peers also send a heartbeat every second. A failed renewal, closed connection, or 3 seconds without a heartbeat cancels the protected pipeline. Closing the stream releases the remote gate, including when its requesting instance exits. Gate connections use the management cluster's configured TLS policy and connection timeout. When an acquisition deadline is configured, the connection timeout is also capped at that duration divided by 4 times the number of remote peers. This reserves acquisition time for other participants when a peer does not respond. Ownership acquisition retains a common node order to prevent distributed deadlocks. Concurrent cluster reads and health probes do not change this lock ordering.

Gating coordinates execution; it does not make replicated backend state immediately consistent. For OTP, read state that includes the previous owner's successful write before validating the next request.