snakemake_bridge 0.2.0 copy "snakemake_bridge: ^0.2.0" to clipboard
snakemake_bridge: ^0.2.0 copied to clipboard

Embed a real-time Snakemake workflow monitor in a Dart desktop app: WebSocket server, typed event models, state reducer and process launcher.

Changelog #

0.2.0 #

Control over how the Snakemake process is launched. Additive: every new parameter defaults to the previous behaviour, and the protocol is unchanged (schema v1).

  • SnakemakeRunner.start takes environment and includeParentEnvironment, passed through to Process.start. Process.start includes the parent environment by default, so the map holding the token was merged over the application's own environment rather than replacing it — and there was no way to ask for anything else. Snakemake inherited whatever the app was launched with, and so did every job it started. For an application that gives each tool its own conda environment that is a correctness problem: a PYTHONPATH, a LD_LIBRARY_PATH or an active conda env in the user's shell puts the wrong interpreter or shared library in front, and the failure is hard to trace back. Passing includeParentEnvironment: false now builds the child's environment from environment alone. The token is merged last, so a stale SNAKEMAKE_LOGGER_DART_TOKEN in the caller's map cannot shadow the run's own — for an exact-case key; Windows matches environment names case-insensitively. Note that executable is resolved against the PATH of the map that was passed, not the parent's.
  • SnakemakeRunner.start takes workdir, the directory the workflow writes into, defaulting to workflowDir as before. The two were forced to be the same, so results/ and .snakemake/ landed inside the workflow tree — which stops that tree from being read-only and shared between runs. workdir is passed as --directory, and the process still starts in workflowDir so that Snakefile discovery keeps working for all four accepted layouts (Snakefile, snakefile, workflow/Snakefile, workflow/snakefile); passing --snakefile instead would have meant guessing which one a given workflow uses. A consequence worth knowing: a relative workdir resolves against workflowDir, not against the application's working directory, so 'runs/today' writes inside the workflow tree.
  • extraArgs is documented as being appended last, so a caller can still override any argument the runner builds, --directory included.
  • The pubspec now declares platforms: as Linux, macOS and Windows. Nothing about the package had changed, but with the key absent pub.dev inferred support from the dart:io usage alone and advertised Android and iOS too — platforms where there is no snakemake process to launch in the first place. Every document already described the package as desktop-only; the metadata now says the same.
  • Documentation fix, no code change: cancel() was described as cancelling the run, and it does not. Both signals reach the Snakemake process only, and Snakemake 9 does not pass them on to its jobs — on SIGTERM the scheduler stops launching new jobs and waits for the running ones ("Will exit after finishing currently running jobs"), and the SIGKILL that follows killAfter orphans every job still running, which then goes on writing into the working directory. SIGINT behaves no better: the local executor's cancel() shuts down a thread pool whose threads are all blocked waiting on their job's process. The README now states this, and shows the process-group approach that does stop the jobs. README.md, ARCHITECTURE.md, SPEC.md and the overview diagram carried the same wrong claim and were corrected.

0.1.1 #

Robustness and performance fixes; no protocol changes (schema v1).

  • SnakemakeRunner: output written by the process before the first stdout/stderr subscriber is no longer lost. The streams were plain broadcast controllers, which discard everything emitted while nobody is listening — and since start is asynchronous, the caller could never subscribe in time; for a process that wrote early, the initial output vanished entirely. It is now buffered (up to the new maxBufferedLines) and delivered in order once a subscriber arrives.
  • SnakemakeRunner: each stream now closes when it ends, rather than on exitCode — the process can exit before in-flight output is delivered. Decoding uses allowMalformed, so an invalid byte from a tool the workflow invokes no longer tears down the stream, and read errors are forwarded to the consumer instead of surfacing as an unhandled asynchronous error.
  • WorkflowRunState: retention of logLines/errors no longer costs O(maxLogLines) per event. Trimming the front of a List on every line shifts the whole remainder and dominated apply on verbose runs; trimming now happens in blocks of the new trimChunk, cutting the cost from ~21.6 µs to ~0.18 µs per log line. In exchange the limit became soft: the length may exceed maxLogLines by up to trimChunk between two trims.
  • WorkflowEvent.fromJson: now honours what it already documented. The direct casts (as String?, as num, as Map?) threw TypeError on any type mismatch; inside the server that silently dropped the whole event — the opposite of the intended forward compatibility. Each field now degrades on its own: a non-numeric entry in job_ids is skipped without discarding the batch, and fromJson is safe to call directly, outside the server's try.
  • WorkflowRunState.byStatus now returns List<JobState> — a snapshot taken at call time — instead of the lazy view returned by where. That view rescanned on every read, which made elementAt(i) quadratic: the itemCount + itemBuilder pattern of a ListView.builder took 8.4 s to walk 50k jobs, against ~1 ms now. Being a live view over jobs, it also changed size between itemCount and itemBuilder, and threw ConcurrentModificationError when an event was applied mid-iteration. Not a breaking change: List is a subtype of Iterable.
  • WorkflowServer no longer lets a pong advance the deduplication cursor. A pong is answered out of band, ahead of whatever the plugin still has queued, so when it carried a real sequence number the cursor jumped past every event still in flight and those events were dropped for good — 36 of 50 in the measured case, triggered by nothing more than calling ping(). Pongs are now delivered outside the ordered stream, like hello, which also protects against a plugin that still numbers them. See SPEC.md.
  • Example: warns on stderr when SNAKEMAKE_LOGGER_DART_TOKEN is unset, since the server then accepts any local connection.

0.1.0 #

  • Initial release.
  • WorkflowServer: embedded WebSocket server (shelf), bound to 127.0.0.1, token authentication, deduplication by seq and a replay request on every reconnection.
  • workflow_events.dart: typed models of the Snakemake events (sealed classes; unknown types become UnknownEvent).
  • WorkflowRunState: event reducer → queryable run state (jobs, progress, DAG, logs, errors).
  • SnakemakeRunner: launches and owns the snakemake process.
  • Example example/snakemake_bridge_example.dart: headless monitor for testing in the terminal.
0
likes
160
points
71
downloads

Documentation

API reference

Publisher

verified publisherkarlaycosta.com.br

Weekly Downloads

Embed a real-time Snakemake workflow monitor in a Dart desktop app: WebSocket server, typed event models, state reducer and process launcher.

Repository (GitHub)
View/report issues

Topics

#snakemake #websocket #workflow #bioinformatics #desktop

License

MIT (license)

Dependencies

shelf, shelf_web_socket, web_socket_channel

More

Packages that depend on snakemake_bridge