@plinthjs/octane
v0.1.0
Published
Mason persistent high-throughput app server (the Laravel Octane equivalent).
Maintainers
Readme
@plinthjs/octane
A persistent, high-throughput application server for Mason, the Laravel Octane equivalent. A
conventional runtime boots the framework on every request; Octane boots the Application once and
reuses the warm instance across many requests. After every request (success or failure) the worker
flushes scoped container instances, so per-request state never leaks into the next request.
Built only on Node built-ins (node:http, node:cluster) plus @plinthjs/core and @plinthjs/http.
Install
npm install @plinthjs/octaneUsage
import { Application } from '@plinthjs/core'
import { HttpKernel, Response, Router } from '@plinthjs/http'
import { OctaneServer, OctaneWorker } from '@plinthjs/octane'
const app = new Application({ runningInConsole: false })
const router = new Router()
router.get('/ping', () => Response.json({ pong: true }))
const kernel = new HttpKernel(router, { container: app })
const worker = new OctaneWorker({ app, kernel })
const server = new OctaneServer(worker)
await server.start({ port: 8000, host: '0.0.0.0' })
// Later, on shutdown: closes the HTTP server, stops ticks, terminates the app.
await server.stop()The worker
OctaneWorker is the testable core. Give it a ready { app, kernel } context, or a factory that is
invoked once on first boot:
const worker = new OctaneWorker({ factory: async () => buildContext() })
await worker.boot() // idempotent; also boots the Application
const response = await worker.handle(request) // runs through the warm HttpKernel
worker.requestsHandled() // 1
worker.isBooted() // trueLifecycle hooks
Every hook registrar returns the worker, so they chain:
worker
.onBoot((app) => warmCaches(app)) // once, after the first boot
.onRequest((request) => metrics.start(request))
.onRequestHandled((request, response) => metrics.finish(request, response))
.onTick(() => flushBuffers(), 5_000) // every 5 seconds while serving
.onTerminate((app) => closeConnections(app))Tick timers are started by server.start() (or worker.startTicking()), are unref'd so they never
hold the process open, and swallow errors so a failing task cannot crash the worker. Call
worker.tick() to run every tick hook once, which is handy in tests.
Clustering
await server.start({ port: 8000, workers: 4 })With workers > 1 the primary process forks that many workers via node:cluster (re-forking any
that exit) and resolves undefined; each worker serves its own warm instance. Under a test runner
the server always runs single-process. Use server.build() to get an unbound node:http server
for a booted worker, and getServer() / getWorker() to inspect the running instance.
Concurrent tasks
import { concurrently } from '@plinthjs/octane'
const [users, orders] = await concurrently([() => loadUsers(), () => loadOrders()])