Under development — the help is being filled in plugin by plugin.
Help/Plugin reference/callbacklistener
Plugin reference

callbacklistener

A general callback listener with subscription / job / route lifecycle.

53 functionsnamespace callbacklistenersource plugins/callback_listener/CallbackListenerPlugin.c

Written from a line-by-line source review; every example output is from a real run.

Introduction

The callbacklistener plugin is the master of the callback_* family: a generic, network-protocol-agnostic async listener that dispatches arbitrary blob-based requests to a script-level callback on a background thread. The plugin supports the full asyncmeta vocabulary (Capabilities = 4095 = ProfileRouteService — every bit), and introduces the three-layer model: subscription (the callback registration), route (= subscription, the asyncmeta-vocabulary name), and job (a concrete request). The callback signature is `callback i32 NAME(ref blob $Request)`; the callback may modify the request blob in place, and that becomes the response.

The three-layer model

Subscription: the channel created by `Open(callback, timeoutMs)` — a script-callback registration with a timeout. Multiple subscriptions may live simultaneously, each with a different callback. Route: same as the subscription, just the asyncmeta-vocabulary name. The `RouteState`, `RouteCallback`, `RouteTimeout`, `RouteKnown`, `RouteMeta`, `RouteInfo`, `RoutePending`, `RouteQueued`, `RouteRunning`, `RouteDrained`, `WaitRouteDrained`, `RouteCloseAccepted`, `RouteClosedQueued`, `RouteCloseInfo`, `RouteClose` all operate on the subscription under another name — pick the code style you prefer (Subscription* is the direct form, Route* is the asyncmeta-compatible form). Job: a request scheduled by `Send`/`SendTo`/`SendBorrowedText`/`SendBorrowedTextTo`. Every job belongs to exactly one subscription (queryable via `JobSubscription` / `JobRoute`).

Send vs SendTo

`Send(request)` and `SendBorrowedText(text)` only work when EXACTLY ONE subscription is open — otherwise they fail with “callbacklistener.Send requires exactly one open subscription”. With multiple subscriptions, `SendTo(subscriptionId, request)` and `SendBorrowedTextTo(subscriptionId, text)` are the explicit forms. `Send` is a legacy convenience for the single-subscription case.

Send vs SendBorrowedText

