Skip to content

Releases: oxphp/stub

v0.7.0 — Decorator StackOverflowException

05 Jun 19:52

Choose a tag to compare

Sync with oxphp v0.7.0.

OxPHP\Decorator

  • Added StackOverflowException, thrown when nested decorated calls exceed the decorator context stack depth (256 levels). Fails loud instead of silently corrupting decorator context for the overflowing frame.

The stub file is byte-identical to oxphp v0.7.0.

v0.6.0 — async race/any, Shared\Atomic + Registry, Worker graceful exit

04 Jun 21:24

Choose a tag to compare

Sync with oxphp v0.6.0.

Global functions

  • Removed oxphp_request_heartbeat($time). Migrate to set_time_limit($seconds)
    — both reset the per-request execution timer to N seconds from now.
  • Added oxphp_async_await_race(int[], ?float) — first promise to settle wins
    (fulfil OR reject); the JavaScript Promise.race analog.
  • oxphp_async_await_any(int[], ?float) is now Promise.any: the first promise
    to FULFIL wins; rejections accumulate and, if all reject, throw
    AggregateAsyncException.
  • oxphp_server_info() array shape changed: "sapi" dropped, "worker_mode" added
    → {version, worker_id, request_time, worker_mode}.

OxPHP\Async

  • Base exception renamed Exception → AsyncException.
  • Added AggregateAsyncException (getErrors/getErrorMap/getPromiseIds).
  • TimeoutException now extends AsyncException and exposes getPartialErrors()
    and getCancelledPromiseIds() (populated by oxphp_async_await_any()).

OxPHP\Shared

  • Base exception renamed Exception → SharedException.
  • New Ordering enum (Relaxed/Acquire/Release/AcqRel/SeqCst) and Atomic class —
    load/store/swap/compareAndSet/fetch arithmetic & bitwise with explicit
    memory ordering. Flag gains the same load/store/swap/compareAndSet surface.
  • New Registry — name-keyed process-global get-or-create for every Shared*
    type (map/counter/atomic/flag/once/mutex/channel/pool/global).
  • Counter: inc/dec replaced by add(); added compareAndSet() and id().
  • Once: getOrInit() (was init()), status(), Reset/Poison failure modes.
  • Mutex: withLock()/tryWithLock()/withLockTimeout(); poison API removed in
    favour of sticky CorruptedMutexException.
  • Channel: now Countable; result-typed tryRecv/recv/recvTimeout and
    trySend/send/sendTimeout returning RecvResult/SendResult (closed/full/
    timeout are normal outcomes, not exceptions).
  • Map: keys are int|string; get()/set()/setIfAbsent()/swap()/pop()/
    compareAndSet()/getMany()/forEach() with null as the absence sentinel.
  • Pool: acquire()/tryAcquire()/acquireTimeout()/with()/withTimeout(),
    RAII Handle with release(), and a Stats snapshot via stats().
  • New exceptions: ValueTooLargeException, InvalidOrderingException,
    CorruptedMutexException. Bounded-wait failures — OperationTimeoutException,
    ContentionException, DeadlockException — now extend Async\AsyncException
    (NOT SharedException), so one catch (AsyncException) sweeps both families.
  • New sub-namespaces: Shared\Once {Status, FailureMode}, Shared\Map
    {KeyCursor}, Shared\Channel {RecvStatus, SendStatus, RecvResult,
    SendResult}, and Shared\Pool\Stats.

The bounded-wait convention is uniform across Shared*: a bare method waits
forever, a try* method is non-blocking, and a *Timeout(int $ms) method waits a
bounded number of milliseconds ($ms must be > 0).

OxPHP\Server\Worker

  • Method renames: getId/getStartTime/getRequestCount/getMemoryUsage/getRss/
    getMaxMemoryBytes → id/startTime/requestCount/memoryUsage/rss/maxMemoryBytes.
  • Graceful exit: scheduleExit(), isExitScheduled(), exitReason()
    (scheduled/max_memory/error).

Packaging

  • @Version bumped 0.5.0 → 0.6.0 in oxphp.stub.php.
  • README function tables and Object API list updated; migration note added.

v0.5.0 — Server\Worker runtime handle

04 Jun 21:15

Choose a tag to compare

Sync with oxphp v0.5.0.

Server runtime — new OxPHP\Server namespace

final class OxPHP\Server\Worker — per-thread handle for the worker runtime.
Stateless wrapper; every method reads Rust thread-local state via FFI at call
time. Worker::current() is a per-thread singleton.

Static factory / predicate:

  • Worker::current(): self — per-thread Worker singleton
  • Worker::isWorkerMode(): bool — whether this thread runs in worker mode

