Skip to content
Caleb Buxton edited this page Jul 5, 2026 · 6 revisions

duckling wiki

Research and historical planning docs for the duckling gem (time/entity extraction via duckling wrapped in Rust via Magnus). Live, actionable work is tracked as GitHub issues and in the roadmap (kept in the repo, not here, so it stays close to the code it tracks) — this wiki holds the research and terrain-mapping that grounded those decisions.

Issue #1 — Ship duckling gem (time extraction via Magnus + wafer-inc-duckling)

Shipped as 0.2.0. Research (API surface, build wiring, type-mapping strategy, test coverage, FFI risk analysis) and the fully-executed implementation plan (kept for historical record). Full reading order and settled decisions: home-issue-1.

Issue #57 — Stop Duckling.parse from blocking async reactor Fibers

In progress. Duckling.parse is a synchronous Rust FFI call that holds Ruby's GVL for its full duration, which stalls sibling Fibers inside an Async::Reactor (e.g. Falcon) — test/falcon_fiber_blocking_test.rb proves this empirically. The headline finding from the research: releasing the GVL alone does not fix it — an empirical spike confirmed the fix needs both a raw GVL release (rb_thread_call_without_gvl, since Magnus 0.8.2 has no safe wrapper for it) and a genuine background Thread spawn, dispatched thread-per-call rather than through a persistent worker pool. Concrete implementation plan, acceptance criteria, and the benchmark requirement: issue #64 (research-tracking issue: #57).

Issue #77 — Spike: does rb_nogvl + RB_NOGVL_OFFLOAD_SAFE obviate the Thread wrapper?

Spike completed. Spiked whether calling the lower-level rb_nogvl directly with flags: RB_NOGVL_OFFLOAD_SAFE lets Ruby 3.4's Fiber::Scheduler#blocking_operation_wait auto-offload the blocking duckling::parse call, obviating the Ruby-level Thread.new wrapper on Ruby 3.4+. Verdict: CONFIRMED on Ruby 3.4+ (under a hand-rolled scheduler) and Ruby 4.0+ (under the real async/io-event stack). Full spike details: spike-does-rb-nogvl-offload-safe-obviate-thread-wrapper (methodology & data: research-rb-nogvl-offload-safe-spike).

Settled Decisions (cross-issue)

  • duckling on crates.io — Published as duckling = "0.4".
  • Symbol keys and Symbol values throughout:body, :dim, :value, :type, :grain, etc.
  • Manual Magnus mapping, not serde_magnusmagnus = "0.8" (not "0.9", which was never published to crates.io).
  • Source gem, not pre-compiled binaries — for now; see #43 on the roadmap.
  • Never stash a bare magnus::Value (or anything wrapping one) across a Magnus call boundary — a past incident here caused a real GC-safety segfault; this rule now shapes how off-GVL FFI payloads are designed (see research-magnus-rb-sys-gvl-release-implementation-sketch).

For what's open and being worked on next, see the roadmap.

Clone this wiki locally