pilotphp/runtime-native

Synchronous in-process runtime adapter for PilotPHP.

Maintainers

Package info

gitlab.com/pilotphp/runtime-native

Issues

pkg:composer/pilotphp/runtime-native

Transparency log

Statistics

Installs: 3

Dependents: 0

Suggesters: 0

Stars: 0

0.1.4 2026-08-02 19:19 UTC

This package is auto-updated.

Last update: 2026-08-02 16:22:03 UTC


README

A finite, synchronous, in-process runtime adapter for PilotPHP.

NativeRuntime boots one kernel, pulls transport-neutral invocations from a finite source, delivers each outcome to a sink, and shuts the kernel down. It is intended for development, tests, command-line jobs, and small controlled integrations. It is not a production server or worker runtime: it has no transport, blocking receive loop, concurrency, signals, retries, daemon supervision, or terminal UI.

Installation

composer require pilotphp/runtime-native

The package requires PHP 8.5, pilotphp/contracts ~0.0.2, and currently pilotphp/runtime dev-main. The development constraint is a deliberate pre-release deviation until a compatible pilotphp/runtime release exists; see Integration.

Package discovery

This package is discoverable but performs no discovery. It publishes the metadata chain that external PilotPHP build tooling walks:

composer.json
  → extra.pilotphp.manifest
  → pilot/package.json
  → entrypoint
  → PilotPHP\RuntimeNative\NativeRuntimePackage
  → descriptor()

pilot/package.json is the machine-readable manifest (pilotphp.package.v1). It names NativeRuntimePackage as the entrypoint, and that class's descriptor() publishes the package's dependencies (pilotphp/contracts, pilotphp/runtime) and its capabilities (runtime.adapter.native, runtime.in-process, runtime.synchronous).

Walking that chain is the build tooling's job, not this package's. Nothing in src/ reads composer.json, the manifest, Composer's installed metadata, or the filesystem — an architecture test enforces it.

Discovery is deliberately inert:

  • Discovering the package constructs no NativeRuntime. It selects no source or sink, builds no kernel, and starts no WorkerLifecycle.
  • Activation does not run anything. Passing a NativeRuntimePackage instance to a composition makes it an active graph node and nothing more.
  • Capabilities are claims, not choices. If several active packages provide a runtime capability, an explicit capability binding picks the provider. There is no priority, first-found, or last-wins rule.
  • The application supplies the collaborators. A source, a sink, and a request scope come from the application bootstrap, because none of them is derivable from package metadata.
  • run() remains the only way to start the runtime.

See Integration for the full sequence and Public API for the per-type contract.

Runnable example

Save this as example.php in a Composer project that also provides pilotphp/container, then run php example.php:

<?php

declare(strict_types=1);

require __DIR__ . '/vendor/autoload.php';

use PilotPHP\Container\Runtime\RequestScope;
use PilotPHP\Contracts\Kernel\KernelInterface;
use PilotPHP\Contracts\Runtime\InvocationInterface;
use PilotPHP\Runtime\Context\RequestContext;
use PilotPHP\Runtime\Invocation\Invocation;
use PilotPHP\RuntimeNative\Result\NullResultSink;
use PilotPHP\RuntimeNative\Runtime\NativeRuntime;
use PilotPHP\RuntimeNative\Source\SingleInvocationSource;

final readonly class Add
{
    public function __construct(public int $left, public int $right) {}
}

final readonly class Sum
{
    public function __construct(public int $value) {}
}

$kernel = new class implements KernelInterface {
    public function boot(): void {}
    public function reset(): void {}
    public function shutdown(): void {}

    public function invoke(InvocationInterface $invocation): object
    {
        /** @var Add $input */
        $input = $invocation->input();

        return new Sum($input->left + $input->right);
    }
};

$invocation = new Invocation(
    'math.add',
    new Add(20, 22),
    new RequestContext('example-1'),
);

$runtime = new NativeRuntime(
    new SingleInvocationSource($invocation),
    new NullResultSink(),
    new RequestScope(),
);

exit($runtime->run($kernel));

The example intentionally prints nothing. NativeRuntime never writes to STDOUT or STDERR; observe its integer return value, summary(), lastError(), or provide a result sink.

Public API

  • NativeRuntime implements RuntimeInterface; run() is one-shot.
  • InvocationSourceInterface::next() returns the next invocation or null when its finite, non-blocking input is exhausted.
  • EmptyInvocationSource, SingleInvocationSource, and IterableInvocationSource are supplied source implementations.
  • InvocationResultSinkInterface receives success and failure outcomes. NullResultSink discards them.
  • InvocationFailurePolicy::Stop is the default; InvocationFailurePolicy::Continue continues only after ordinary failures on a still-healthy worker.
  • NativeRuntimeSummary reports the final exit code, counters, and worker poisoning.
  • InvocationSuccess and InvocationFailure are optional compact result records for custom sinks; the runtime does not construct or store them.

Source and sink interfaces are the supported replacement points. They replace where work comes from and where outcomes go; they do not replace lifecycle orchestration. The runtime integrates with the kernel exclusively through WorkerLifecycle.

Exit values

ValueEnum caseMeaning
0SuccessSource exhausted and every delivered invocation succeeded
1InvocationFailureAt least one ordinary invocation failed
2BootFailureWorker boot failed; shutdown was not attempted
3PoisonedProcessing failed and worker health became poisoned
4ShutdownFailureShutdown failed; this overrides the earlier exit value
5SourceFailureReading the next invocation threw
6ResultSinkFailureDelivering a success or failure outcome threw

With Continue, an ordinary failure still makes the final value 1 even if later invocations succeed. Source, sink, poisoning, boot, and shutdown failures always stop. Details are in Error policy.

Documentation

Development

make install
make check
make benchmark

make check validates Composer metadata, checks style, runs PHPStan, and runs the tests. Benchmarks are measurements, not release gates.