Instance methods:

  • getId(): int — worker thread index (0..N-1)
  • getStartTime(): float — Unix timestamp when the thread was spawned
  • getRequestCount(): int — requests this thread has started (1-based)
  • getMemoryUsage(): int — current Zend allocator usage in bytes
  • getRss(): int — process RSS in bytes
  • getMaxMemoryBytes(): int — configured worker memory cap (0 = none)
  • serve(callable): void — enter the worker request-dispatch loop

Exception:

  • OxPHP\Server\Exception\InvalidServeContextException — thrown by serve()
    when called outside worker mode

Packaging

  • @Version bumped 0.3.0 → 0.5.0 in oxphp.stub.php
  • README function tables updated

v0.3.0 — Shared primitives, APM, profiler, async namespace cleanup

25 Apr 20:26

Choose a tag to compare

Async — namespace cleanup

  • OxPHP\AsyncException → OxPHP\Async\Exception
  • OxPHP\AsyncTimeoutException → OxPHP\Async\TimeoutException
  • OxPHP\AsyncBorrowException → OxPHP\Async\BorrowException
    (no longer "reserved" — now thrown by every BorrowedProxy access)
  • OxPHP\Async\BorrowedProxy — opaque stand-in injected for use-captured
    values that aren't safe to touch on the promise thread; every access
    (__get/__set/__call/__isset/__unset/__toString/__debugInfo/jsonSerialize)
    throws BorrowException

New APM API (OpenTelemetry tracing)

Global functions:

  • oxphp_apm_trace(string, callable, array) — auto-closed child span
  • oxphp_apm_start(string, array): int — manually open a child span
  • oxphp_apm_end(int) — close a manually opened span
  • oxphp_apm_attribute(string, mixed, ?int) — add attribute to current/given span
  • oxphp_apm_event(string, array, ?int) — add a named timestamp event
  • oxphp_apm_error(Throwable, ?int) — record exception + mark span errored
  • oxphp_apm_status(int, ?string, ?int) — set explicit span status
  • oxphp_apm_trace_id(): string — 32-hex W3C trace ID
  • oxphp_apm_span_id(): string — 16-hex active span ID
  • oxphp_apm_header(): string — W3C traceparent header value

Constants:

  • OXPHP_APM_OK, OXPHP_APM_ERROR

Attribute:

  • #[OxPHP\Apm\Trace(?string $name = null)] — auto-registered when APM is enabled,
    wraps the annotated function/method in a span (implements Decorator\AttributeInterface)

New Profiler API (namespace OxPHP\Profile)

Functions:

  • OxPHP\Profile\is_active(): bool
  • OxPHP\Profile\start() / stop() / pause() / resume()
  • OxPHP\Profile\mark(string $label, array $attrs = [])
  • OxPHP\Profile\metric(string $name, float $value)

Attributes (all under OxPHP\Profile):

  • #[Profile], #[Exclude] — explicit include / exclude
  • #[Sample(float $rate)] — per-target sampling
  • #[Tag(string $key, string $value)] — repeatable static tag
  • #[Mark(?string $label = null)] — entry-point marker
  • #[SlowThreshold(int $ms)] — emit slow.call marker over $ms
  • #[MemoryThreshold(int $kb)] — emit memory.spike marker over $kb

New Shared primitives (namespace OxPHP\Shared)

Process-wide concurrent primitives visible from every PHP worker thread.
All implement the OxPHP\Shared\Shareable marker interface so they can be
nested inside Map / Channel without serialisation.

  • Counter — lock-free atomic signed 64-bit counter (get/set/inc/dec/add/
    compareAndSet/addBatch/reset/id)
  • Flag — atomic boolean flag (test/set/clear/compareAndSet/exchange/id)
  • Once — run-once container with cross-worker initialisation
    (get/isInitialized/trySet/init/id)
  • Mutex — poisoning mutex with optional timeout
    (with/tryWith/isPoisoned/clearPoison/id)
  • Channel — bounded MPMC queue with fiber-aware blocking send/recv
    (send/recv/trySend/tryRecv/sendMany/recvMany/close/isClosed/pending/id)
  • Map — concurrent string→mixed store with cycle detection and per-instance
    cap (get/set/has/remove/clear/count/keys/maxEntries/setIfAbsent/update/
    getOrSet/setMany/getMany/updateMany/removeMany/id)
  • Pool — bounded object pool with idle-timeout eviction
    (acquire/release/with/evict/size/inUse/idle/waiting/maxSize/id)
  • OxPHP\Shared\Pool\Handle — scope-bound reference returned by Pool::acquire()

Exception hierarchy (all extend OxPHP\Shared\Exception):

  • StaleHandleException, TypeException ← CycleException, CapacityException,
    ClosedException, PoisonedException, TimeoutException ← DeadlockException,
    UninitializedException