`Send` takes a blob (the request's binary data); `SendBorrowedText` takes a string passed to the callback as a borrowed blob — fewer memory copies than building an explicit blob. The two forms are semantically equivalent: the callback always gets a ref blob parameter, and the modified bytes become the response.

Two wait styles

The plugin offers two wait functions. `WaitComplete(jobId, timeoutMs)` waits for one SPECIFIC job to finish, returning 1/0 (did it complete in time). `WaitDrained(subscriptionId, timeoutMs)` and `WaitRouteDrained(subscriptionId, timeoutMs)` wait for a SUBSCRIPTION to fully drain (every job belonging to it to finish). Important: in the parameter table for WaitComplete the argument is registered as `subscriptionId`, but the source treats it as a `jobId` — the parameter-table name only conveys the count/type, not semantics; semantics come from the source.

Taking job results

A completed job's response blob is collected by `Take(jobId)` or `TakeBlob(jobId)` — these are synonyms. `Take/TakeBlob` destroys the job; the jobId is invalid afterward. `JobHasBlobResult(jobId)` and `JobBlobResultSize(jobId)` allow defensive pre-checks: if Status is non-zero or the job is not finished, Take raises a runtime error.

Two-step shutdown

Clean shutdown of a single subscription: (1) `RouteClose(subscriptionId)` or `CloseSubscription(subscriptionId)` — same handler; the return value is the count of queued jobs canceled by the close (0 = clean close with nothing pending). (2) `WaitRouteDrained(subscriptionId, timeoutMs)` — wait for the in-flight callbacks to finish. (3) Plugin-wide shutdown: `Close()` — closes every still-open subscription and stops the background thread. Observation: `RouteCloseAccepted` is a LATCH — once it's 1 it does not reset when reopening.

Loading the plugin

plugin "../plugins/print/PrintPlugin";
plugin "../plugins/async_meta/AsyncMetaPlugin";
plugin "../plugins/callback_listener/CallbackListenerPlugin";

A typical flow — one subscription, Send + WaitComplete + Take

callback i32 Echo(ref blob $Request)
{
// the callback may modify the request bytes in place;
// those become the response blob bytes
return(1);
}
i32 main()
{
i64 $sub;
i64 $jobId;
blob $req[3];
blob $resp[8];
$req[0] = 65;
$req[1] = 66;
$req[2] = 67;
$sub = callbacklistener.Open("Echo", 5000);
$jobId = callbacklistener.Send($req);
callbacklistener.WaitComplete($jobId, 5000);
$resp = callbacklistener.TakeBlob($jobId);
callbacklistener.Close();
return(0);
}

What to know about every function (the basics)

  • Capabilities is always ProfileRouteService = 4095 = every bit (full asyncmeta profile).

  • Subscription/Route equivalence: same thing, two names. `JobSubscription == JobRoute`, `SubscriptionPending == RoutePending`, etc.

  • Send / SendBorrowedText only work with ONE open subscription; with several subs, SendTo / SendBorrowedTextTo is required.

  • WaitComplete waits on a JOB (jobId), NOT a subscription — the parameter name in the registration is misleading.

  • WaitDrained and WaitRouteDrained wait on a SUBSCRIPTION (subscriptionId): completion of every job belonging to it.

  • Take and TakeBlob are synonyms with identical behavior, and both destroy the job.

  • RouteClose and CloseSubscription are the same handler — two names, same behavior. The return is the count of canceled queued jobs.

  • Cancel takes a jobId and only removes jobs that have not yet started.

  • OpenCount is the plugin-wide, global open-subscription count.

  • An error (stopping the script) is caused by a wrong argument count or type, an out-of-range timeoutMs, an invalid jobId/subscriptionId, an already-closed subscription, and touching an already-closed plugin.

How to read the signatures

callback is the script-level callback name (`callback i32 NAME(ref blob $X)`). timeoutMs is the callback's run-time limit in ms; -1 = infinite. subscriptionId is the positive id given by Open. jobId is the positive id given by Send*. metaKey is one of the asyncmeta.RouteMeta* or JobMeta* values. The type after the -> arrow is the return type.

Lifecycle

Plugin capability query, opening a subscription, and plugin-wide shutdown.

callbacklistener.Capabilities

callbacklistener.Capabilities() -> int

Returns the plugin's capability bitmask matching the asyncmeta constants.

Parameters

This function takes no arguments.

Return value

asyncmeta.ProfileRouteService (=4095): every asyncmeta bit (the entire vocabulary supported).

Example
printf("%d\n", callbacklistener.Capabilities());
printf("%d\n", (callbacklistener.Capabilities() ==
asyncmeta.ProfileRouteService()));
Output after running
4095
1
When to use

For checking against another asyncmeta-compatible backend. callback_listener supports the FULL vocabulary — the Supports* helpers return 1 for everything.

callbacklistener.Open

callbacklistener.Open(callback, timeoutMs) -> int

Opens a subscription (callback registration) and returns the subscriptionId.

Parameters
Parameter Type Description
callback string Script-level callback name to call. Signature: `callback i32 NAME(ref blob $X)`.
timeoutMs int Callback run-time limit in ms. -1 = infinite; otherwise 0..2147483647.
Return value

The subscriptionId (positive i64) to pass to other operations. Bad arguments or a closed plugin raises a runtime error.

Example
callback i32 Echo(ref blob $X) { return(1); }
i64 $sub;
$sub = callbacklistener.Open("Echo", 5000);
printf("%d\n", ($sub > 0));
Output after running
1
When to use

Create an async callback channel. You can open multiple subscriptions — one with an echo callback, another with a transform callback; SendTo targets the right channel.

callbacklistener.OpenCount

callbacklistener.OpenCount() -> int

Returns the count of currently open subscriptions (plugin-wide, global view).

Parameters

This function takes no arguments.

Return value

The number of open subscriptions (0 if none).

Example
printf("%d\n", callbacklistener.OpenCount());
i64 $sub;
$sub = callbacklistener.Open("Echo", 5000);
printf("%d\n", callbacklistener.OpenCount());
Output after running
0
1
When to use

For resource control and diagnostics. If it does not return to 0 after Close calls, that signals a resource leak.

callbacklistener.Close

callbacklistener.Close() -> int

Plugin-wide shutdown: close every subscription and stop the background thread.

Parameters

This function takes no arguments.

Return value

0 (always).

Example
callbacklistener.Close();
printf("Close done\n");
Output after running
Close done
When to use

At the script's end, for clean resource shutdown. A currently running callback may finish, but no new job will start.

Job submission

Schedule async jobs to an open subscription. All four verbs return immediately with the jobId.

callbacklistener.Send

callbacklistener.Send(request) -> int

Schedules an async job on the single open subscription (legacy: fails with multiple subs).

Parameters
Parameter Type Description
request blob The input blob passed to the callback. The callback may modify it in place; the modification is visible in the response blob.
Return value

The jobId (positive i64). Multiple subs or no open sub raises a runtime error.

Example
i64 $sub;
i64 $jobId;
blob $req[3];
$req[0] = 65;
$req[1] = 66;
$req[2] = 67;
$sub = callbacklistener.Open("Echo", 5000);
$jobId = callbacklistener.Send($req);
printf("%d\n", ($jobId > 0));
Output after running
1
When to use

Simple, single-subscription scenarios: more convenient than SendTo since no explicit subscriptionId is needed. Use SendTo with multiple subs.

callbacklistener.SendTo

callbacklistener.SendTo(subscriptionId, request) -> int

Schedules an async job to a SPECIFIC subscription.

Parameters
Parameter Type Description
subscriptionId int The target subscription id.
request blob The input blob passed to the callback.
Return value

The jobId (positive i64). An invalid subscriptionId or closed subscription raises a runtime error.

Example
i64 $sub;
i64 $jobId;
blob $req[3];
$req[0] = 65;
$req[1] = 66;
$req[2] = 67;
$sub = callbacklistener.Open("Echo", 5000);
$jobId = callbacklistener.SendTo($sub, $req);
printf("%d\n", ($jobId > 0));
Output after running
1
When to use

With multiple subscriptions (different callbacks): SendTo targets the right channel. You can build a router-style pattern — different processing callback per subscription, code dispatches to the right one.

callbacklistener.SendBorrowedText

callbacklistener.SendBorrowedText(text) -> int

Schedules an async job with text input to the single open subscription.

Parameters
Parameter Type Description
text string The text passed to the callback (as a borrowed blob).
Return value

The jobId (positive i64). Multiple subs or no open sub raises a runtime error.

Example
i64 $sub;
i64 $jobId;
$sub = callbacklistener.Open("Echo", 5000);
$jobId = callbacklistener.SendBorrowedText("hi");
printf("%d\n", ($jobId > 0));
Output after running
1
When to use

For text inputs (commands, JSON strings): fewer memory copies than explicit blob construction.

callbacklistener.SendBorrowedTextTo

callbacklistener.SendBorrowedTextTo(subscriptionId, text) ->
int

Schedules an async job with text input to a SPECIFIC subscription.

Parameters
Parameter Type Description
subscriptionId int The target subscription id.
text string The text passed to the callback.
Return value

The jobId (positive i64).

Example
i64 $sub;
i64 $jobId;
$sub = callbacklistener.Open("Echo", 5000);
$jobId = callbacklistener.SendBorrowedTextTo($sub, "world");
printf("%d\n", ($jobId > 0));
Output after running
1
When to use

For multiple subscriptions + text input. The borrowed-text minimizes memory allocation.

Wait and take

Wait for the job to finish, take the response blob, and cancel queued jobs.

callbacklistener.WaitComplete

callbacklistener.WaitComplete(jobId, timeoutMs) -> int

Blocks until the job completes (jobId!), but does NOT destroy the job — status and result remain queryable.

Parameters
Parameter Type Description
jobId int The JOB id (NOT subscriptionId — the registration parameter table is misleading).
timeoutMs int Maximum wait in milliseconds; -1 = infinite.
Return value

1 if the job completed; 0 if the timeout expired and the job is still running.

Example
i64 $sub;
i64 $jobId;
blob $req[3];
$req[0] = 65;
$req[1] = 66;
$req[2] = 67;
$sub = callbacklistener.Open("Echo", 5000);
$jobId = callbacklistener.Send($req);
printf("%d\n", callbacklistener.WaitComplete($jobId, 5000));
Output after running
1
When to use

First step of the two-step pattern: wait for completion, then verify success via Status / JobMeta, finally Take/TakeBlob the response. IMPORTANT: the parameter name in the registration is subscriptionId, but the source treats it as `JobId` — pass the JOB id.

callbacklistener.Take

callbacklistener.Take(jobId) -> blob

Returns the response blob of an already-completed job and destroys the job. Synonym for TakeBlob.

Parameters
Parameter Type Description
jobId int The jobId.
Return value

The response blob (the callback-modified request bytes). If the job has not completed, a runtime error.

Example
i64 $sub;
i64 $jobId;
blob $req[3];
blob $resp[8];
$req[0] = 65;
$req[1] = 66;
$req[2] = 67;
$sub = callbacklistener.Open("Echo", 5000);
$jobId = callbacklistener.Send($req);
callbacklistener.WaitComplete($jobId, 5000);
$resp = callbacklistener.Take($jobId);
printf("%d\n", $resp.Length);
Output after running
3
When to use

Stylistic choice when the result is conceptually “taken” rather than emphasizing the blob type. Behavior is identical to TakeBlob — same handler.

callbacklistener.TakeBlob

callbacklistener.TakeBlob(jobId) -> blob

Returns the response blob of an already-completed job and destroys the job. Synonym for Take.

Parameters
Parameter Type Description
jobId int The jobId.
Return value

The response blob.

Example
i64 $sub;
i64 $jobId;
blob $req[3];
blob $resp[8];
$req[0] = 65;
$req[1] = 66;
$req[2] = 67;
$sub = callbacklistener.Open("Echo", 5000);
$jobId = callbacklistener.Send($req);
callbacklistener.WaitComplete($jobId, 5000);
$resp = callbacklistener.TakeBlob($jobId);
printf("%d %d %d\n", $resp[0], $resp[1], $resp[2]);
Output after running
65 66 67
When to use

Emphasizes the taken result is a blob. Identical semantics to Take — the choice is stylistic.

callbacklistener.Cancel

callbacklistener.Cancel(jobId) -> int

Attempts to remove a queued (not yet started) job.

Parameters
Parameter Type Description
jobId int The jobId.
Return value

1 if the job was removed from the queue; 0 if it is already running or has completed.

Example
i64 $sub;
i64 $jobId;
blob $req[3];
$sub = callbacklistener.Open("Echo", 5000);
$jobId = callbacklistener.Send($req);
printf("%d\n", callbacklistener.Cancel($jobId));
Output after running
0
When to use

Only queued jobs can be canceled — running ones must self-terminate via callback timeoutMs. The 0 return is normal if the job has already started.

Subscription-level state

Current state of a subscription: open/closed, callback name, timeout, meta fields. The Subscription*/Route* names are synonyms — they query the same subscription.

callbacklistener.SubscriptionState

callbacklistener.SubscriptionState(subscriptionId) -> int

Returns the subscription's state (open/closed).

Parameters
Parameter Type Description
subscriptionId int The subscription id.
Return value

1 (open, asyncmeta.RouteStateOpen), 0 (closed, RouteStateClosed).

Example
i64 $sub;
$sub = callbacklistener.Open("Echo", 5000);
printf("%d\n", callbacklistener.SubscriptionState($sub));
Output after running
1
When to use

For programmatic state checking. Synonym of RouteState — same return under a different name.

callbacklistener.RouteState

callbacklistener.RouteState(subscriptionId) -> int

Synonym of SubscriptionState: returns the subscription state under the asyncmeta vocabulary.

Parameters
Parameter Type Description
subscriptionId int The subscription id.
Return value

asyncmeta.RouteStateOpen (=1) or RouteStateClosed (=0).

Example
i64 $sub;
$sub = callbacklistener.Open("Echo", 5000);
printf("%d\n", callbacklistener.RouteState($sub));
Output after running
1
When to use

If your code shares other asyncmeta-compatible backends, use this for consistency.

callbacklistener.SubscriptionStateText

callbacklistener.SubscriptionStateText(subscriptionId) ->
string

Human-readable text of the state.

Parameters
Parameter Type Description
subscriptionId int The subscription id.
Return value

“open” or “closed”.

Example
i64 $sub;
$sub = callbacklistener.Open("Echo", 5000);
printf("%s\n", callbacklistener.SubscriptionStateText($sub));
Output after running
open
When to use

For logging or UI display.

callbacklistener.RouteStateText

callbacklistener.RouteStateText(subscriptionId) -> string

Synonym of SubscriptionStateText.

Parameters
Parameter Type Description
subscriptionId int The subscription id.
Return value

“open” or “closed”.

Example
i64 $sub;
$sub = callbacklistener.Open("Echo", 5000);
printf("%s\n", callbacklistener.RouteStateText($sub));
Output after running
open
When to use

For logging, under the asyncmeta vocabulary.

callbacklistener.SubscriptionCallback

callbacklistener.SubscriptionCallback(subscriptionId) ->
string

Returns the callback name passed at Open.

Parameters
Parameter Type Description
subscriptionId int The subscription id.
Return value

The callback name as text.

Example
i64 $sub;
$sub = callbacklistener.Open("Echo", 5000);
printf("%s\n", callbacklistener.SubscriptionCallback($sub));
Output after running
Echo
When to use

For reflectivity and diagnostics: confirms which callback is bound to the subscription.

callbacklistener.RouteCallback

callbacklistener.RouteCallback(subscriptionId) -> string

Synonym of SubscriptionCallback.

Parameters
Parameter Type Description
subscriptionId int The subscription id.
Return value

The callback name as text.

Example
i64 $sub;
$sub = callbacklistener.Open("Echo", 5000);
printf("%s\n", callbacklistener.RouteCallback($sub));
Output after running
Echo
When to use

For logging, under the asyncmeta vocabulary.

callbacklistener.SubscriptionTimeout

callbacklistener.SubscriptionTimeout(subscriptionId) -> int

Returns the timeout value passed at Open, in ms.

Parameters
Parameter Type Description
subscriptionId int The subscription id.
Return value

The timeoutMs value; -1 for infinite.

Example
i64 $sub;
$sub = callbacklistener.Open("Echo", 5000);
printf("%d\n", callbacklistener.SubscriptionTimeout($sub));
Output after running
5000
When to use

Reflective query of subscription configuration.

callbacklistener.RouteTimeout

callbacklistener.RouteTimeout(subscriptionId) -> int

Synonym of SubscriptionTimeout.

Parameters
Parameter Type Description
subscriptionId int The subscription id.
Return value

The timeoutMs value.

Example
i64 $sub;
$sub = callbacklistener.Open("Echo", 5000);
printf("%d\n", callbacklistener.RouteTimeout($sub));
Output after running
5000
When to use

For logging, under the asyncmeta vocabulary.

callbacklistener.RouteKnown

callbacklistener.RouteKnown(subscriptionId) -> int

Tells whether the subscriptionId is known (still open in the plugin).

Parameters
Parameter Type Description
subscriptionId int The subscription id.
Return value

1 if known (open); 0 if not.

Example
i64 $sub;
$sub = callbacklistener.Open("Echo", 5000);
printf("%d\n", callbacklistener.RouteKnown($sub));
Output after running
1
When to use

Defensive check. If 0, the subscription is already closed or unknown.

callbacklistener.RouteMeta

callbacklistener.RouteMeta(routeId, metaKey) -> int

Returns a specific meta field of the subscription by asyncmeta.RouteMeta* keys.

Parameters
Parameter Type Description
routeId int The subscription id (the parameter name follows the asyncmeta vocabulary).
metaKey int An asyncmeta.RouteMeta* value (State, Timeout, Pending, Queued, Running, Drained, Known, CloseAccepted, ClosedQueued).
Return value

The value for the field.

Example
i64 $sub;
$sub = callbacklistener.Open("Echo", 5000);
printf("%d\n", callbacklistener.RouteMeta($sub,
asyncmeta.RouteMetaState()));
printf("%d\n", callbacklistener.RouteMeta($sub,
asyncmeta.RouteMetaDrained()));
Output after running
1
1
When to use

Uniform asyncmeta query of subscription state. For portable code across backends, this is the portable form.

callbacklistener.SubscriptionInfo

callbacklistener.SubscriptionInfo(subscriptionId) -> string

Returns the subscription state as a key=value diagnostic string.

Parameters
Parameter Type Description
subscriptionId int The subscription id.
Return value

A space-separated key=value list.

Example
i64 $sub;
$sub = callbacklistener.Open("Echo", 5000);
printf("%d\n", (str.Len(callbacklistener.SubscriptionInfo($sub)) >
0));
Output after running
1
When to use

Detailed diagnostics in a single call.

callbacklistener.RouteInfo

callbacklistener.RouteInfo(subscriptionId) -> string

Synonym of SubscriptionInfo.

Parameters
Parameter Type Description
subscriptionId int The subscription id.
Return value

A key=value diagnostic string.

Example
i64 $sub;
$sub = callbacklistener.Open("Echo", 5000);
printf("%d\n", (str.Len(callbacklistener.RouteInfo($sub)) >
0));
Output after running
1
When to use

Under the asyncmeta vocabulary.

Subscription-level traffic

Per-subscription job traffic metrics: pending, queued, running, drained. The Subscription*/Route* names are synonyms here as well.

callbacklistener.SubscriptionPending

callbacklistener.SubscriptionPending(subscriptionId) -> int

Returns the number of pending (not yet started) jobs on the subscription.

Parameters
Parameter Type Description
subscriptionId int The subscription id.
Return value

The number of pending jobs.

Example
i64 $sub;
$sub = callbacklistener.Open("Echo", 5000);
printf("%d\n", callbacklistener.SubscriptionPending($sub));
Output after running
0
When to use

Early signal of congestion.

callbacklistener.RoutePending

callbacklistener.RoutePending(subscriptionId) -> int

Synonym of SubscriptionPending.

Parameters
Parameter Type Description
subscriptionId int The subscription id.
Return value

The number of pending jobs.

Example
i64 $sub;
$sub = callbacklistener.Open("Echo", 5000);
printf("%d\n", callbacklistener.RoutePending($sub));
Output after running
0
When to use

For logging, under the asyncmeta vocabulary.

callbacklistener.SubscriptionQueued

callbacklistener.SubscriptionQueued(subscriptionId) -> int

Returns the number of queued jobs on the subscription.

Parameters
Parameter Type Description
subscriptionId int The subscription id.
Return value

The number of queued jobs.

Example
i64 $sub;
$sub = callbacklistener.Open("Echo", 5000);
printf("%d\n", callbacklistener.SubscriptionQueued($sub));
Output after running
0
When to use

For monitoring the internal queue length.

callbacklistener.RouteQueued

callbacklistener.RouteQueued(subscriptionId) -> int

Synonym of SubscriptionQueued.

Parameters
Parameter Type Description
subscriptionId int The subscription id.
Return value

The number of queued jobs.

Example
i64 $sub;
$sub = callbacklistener.Open("Echo", 5000);
printf("%d\n", callbacklistener.RouteQueued($sub));
Output after running
0
When to use

For logging, under the asyncmeta vocabulary.

callbacklistener.SubscriptionRunning

callbacklistener.SubscriptionRunning(subscriptionId) -> int

Returns the number of currently running jobs on the subscription.

Parameters
Parameter Type Description
subscriptionId int The subscription id.
Return value

The number of running jobs.

Example
i64 $sub;
$sub = callbacklistener.Open("Echo", 5000);
printf("%d\n", callbacklistener.SubscriptionRunning($sub));
Output after running
0
When to use

For monitoring parallelism.

callbacklistener.RouteRunning

callbacklistener.RouteRunning(subscriptionId) -> int

Synonym of SubscriptionRunning.

Parameters
Parameter Type Description
subscriptionId int The subscription id.
Return value

The number of running jobs.

Example
i64 $sub;
$sub = callbacklistener.Open("Echo", 5000);
printf("%d\n", callbacklistener.RouteRunning($sub));
Output after running
0
When to use

For logging, under the asyncmeta vocabulary.

callbacklistener.SubscriptionDrained

callbacklistener.SubscriptionDrained(subscriptionId) -> int

Tells whether the subscription is drained (pending = queued = running = 0).

Parameters
Parameter Type Description
subscriptionId int The subscription id.
Return value

1 if drained; 0 if something is in progress.

Example
i64 $sub;
$sub = callbacklistener.Open("Echo", 5000);
printf("%d\n", callbacklistener.SubscriptionDrained($sub));
Output after running
1
When to use

Before clean shutdown: ensure Drained=1 before calling Close.

callbacklistener.RouteDrained

callbacklistener.RouteDrained(subscriptionId) -> int

Synonym of SubscriptionDrained.

Parameters
Parameter Type Description
subscriptionId int The subscription id.
Return value

1 if drained; 0 if not.

Example
i64 $sub;
$sub = callbacklistener.Open("Echo", 5000);
printf("%d\n", callbacklistener.RouteDrained($sub));
Output after running
1
When to use

For logging, under the asyncmeta vocabulary.

callbacklistener.WaitDrained

callbacklistener.WaitDrained(subscriptionId, timeoutMs) -> int

Blocks until the subscription is drained, or timeoutMs expires.

Parameters
Parameter Type Description
subscriptionId int The subscription id.
timeoutMs int Maximum wait in ms; -1 = infinite.
Return value

1 if drain occurred before timeoutMs expired; 0 if it expired.

Example
i64 $sub;
$sub = callbacklistener.Open("Echo", 5000);
printf("%d\n", callbacklistener.WaitDrained($sub, 50));
Output after running
1
When to use

In the two-step shutdown pattern: AFTER RouteClose, wait for full drain so every in-flight job can finish.

callbacklistener.WaitRouteDrained

callbacklistener.WaitRouteDrained(subscriptionId, timeoutMs) ->
int

Synonym of WaitDrained.

Parameters
Parameter Type Description
subscriptionId int The subscription id.
timeoutMs int Max wait in ms.
Return value

1 if drain occurred; 0 if expired.

Example
i64 $sub;
$sub = callbacklistener.Open("Echo", 5000);
printf("%d\n", callbacklistener.WaitRouteDrained($sub, 50));
Output after running
1
When to use

For logging, under the asyncmeta vocabulary.

Job-level state and metadata

Current state (phase, status, error) and metadata (timeout, owning subscription, blob result info) of a specific job. Take preconditions are checked here.

callbacklistener.State

callbacklistener.State(jobId) -> int

Returns a unified state code for the job (a shorthand of phase or completion-with-error).

Parameters
Parameter Type Description
jobId int The jobId.
Return value

A state code (a combination of Phase + Status).

Example
i64 $sub;
i64 $jobId;
blob $req[3];
$sub = callbacklistener.Open("Echo", 5000);
$jobId = callbacklistener.Send($req);
callbacklistener.WaitComplete($jobId, 5000);
printf("%d\n", callbacklistener.State($jobId));
Output after running
2
When to use

Makes the job state visible in one query; a simplified summary of Phase + Status.

callbacklistener.Phase

callbacklistener.Phase(jobId) -> int

Returns the job phase from the asyncmeta.Phase* constants.

Parameters
Parameter Type Description
jobId int The jobId.
Return value

asyncmeta.PhaseQueued (=0), PhaseRunning (=1), or PhaseCompleted (=2).

Example
i64 $sub;
i64 $jobId;
blob $req[3];
$sub = callbacklistener.Open("Echo", 5000);
$jobId = callbacklistener.Send($req);
callbacklistener.WaitComplete($jobId, 5000);
printf("%d\n", callbacklistener.Phase($jobId));
Output after running
2
When to use

For programmatic phase checks: compare with the asyncmeta constants.

callbacklistener.PhaseText

callbacklistener.PhaseText(jobId) -> string

Returns the phase as text.

Parameters
Parameter Type Description
jobId int The jobId.
Return value

“queued”, “running”, or “completed”.

Example
i64 $sub;
i64 $jobId;
blob $req[3];
$sub = callbacklistener.Open("Echo", 5000);
$jobId = callbacklistener.Send($req);
callbacklistener.WaitComplete($jobId, 5000);
printf("%s\n", callbacklistener.PhaseText($jobId));
Output after running
completed
When to use

For logging or UI display.

callbacklistener.Status

callbacklistener.Status(jobId) -> int

Returns the job's status: 0 = success, non-zero = error.

Parameters
Parameter Type Description
jobId int The jobId.
Return value

0 if the job ran successfully; non-zero is the error code.

Example
i64 $sub;
i64 $jobId;
blob $req[3];
$sub = callbacklistener.Open("Echo", 5000);
$jobId = callbacklistener.Send($req);
callbacklistener.WaitComplete($jobId, 5000);
printf("%d\n", callbacklistener.Status($jobId));
Output after running
0
When to use

After WaitComplete, check this first: if 0, go ahead with Take; if non-0, ErrorText is more precise.

callbacklistener.StatusText

callbacklistener.StatusText(jobId) -> string

Textual counterpart of the status.

Parameters
Parameter Type Description
jobId int The jobId.
Return value

“success” on a successful job, other text depending on the error type.

Example
i64 $sub;
i64 $jobId;
blob $req[3];
$sub = callbacklistener.Open("Echo", 5000);
$jobId = callbacklistener.Send($req);
callbacklistener.WaitComplete($jobId, 5000);
printf("%s\n", callbacklistener.StatusText($jobId));
Output after running
success
When to use

For logging or user feedback.

callbacklistener.ErrorText

callbacklistener.ErrorText(jobId) -> string

Returns the job error message (empty on success).

Parameters
Parameter Type Description
jobId int The jobId.
Return value

The error message text; empty string on a successful job.

Example
i64 $sub;
i64 $jobId;
blob $req[3];
$sub = callbacklistener.Open("Echo", 5000);
$jobId = callbacklistener.Send($req);
callbacklistener.WaitComplete($jobId, 5000);
printf("%d\n", str.Len(callbacklistener.ErrorText($jobId)));
Output after running
0
When to use

If Status is non-0, this reveals the cause of the error.

callbacklistener.JobInfo

callbacklistener.JobInfo(jobId) -> string

Returns the job state as a key=value diagnostic string.

Parameters
Parameter Type Description
jobId int The jobId.
Return value

A space-separated key=value list.

Example
i64 $sub;
i64 $jobId;
blob $req[3];
$sub = callbacklistener.Open("Echo", 5000);
$jobId = callbacklistener.Send($req);
callbacklistener.WaitComplete($jobId, 5000);
printf("%d\n", (str.Len(callbacklistener.JobInfo($jobId)) >
0));
Output after running
1
When to use

Detailed job diagnostics in a single call.

callbacklistener.JobSubscription

callbacklistener.JobSubscription(jobId) -> int

Returns the id of the subscription the job belongs to.

Parameters
Parameter Type Description
jobId int The jobId.
Return value

The subscriptionId.

Example
i64 $sub;
i64 $jobId;
blob $req[3];
$sub = callbacklistener.Open("Echo", 5000);
$jobId = callbacklistener.Send($req);
printf("%d\n", (callbacklistener.JobSubscription($jobId) ==
$sub));
Output after running
1
When to use

Reflective query of the job-owner relation.

callbacklistener.JobRoute

callbacklistener.JobRoute(jobId) -> int

Synonym of JobSubscription — returns the owning subscription/route id.

Parameters
Parameter Type Description
jobId int The jobId.
Return value

The subscriptionId (= routeId).

Example
i64 $sub;
i64 $jobId;
blob $req[3];
$sub = callbacklistener.Open("Echo", 5000);
$jobId = callbacklistener.Send($req);
printf("%d\n", (callbacklistener.JobRoute($jobId) == $sub));
Output after running
1
When to use

Under the asyncmeta vocabulary (route = subscription).

callbacklistener.JobTimeout

callbacklistener.JobTimeout(jobId) -> int

Returns the job's configured callback timeout in ms (inherited from the subscription).

Parameters
Parameter Type Description
jobId int The jobId.
Return value

The timeoutMs value.

Example
i64 $sub;
i64 $jobId;
blob $req[3];
$sub = callbacklistener.Open("Echo", 5000);
$jobId = callbacklistener.Send($req);
printf("%d\n", callbacklistener.JobTimeout($jobId));
Output after running
5000
When to use

For logging or configuration checks.

callbacklistener.JobKnown

callbacklistener.JobKnown(jobId) -> int

Tells whether the jobId is known to the plugin.

Parameters
Parameter Type Description
jobId int The jobId.
Return value

1 if known; 0 if not (e.g. already destroyed by Take).

Example
i64 $sub;
i64 $jobId;
blob $req[3];
$sub = callbacklistener.Open("Echo", 5000);
$jobId = callbacklistener.Send($req);
printf("%d\n", callbacklistener.JobKnown($jobId));
Output after running
1
When to use

Defensive check: if 0, the job no longer exists.

callbacklistener.JobMeta

callbacklistener.JobMeta(jobId, metaKey) -> int

Returns a specific meta field of the job by asyncmeta.JobMeta* keys.

Parameters
Parameter Type Description
jobId int The jobId.
metaKey int An asyncmeta.JobMeta* value (Phase=1, Status=2, Route=3, Timeout=4, Known=5, HasBlobResult=6, BlobResultSize=7).
Return value

The value matching the field. JobMetaKnown returns 0 on an unknown jobId.

Example
i64 $sub;
i64 $jobId;
blob $req[3];
$sub = callbacklistener.Open("Echo", 5000);
$jobId = callbacklistener.Send($req);
callbacklistener.WaitComplete($jobId, 5000);
printf("%d\n", callbacklistener.JobMeta($jobId,
asyncmeta.JobMetaPhase()));
Output after running
2
When to use

Uniform asyncmeta query on the job state — for portable code across backends.

callbacklistener.JobHasBlobResult

callbacklistener.JobHasBlobResult(jobId) -> int

Tells whether the job has a blob result (completed and successful).

Parameters
Parameter Type Description
jobId int The jobId.
Return value

1 if yes; 0 if no.

Example
i64 $sub;
i64 $jobId;
blob $req[3];
$sub = callbacklistener.Open("Echo", 5000);
$jobId = callbacklistener.Send($req);
callbacklistener.WaitComplete($jobId, 5000);
printf("%d\n", callbacklistener.JobHasBlobResult($jobId));
Output after running
1
When to use

Take precondition: if 0, Take raises a runtime error.

callbacklistener.JobBlobResultSize

callbacklistener.JobBlobResultSize(jobId) -> int

Returns the response blob size in bytes (only for a completed, successful job).

Parameters
Parameter Type Description
jobId int The jobId.
Return value

The blob size in bytes. If the job did not complete successfully, a runtime error.

Example
i64 $sub;
i64 $jobId;
blob $req[3];
$sub = callbacklistener.Open("Echo", 5000);
$jobId = callbacklistener.Send($req);
callbacklistener.WaitComplete($jobId, 5000);
printf("%d\n", callbacklistener.JobBlobResultSize($jobId));
Output after running
3
When to use

For memory pre-allocation: you know how big a blob to allocate for Take.

Subscription shutdown

Shutdown of a single subscription (independent of the plugin-wide Close). RouteClose and CloseSubscription are synonyms — same handler.

callbacklistener.CloseSubscription

callbacklistener.CloseSubscription(subscriptionId) -> int

Closes the given subscription and cancels its queued jobs.

Parameters
Parameter Type Description
subscriptionId int The subscription id.
Return value

The count of queued jobs canceled by the close (0 = clean close with nothing pending).

Example
i64 $sub;
$sub = callbacklistener.Open("Echo", 5000);
printf("%d\n", callbacklistener.CloseSubscription($sub));
Output after running
0
When to use

For a clean shutdown of a single subscription (without tearing down the whole plugin). The currently running callback may finish; no new job will run.

callbacklistener.RouteClose

callbacklistener.RouteClose(subscriptionId) -> int

Synonym of CloseSubscription — exact same handler.

Parameters
Parameter Type Description
subscriptionId int The subscription id.
Return value

The count of canceled queued jobs.

Example
i64 $sub;
$sub = callbacklistener.Open("Echo", 5000);
printf("%d\n", callbacklistener.RouteClose($sub));
Output after running
0
When to use

Under the asyncmeta vocabulary. Choosing between RouteClose and CloseSubscription is stylistic.

callbacklistener.RouteCloseAccepted

callbacklistener.RouteCloseAccepted(subscriptionId) -> int

Tells whether a close request has been accepted on the subscription.

Parameters
Parameter Type Description
subscriptionId int The subscription id.
Return value

1 if yes; 0 if no RouteClose / CloseSubscription has happened yet.

Example
i64 $sub;
$sub = callbacklistener.Open("Echo", 5000);
callbacklistener.RouteClose($sub);
printf("%d\n", callbacklistener.RouteCloseAccepted($sub));
Output after running
1
When to use

LATCH: once 1, it does not reset on reopen. Value persists for the subscription's entire life.

callbacklistener.RouteClosedQueued

callbacklistener.RouteClosedQueued(subscriptionId) -> int

Returns the count of queued jobs canceled by the most recent RouteClose / CloseSubscription.

Parameters
Parameter Type Description
subscriptionId int The subscription id.
Return value

The count of canceled queued jobs.

Example
i64 $sub;
$sub = callbacklistener.Open("Echo", 5000);
callbacklistener.RouteClose($sub);
printf("%d\n", callbacklistener.RouteClosedQueued($sub));
Output after running
0
When to use

For diagnostics and logging: how many jobs were lost during shutdown.

callbacklistener.RouteCloseInfo

callbacklistener.RouteCloseInfo(subscriptionId) -> string

Returns the subscription shutdown process as a key=value diagnostic string.

Parameters
Parameter Type Description
subscriptionId int The subscription id.
Return value

A space-separated key=value list.

Example
i64 $sub;
$sub = callbacklistener.Open("Echo", 5000);
printf("%d\n", (str.Len(callbacklistener.RouteCloseInfo($sub)) >
0));
Output after running
1
When to use

Detailed shutdown diagnostics in a single call.

Practical notes

What the callbacklistener plugin is good for

  • Generic async callback channel without network protocol: the code controls when and what request to send to the callback.

  • Parallel management of multiple channels: each subscription serves its own callback with separate state/traffic metrics.

  • asyncmeta compatibility with the full vocabulary: Phase, Status, JobMeta, RouteMeta, WaitDrained, RouteClose — every bit supported (Capabilities = 4095).

  • The subscription/route synonym pair allows stylistic choice in code — Subscription* names are direct, Route* names follow the asyncmeta convention.

Send vs SendTo usage

If your code opens only one subscription, `Send(request)` is simpler — no explicit subscriptionId needed. But if you ever open a second subscription (or some library calls Open without your knowledge), Send will fail. For defensive programming `SendTo(subscriptionId, request)` is always preferred — explicit, portable, and clearer in code about which channel you're sending to.

WaitComplete — a crucial detail

The `WaitComplete(jobId, timeoutMs)` parameter table in the registration is `gSubscriptionWaitParams` — which may suggest it takes a subscriptionId. The source code is unambiguous: `JobId = Args[0]` — it takes the JOB id. The parameter table here only encodes the argument TYPE and COUNT (one int, one int), not semantics. This is an important detail: if you accidentally pass a subscriptionId, the error message will be “job not found”. Always pass a jobId to WaitComplete.

RouteClose / CloseSubscription return value

The two calls (`RouteClose` and `CloseSubscription`) are the SAME handler — two names, identical behavior. The return value is NOT a 1/0 success flag, but the COUNT of queued jobs canceled by the close. Typically 0 (clean close with no pending jobs). A positive value: that many queued jobs were lost. A subscription closed once cannot be reopened — a second call raises a runtime error with “subscription is not open”.

Two-step shutdown pattern

(1) `RouteClose(subscriptionId)` (or `CloseSubscription`): signals the subscription is to be closed. Queued jobs are canceled; the running callback may finish. (2) `WaitRouteDrained(subscriptionId, timeoutMs)`: waits until every in-flight job is done. (3) `Close()` (plugin-wide): full plugin shutdown, including every subscription. The `RouteCloseAccepted` LATCH flips to 1 on the first RouteClose and stays — useful for diagnostics.

Error handling

An invalid jobId, subscriptionId, wrong argument count or type, out-of-range timeoutMs, touching an already-closed subscription, and touching an already-closed plugin are reported by the runtime as a runtime error, and the script stops. A WaitComplete wait-timeout is `DOMIN_STATUS_TIMEOUT`; a Close-style shutdown is `DOMIN_STATUS_SHUTDOWN`. Take/TakeBlob only accept completed (Phase=Completed) jobs.

The callbacktcp TCP listener plugin

Loopback TCP server + client in one, optional TLS, sync/async request patterns, full asyncmeta vocabulary — complete function reference