Skip to content

rutis v0.19.2

Choose a tag to compare

@github-actions github-actions released this 30 Oct 14:14
· 220 commits to main since this release
fc785ff

rutis 0.19.2

中文 · 0.19.1 release notes

0.19.2 fixes bugs: places that gave wrong results, hung or made memory blow up. Plugin code and rutis.json stay as they are; the "Behaviour changes" section lists every difference you can see, and the three that affect code written today come first.

Read these three first

  • TypeScript / Bun tests unload at the end of the test (#933, #971). The plugin load loaded is unloaded when its test ends and the fake services it gave are withdrawn, so a failed test no longer leaves its services to the next one (the next test used to get llm is already provided by rutis-test). Code that loads in one test and goes on using it in the next now gets PluginTestError: the plugin is unloaded in the second test: have each test load its own.
  • A 30-second limit on the Python test tool's calls (#971). An asynchronous call of the service under test that does not return within 30 seconds fails with PluginTestError: greeter.hello() did not return within 30 s; the test used to hang without a word.
  • A runtime path that is not there is an error (#935, #974). A runtimes.node.runtime or runtimes.bun.runtime naming a path that does not exist used to switch quietly to a runtime found elsewhere; now check, run, dev and add all say runtimes.node.runtime names <path>, which does not exist (for a directory without package.json, …, which is no npm package (it has no package.json)). A runtimes.py.project that does not exist used to be reported as the interpreter's error; now the message says the path does not exist.

Memory

  • The memory peak when many instances close together (#977, #978). Each emit copied all the listeners of its event, and every queued event held its own copy; when the listeners grow with the number of instances, the peak grew with its square. Now emits without a filter share one listener list cached per event name, and nothing is allocated when there is no listener; an emit with a filter and parallel / serial / waterfall / bail still select each time. Measured on Dim (0.17.1, N=1000 sessions closed one after another): the closing peak goes from 3.43 GB to 444 MB (what the sessions use while running). Event order, filters, once / prepend are unchanged.

Hosts

  • A plugin evicted while loading returns to Pending when build / validate / apply returns an error (#968, #969). When a service a loading plugin uses is withdrawn, the kernel cancels that generation first; the plugin used to go to Failed after that, was not retried when the same service came back, and only restart() brought it back; now it returns to Pending and loads once more when the service comes back. A restart, update, dispose or shutdown while loading used to pass through Failed once (the final state was right); it no longer does. A panic after the cancellation still goes to the error sink once; a plugin cancelling its own token, and a genuine failure the driver did not cancel, are still Failed.
  • An abandoned reconcile no longer holds up later operations (#934, #972). After a host gave up a reconcile with timeout (one row's apply does not return), a reload of another row, another reconcile and the reload after a runtime restart used to never return; now they return as usual, and the stuck row is still starting. Loader::settled() still waits for every row.

rutis-host

  • Under check --strict, a misspelt row field and a row id used twice are errors (#974), exit code 1; without --strict they are still warnings. A misspelt row field gets a did you mean.
  • status / call say where they looked when no host answers (#974): no rutis-host answers for <configuration> at <socket path> (XDG_RUNTIME_DIR=<value>), adding that for a host run as a service the command must run in its environment. The deployment section has a complete systemd unit and launchd plist.

rutis-host dev

(#938, #976)

  • Python: a changed helper module of the plugin's package is now imported again, together with the other modules of the package (it used to print reloaded and go on running the old code); modules outside the plugin's package still need dev restarted.
  • Python: a breakpoint() without --debug fails the call with RuntimeError: breakpoint() needs a terminal, and this Python runtime has none: run rutis-host dev --debug (it used to be BdbQuit or SystemExit: 1); under --debug, Ctrl-C after a breakpoint exits at once with exit code 0 (it used to wait the full 10 seconds and exit with 2).
  • Go: with several plugins in one binary, the project's own plugins are the rows rutis.dev.json writes (banner running weather, llm); a name ignored on a row of the same id gets a warning.
  • In a Python project with a package.json at its root, it is a Node project only when the entry file that package.json names exists.
  • A row whose reload failed and whose previous version keeps running shows in status as running (the previous version: its last reload failed).
  • A row restarted by a change names its reason once: caller: restarted (weather reloaded) (with several files changed together it used to be restarted (weather reloaded, weather restarted)).

Test tools

  • TypeScript / Bun: while a test waits for the result of a function a plugin handed over, node --test no longer takes the process for idle and cancels the test (#932, #967). The example of section 5 of Build a host open to plugins failed every time on Linux because of it.

Error messages and intermittent failures

(#965, #975; #922, #970)

  • A failed wait for a runtime's greeting says why: the runtime's channel failed: the read of its greeting was cancelled / … panicked: <message>.
  • When a runtime process exits, calls on its objects always say runtime <name> exited (they sometimes said disconnected).
  • Two intermittently failing tests are fixed at their root (the fd handover in test_command, waits.rs judging complexity by elapsed time).

Documentation

(#939, #973)

What the 0.19.0 evaluation had to guess, or found different from what happens: the Go debugger version (dlv@v1.26.3, which installs with Go 1.24) and a dev-only fake service written in Go; the row id of a Python project in dev; a Rust plugin using another language's service by name, and how a plugin without configuration registers; how a host gets the state as text, and the type of processes(); rutis-host's row fields, its output formats, and which languages check argument types.

Behaviour changes

Where Before Now
End of a TS / Bun test the plugin load loaded stays until unload unloaded when the test ends
An asynchronous call in the Python test tool hangs while it does not return after 30 s, PluginTestError: … did not return within 30 s
runtimes.node.runtime / runtimes.bun.runtime naming a path that is not there quietly uses a runtime found elsewhere an error naming the path
check --strict: a misspelt row field, a row id used twice warnings, exit code 0 errors, exit code 1
status / call find no host no rutis-host runs … (status), no rutis-host run or dev is running for … (call) names the socket path and XDG_RUNTIME_DIR
Evicted while loading, build / validate / apply returns an error Failed, not retried back to Pending, loaded again when the service returns
restart / update / dispose / shutdown while loading passes through Failed once does not pass through Failed
Operations after an abandoned reconcile never return return as usual
Many instances closing together (listeners growing with instances) the peak grows with the square of the instance count linear in the instance count
dev: a Python helper module changed prints reloaded, still the old code imported again
dev: breakpoint() without --debug BdbQuit / SystemExit: 1 RuntimeError: … run rutis-host dev --debug
dev --debug: Ctrl-C after a breakpoint waits 10 s, exit code 2 exits at once, exit code 0
dev: a Go binary of several plugins the first in alphabetical order is the project's own, name dropped silently the rows rutis.dev.json writes are the project's own, a warning when name is dropped
dev: a row restarted by a change the reason may repeat (weather reloaded, weather restarted) written once per row
A failed wait for a runtime's greeting the runtime's channel failed followed by the cancellation or the panic
Calls on objects of a runtime that exited sometimes disconnected always exited

Compatibility

  • The protocol is unchanged and 0.19.2 connects with 0.19.0 and 0.19.1 as usual. The formats of rutis.json and rutis.dev.json are unchanged.
  • No public API is added or removed.

Packages

All of these are version 0.19.2: on crates.io rutis, rutis-macros, rutis-bridge, rutis-loader, rutis-types, rutis-host, rutis-sdk, rutis-dylib, rutis-dylib-meta, rutis-dylib-launcher; on npm @arcships/rutis, @arcships/rutis-runtime, @arcships/rutis-bun, @arcships/rutis-host and the five platform packages; on PyPI rutis, rutis-host; the Go module github.com/arcships/rutis/go/rutis (tag go/rutis/v0.19.2); the Swift package (v0.19.2); the rutis-host binaries on the GitHub release page. The Kotlin SDK, as in 0.19.0, is used from source at the tag v0.19.2.