Other

  • @Version tag bumped to 0.3.0
  • README updated with APM, Profiler and Shared sections

v0.2.0 — Object API, async, decorators

25 Apr 20:10

Choose a tag to compare

New global functions

  • oxphp_http_request() — typed read-only request object (RequestInterface)
  • oxphp_superglobals_enabled() — check if $_GET/$_POST are populated
  • oxphp_sleep(float), oxphp_usleep(int) — cooperative fiber sleep
  • oxphp_async(Closure, ...) — dispatch a closure to the async worker pool
  • oxphp_async_await(int, ?float) — block on a single promise
  • oxphp_async_await_all(int[], ?float) — wait for every promise
  • oxphp_async_await_any(int[], ?float) — race promises, first wins
  • oxphp_register_decorator(string) — register an #[Attribute] decorator class

New Object API (namespace OxPHP\Http)

  • RequestInterface (+ final Request) — method/path/fullUri/scheme/host/port,
    query/payload, headers/cookies, raw body, file uploads, ip, startTime,
    attributes, session
  • SessionInterface (+ final Session) — read-only $_SESSION view
  • UploadedFileInterface (+ final UploadedFile) — uploaded file with magic-bytes
    MIME detection (type() vs spoofable clientType())
  • AttributesInterface (+ final Attributes) — mutable middleware container

New exception classes

  • OxPHP\Http\Exception\NoActiveRequestException — base for request-context errors
  • OxPHP\Http\Exception\AsyncContextException — request access from oxphp_async()
  • OxPHP\Http\Exception\WorkerIdleException — worker between requests
  • OxPHP\AsyncException — async task failed (closure threw / die / exit)
  • OxPHP\AsyncTimeoutException — oxphp_async_await() timed out
  • OxPHP\AsyncBorrowException — reserved for future use
  • OxPHP\Decorator\RejectedException — Rust-native decorator rejected the call

New decorator API (namespace OxPHP\Decorator)

  • AttributeInterface — implement before(Context)/after(Context) and register
    with oxphp_register_decorator()
  • Context — target/class/method/function, objectId, requestId, traceId,
    lazy getParams() / getResult() / hasResult()

Other

  • @Version tag bumped to 0.2.0; oxphp_server_info() example updated to match

v0.1.0 — Initial release

25 Apr 19:56

Choose a tag to compare

Function stubs for the oxphp_sapi PHP
extension. Enables IDE autocompletion (PhpStorm, VS Code + Intelephense) and
static analysis (PHPStan, Psalm) for oxphp_*() calls.

Declarations only — the file is not loaded at runtime, so it can't collide
with the real C-level functions exported by the OxPHP server.

Install

composer require --dev oxphp/stubs

PHPStan picks the stubs up automatically via
phpstan/extension-installer.
Psalm users wire them in through <stubs> in psalm.xml — see the
README for details.

Functions covered

Function Returns Purpose
oxphp_request_id() string 16-hex-char request ID, identical to the X-Request-ID response header. Passes through a client-supplied header when present.
oxphp_worker_id() int Zero-based index of the PHP ZTS worker thread serving the request (0..PHP_WORKERS-1). Useful for per-worker caches and log correlation.
oxphp_server_info() array{sapi, version, worker_id, request_time} Server metadata. request_time is captured before php_request_startup() with microsecond precision.
oxphp_finish_request() bool Flushes the response and detaches the request so subsequent code runs in the background (analogue of fastcgi_finish_request). Returns false if already called.
oxphp_is_worker() bool true when the SAPI is in worker mode (PHP booted once, requests served via oxphp_worker()), false in traditional per-request mode.
oxphp_is_streaming() bool true when the current request is in streaming mode (SSE / chunked transfer) — output is flushed instead of buffered.
oxphp_request_heartbeat(int $time = 10) bool Extends the request timeout by $time seconds from the moment of the call. Intended to be invoked periodically inside long-running loops.
oxphp_stream_flush() bool Activates streaming mode and flushes buffered output as a chunk. First call sends HTTP headers; subsequent calls flush data written since the previous call. Auto-activated when Content-Type: text/event-stream. Returns false if oxphp_finish_request() already fired.
oxphp_worker(callable $handler) bool Enters the worker-mode request loop. The handler is invoked per request with fresh superglobals; bootstrap state in the outer scope persists between requests. Requires the WORKER_FILE env var. Returns true on graceful shutdown; code after the call runs during shutdown.

Compatibility

  • PHP >= 8.4
  • Tracks oxphp_sapi extension API at version 0.1.0

License

MIT — safe to add as a require-dev to any project. The OxPHP server itself
remains AGPL-3.0-or-later.