@open-matrix/runtime-hosting (0.1.19)

Published 2026-09-05 02:53:29 +00:00 by hivecast-admin

Installation

@open-matrix:registry=
npm install @open-matrix/runtime-hosting@0.1.19
"@open-matrix/runtime-hosting": "0.1.19"

About this package

@open-matrix/runtime-hosting

Adapters between the generic application host and Matrix runtime/actor lifecycles. The package has no compile-time dependency on @open-matrix/core; its structural ports prevent a dependency cycle and keep the actor kernel hosting-independent.

Runtime ownership

Generic Host
    -> MatrixRuntimeHostedService
        -> MatrixRuntime lifecycle
            -> MatrixActorLease lifecycle

AddLegacyMatrixRuntime() is an explicitly named Anti-Corruption Layer for the current constructor-starting runtime. It preserves inert host Build() by deferring runtime construction until host startup, but it does not make the legacy constructor itself inert.

If an asynchronous legacy factory ignores cancellation and returns after the startup deadline, the adapter compensates the unexposed result by invoking its shutdown() operation and then asynchronous disposal. The canceled result is never published through IMatrixRuntimeAccessor; cleanup failures remain observable and retain the runtime as host-disposal retry authority.

AddNativeMatrixRuntime() is the target path:

const builder = Host.CreateApplicationBuilder();

AddMatrixActorActivation(builder.Services);

AddNativeMatrixRuntime(
  builder.Services,
  (services, token) => {
    token.ThrowIfCancellationRequested();
    return MatrixRuntimeBuilder.create()
      .withTransport(transport)
      .withActorActivator(
        services.GetRequiredService(IMatrixActorActivatorKey),
      )
      .buildInert();
  },
);

await using host = builder.Build();
await host.StartAsync();

The native adapter maps:

Host StartingAsync -> construct inert runtime + ValidateAsync
Host StartAsync    -> runtime StartAsync
Host StoppingAsync -> runtime BeginDrainAsync
Host StopAsync     -> runtime StopAsync
Provider disposal  -> runtime DisposeAsync

Runtime stop is a retryable resource transaction. A failed or caller-canceled StopAsync attempt leaves the lifecycle nonterminal, retains the exact runtime, and clears only the failed in-flight attempt. A later host stop supplies a fresh cancellation signal and resumes at runtime stop without repeating a completed drain phase. The runtime is published by IMatrixRuntimeAccessor only while its state is operational or successfully stopped; a faulted-but-retained runtime is kept private as cleanup authority until retry succeeds or disposal completes.

Hosted resources

AddHostedResource() adapts one independently owned asynchronous resource into an IHostedLifecycleService. Registration order expresses dependency order: resources start dependencies-first and stop consumers-first. Construction and asynchronous I/O occur during host startup rather than in dependency-injection factories.

Hosted-resource shutdown is also a retryable resource transaction. A failed or caller-canceled StopAsync attempt:

  • retains the exact resource value as cleanup authority;
  • transitions the accessor to Faulted, so operational access is refused while cleanup remains incomplete;
  • discards only the failed in-flight stop promise;
  • accepts a fresh cancellation token on the next host stop;
  • does not repeat a successfully completed BeginDrainAsync phase;
  • disposes and releases the value only after stop succeeds.

DisposeAsync() cannot destroy the retained object graph while stop remains incomplete. It first resumes the stop transaction with CancellationToken.None; only successful stop permits final resource disposal and the terminal Disposed state.

Actor activation

AddMatrixActorActivation() registers a service-provider-backed actor activator. Activation is two-phase so the runtime can wire RootActor control delegates before inbox subscriptions begin:

const lease = await activator.CreateLeaseAsync(
  ActorType,
  context,
  id,
  properties,
);

// Runtime-owned callbacks and metadata are installed here.
await lease.InitializeAsync(signal);

Each lease owns one actor and one asynchronous dependency scope. It guarantees:

  • initialization at most once;
  • disposal at most once;
  • actor disposal before scope disposal;
  • cleanup after failed initialization;
  • a fresh scope for every supervised restart;
  • disposal requests abort cancellation-aware initialization and then join the single in-flight initialization transaction before releasing either resource;
  • cancellation-unaware initialization is still serialized: any allocation made after an awaited continuation is observed before actor disposal begins, so no actor can resume into an already-disposed dependency scope;
  • the post-initialization cancellation fence prevents a lease from publishing IsInitialized = true after disposal has been requested.

Important tradeoffs

  • MatrixContext remains hierarchical actor/protocol context; the dependency scope is a separate flat lifetime boundary.
  • Existing property-bag actors continue through ActorPropertyBinder while implementation dependencies move toward constructor injection.
  • Dynamic packages may not mutate the root provider after build; package-local providers are a later package-hosting concern.
  • The legacy adapter is temporary and must not become an unnamed fallback.

Dependencies

Dependencies

ID Version
@open-matrix/core 0.1.31
@open-matrix/hosting 0.1.7

Development Dependencies

ID Version
@types/node ^25.0.10
typescript ^5.7.0
Details
npm
2026-09-05 02:53:29 +00:00
2
MIT
latest
13 KiB
Assets (1)
Versions (17) View all
0.1.19 2026-09-05
0.1.18 2026-09-05
0.1.17 2026-09-04
0.1.16 2026-09-04
0.1.15 2026-09-04