phasync
Swerve / publish

Method

Swerve::publish

Send a message to every subscriber of $topic, in every worker process of this swerve, this one included.

Description#

public static Swerve::publish(
    string $topic,
    mixed $message
): void

Returns once the message is on its way, not once delivered, and never suspends the caller, even the first time this worker publishes to $topic: safe to call from a finally, including one that runs after the coroutine was cancelled (a WebSocket handler's goodbye). Delivery is at most once, to the subscriptions that exist when the message reaches their worker: there is no history, and a worker starting later (after a reload, a recycle, a crash) sees nothing sent before. The messages of one publishing worker arrive in the order it published them, with no order between workers. A worker that does not read its inbox loses the messages sent to it after 0.1 s. Swerve embedded without its master process delivers in this process only.

Every message travels as JSON: encoded once here, decoded once in each worker, and every subscriber gets the value published, shared: a string stays a string ('{}' too), a list an array, and an object (an array with keys) a read-only SealedObject: $message->end.

Parameters#

$topic string
1 to 255 bytes
$message mixed
Anything json_encode() takes except null; at most 128 KiB encoded

Errors / Exceptions#

ExceptionWhen
InvalidArgumentExceptionFor a topic or message outside those sizes, a topic starting with "\0", or null (which a heartbeat subscription yields for "nothing came")
LogicExceptionDirectly in swerve.php, which the worker serves after: a coroutine started there waits instead
JsonExceptionFor a value JSON can't express

Examples#

Example 1Every subscriber gets every message
use Swerve\Swerve;

phasync::run(function () {
    // Two subscribers, as two requests in a worker would have
    foreach (['ann', 'bob'] as $name) {
        $subscription = Swerve::subscribe('game');     // subscribed now, not at the foreach
        phasync::go(function () use ($subscription, $name) {
            foreach ($subscription as $message) {
                echo "$name got ", json_encode($message), "\n";
                if ('end' === $message) {
                    break;
                }
            }
        });
    }

    Swerve::publish('game', ['type' => 'score', 'player' => 7, 'points' => 10]);
    Swerve::publish('game', [7, 'kill']);
    Swerve::publish('game', 'end');
});
Output
ann got {"type":"score","player":7,"points":10}
bob got {"type":"score","player":7,"points":10}
ann got [7,"kill"]
bob got [7,"kill"]
ann got "end"
bob got "end"
Example 2
Swerve::publish('game', ['kill', $playerId]);
Swerve::publish('game', ['type' => 'score', 'player' => $playerId, 'points' => 10]);

See also#