MMOframework
Why AI Playground Libraries Documentation Search Agency
FR EN
Index

JobEventStream

MMO\core\jobs · 1 symbol · generated 27 Oct 2026

class

JobEventStream

JobEventStream.php:26

A job's events as Server-Sent Events (text/event-stream), read as they come: what JobController's events.sse answers, through a StreamResponse (which sends each chunk as it is read).

class MMO\core\jobs\JobEventStream implements Psr\Http\Message\StreamInterface
Namespace
MMO\core\jobs
Implements
StreamInterface
Each event of the job ([`JobStore::events`](https://mmoframework.fr/en/documentation/mmo.core/php/jobs/JobStore.md#jobstore-events)) becomes one frame: `id:` its position, `event:` its type, `data:` its json. A browser's `EventSource` sends the last id back when it reconnects (`Last-Event-ID`), and the stream starts after it: nothing is lost or repeated. The stream: - starts with `retry:` (how long a browser waits before reconnecting) and a `job` frame, the job's record; - waits for new events, checking every [`$interval`](https://mmoframework.fr/en/documentation/mmo.core/php/jobs/JobEventStream.md#jobeventstream-interval) seconds, with a comment every [`$keepAlive`](https://mmoframework.fr/en/documentation/mmo.core/php/jobs/JobEventStream.md#jobeventstream-keepalive) seconds so that no proxy closes it; - releases the session (its lock would block every other request of the browser while it streams); - ends once the job has ended and its last event is sent (an `end` frame, the record again: a browser then closes its `EventSource`, or it would reconnect), when the client leaves, or after [`$duration`](https://mmoframework.fr/en/documentation/mmo.core/php/jobs/JobEventStream.md#jobeventstream-duration) seconds (the browser reconnects where it stopped: a php worker is not held forever).
$stream = new JobEventStream(JobStore::Shared(), $id, (int)($_SERVER['HTTP_LAST_EVENT_ID'] ?? 0)); return new StreamResponse($stream, 200, 'OK', JobEventStream::Headers());

Properties12

begun

protected bool $begun = false
Type
bool

duration

int $duration = 300
Type
int

ended

protected bool $ended = false
Type
bool

id

protected string $id
Type
string

interval

float $interval = 0.25
Type
float

keepAlive

int $keepAlive = 15
Type
int

lastSent

protected float $lastSent
Type
float

offset

protected int $offset
Type
int

retry

int $retry = 2000
Type
int

started

protected float $started
Type
float

store

protected MMO\core\jobs\JobStore $store
Type
JobStore

Methods21

Frame($event, $data, $id)

staticJobEventStream.php:75

One SSE frame.

static function Frame(?string $event, mixed $data, ?int $id = null): string
$eventnull | stringits type (none: the browser's message)
$datamixedjson encoded
$id = nullnull | int
returnsstring
JobEventStream::Frame('progress', ['done' => 3], 120); // "id: 120\nevent: progress\ndata: {\"done\":3}\n\n"

getContents()

JobEventStream.php:156
function getContents(): string
returnsstringevery frame until the end: only for a job that has ended (or a test), it waits otherwise.

Headers()

staticJobEventStream.php:58
static function Headers(): array
returnsarraystring> the headers an event stream answers with: never cached, never buffered (nginx).

read($length)

JobEventStream.php:86

The next frames: waits until there is something to send (new events, a keep-alive, the end).

function read(int $length): string
$lengthintignored: frames are sent whole
returnsstring'' only once the stream has ended

seek($offset, $whence)

JobEventStream.php:152
function seek(int $offset, int $whence = MMO\core\jobs\SEEK_SET): void
$offsetint
$whence = MMO\core\jobs\SEEK_SETint
returnsvoid

__construct($store, $id, $offset, $aborted)

JobEventStream.php:53
function __construct( MMO\core\jobs\JobStore $store, string $id, int $offset = 0, ?Closure $aborted = null )
$storeJobStore
$idstringthe job
$offset = 0intwhere to start: the last event id the client has (0: from the start)
$aborted = nullnull | Closure