Skip to content

v0.3.0

Choose a tag to compare

@arloliu arloliu released this 03 Aug 08:09
· 28 commits to main since this release

Observability and lifecycle reporting: a host can now say which plugin a
failure came from, order the transitions it observes, account for what it
drops, and size its own shared memory. Plus the teardown and crash-reporting
fixes that writing those answers surfaced.

Full detail in CHANGELOG.md.

Added

  • Typed lifecycle verdicts. EventUnhealthy carries a typed error
    (MissedHeartbeatsError, WedgedError) instead of prose, so a consumer can
    branch on which check failed rather than matching message text. Sentinels
    ErrHeartbeatsMissed and ErrWedged work with errors.Is.
  • Panic identity. PluginPanicError names the plugin, service, and method.
    Calls through generated stubs address methods by numeric ID and had no name
    to report at all; the generator now registers each method's name via
    RegisterIdentityName, resolved only when a panic actually happens, with an
    allocation gate holding the ordinary call path to its measured cost.
    Regenerate stubs with the v0.3.0 generator to get named panics.
  • Drop accounting. observe.MetricStdioDropped, MetricObserveDropped,
    and MetricStdioSinkPanic count stdio lines and observability records a host
    discards. Reported as per-interval deltas rather than one event per drop, so
    a plugin spraying output cannot turn a counter into its own flood, with a
    final delta when an instance ends so the interval a crash cuts short is still
    accounted for.
  • Health transition revisions. Event.Revision and
    HealthSnapshot.Revision let a consumer seed from Health() and fold
    Events() with one comparison. Kind and Time cannot do this: the bus
    delivers a critical EventCrashed ahead of an informational EventStarting
    published before it, and two events in the same tick carry equal Time.
    Revisions are comparable only within one Event.Plugin.
  • ShmGeometry.RegionBytes(). Reports the exact per-plugin region size,
    derived by the same code that lays out a real region so the two cannot drift.
    Default geometry reserves 65,994,752 bytes per plugin — the number to size a
    container against.

Changed

  • Host.Stop honors its context on every path it previously outran: a
    supervisor a parked Start had not handed over, pinned-binary hashing under
    the host lock, and a worker release owned by another caller. Concurrent
    Stop callers are now linearized. A caller passing a tight deadline will see
    context errors where it previously blocked and eventually succeeded —
    teardown continues in the background; the error says the wait ended.
  • Host.Start after a Stop has begun reports ErrHostStopped.

Fixed

  • A crash's stderr is no longer lost to the sink queue. The tail a crash
    reason is built from was reachable only through the same bounded queue that
    feeds a PluginSpec.Stdio sink, so a sink falling behind, or the
    cancellation that precedes reporting a crash, could empty
    PluginCrashError.StderrTail and the stderr suffix inside Reason. A plugin
    that sprayed output before dying was then indistinguishable from one that
    printed nothing. The tail is now written by the goroutine that reads the
    pipe, before the queue.

Compatibility

Source-compatible with v0.2.0 except for positional composite literals of
styx.Event and styx.HealthSnapshot, which gained a Revision field. Keyed
literals and reads are unaffected:

grep -rn 'styx\.Event{[^K]' --include='*.go' .
grep -rn 'styx\.HealthSnapshot{[^A-Z]' --include='*.go' .

Pre-1.0: the public Go API may still move between minor versions. The wire
contracts (shm-abi.md, stream-protocol.md) are frozen.

Known gap

A narrower stderr-loss window remains: the stdio pipes are closed during
process teardown while the reader may still be draining them, so a plugin that
writes to stderr and exits in the same instant can still lose its tail. Closing
it needs a bounded join before the close, since a plugin leaking a grandchild
that holds the stderr write end would otherwise hang teardown — a
teardown-ordering change deliberately left out of this release. Where stderr is
the whole diagnosis, configure a PluginSpec.Stdio sink and log from there as
well; that path does not share this window.