Skip to content

ariadne: generic async URI resolver — (fetch uri) / (fetch-async uri) (§13.8) - #475

Merged
transfix merged 1 commit into
masterfrom
feat/ari-async-resolve
Sep 29, 2026
Merged

transfix merged 1 commit into
masterfrom
feat/ari-async-resolve

Conversation

@transfix

Copy link
Copy Markdown
Owner

Adds a scheme-agnostic async resolver so an ari program can load any registered URI scheme (file/state/cvc/http) without blocking the scheduler thread — the DSL surface for "all ari-generated URI requests async". Builds on PR-A (#474)'s park/future machinery.

(get-attr (fetch "state://sys.cfg?value") "body")   ; any scheme, async, no thread blocked
(await (fetch-async "file:///x.ari"))                ; a future you can await

What it does

launch_uri_fetch runs the synchronous cvc::ariadne::resolve() on a compute-pool worker (off the scheduler thread) and posts the marshalled result to a unique #-reply channel — the same launch shape as launch_http_fetch. Two verbs reuse PR-A's park/future primitives:

  • (fetch-async URI [BASE]) → a future handle (await it, or msg-recv it).
  • (fetch URI [BASE]) → transparent: self-parks and returns the dict directly.

Reply dict: { ok body(bytes) url error } (scheme-agnostic — no HTTP status/headers; use http-get for those). The register gate is split so (fetch*) needs no HTTP backend (works over any registered scheme, even in a curl-less build) while (http-get*) still require cvc::net::have_http_backend(). resolve() is app-free with its own barrier; the worker wraps it and always posts a dict, so a waiter never hangs.

Scoping (the honest answer to "all ari URI requests async")

The other ari-generated URI requests stay synchronous by design: import:/load:/include: resolve at load time, off the draw walk (roadmap §13.8 — sync is legal there), and scene source:{uri:} is a one-shot at scene setup (not per-frame). So nothing ari-generated blocks the render thread today; a DSL program that wants async loading uses (fetch). An async scene source:{uri:} realize (so a large remote asset doesn't block scene setup) is a natural follow-up (it needs an async resolve_to_file + temp-file lifetime across the hop).

Tests

ariadne_runtime_test (AriadneNetIntrinsics, offline): (fetch) transparently resolves a canned custom scheme with the bytes body threaded in; (await (fetch-async …)) resolves the future. Full ariadne_runtime_test 106, 0/20 flaky.

Next in the arc: render-pass park budget + safety (PR-C — residents currently run with no time budget).

… (§13.8)

Add a scheme-agnostic async resolver so an ari program can load ANY registered
URI scheme (file/state/cvc/http) without blocking the scheduler thread — the DSL
surface for "all ari-generated URI requests async".

net_intrinsics.cpp: launch_uri_fetch runs the SYNCHRONOUS cvc::ariadne::resolve()
on a compute-pool worker (OFF the scheduler thread) and posts the marshalled result
to a unique '#'-reply channel — the same launch shape as launch_http_fetch, but for
arbitrary URIs. Two verbs reuse the PR-A park/future machinery:
  (fetch-async URI [BASE]) -> a future handle (await it, or msg-recv it)
  (fetch URI [BASE])       -> TRANSPARENT: self-parks, returns the dict directly
The reply dict is { ok  body(bytes)  url  error } (scheme-agnostic: no HTTP
status/headers). So (get-attr (fetch uri) "body") reads as one expression.

The register gate is split so (fetch*) does NOT require an HTTP backend — it works
over any registered scheme and is useful in a curl-less build — while (http-get*)
still gate on cvc::net::have_http_backend(). resolve() is app-free and has its own
try/catch barrier; the worker additionally wraps it and always posts a dict, so a
waiter never hangs.

The other ari-generated URI requests stay synchronous by design: import:/load:/
include: resolve at LOAD time (off the draw walk, where sync is legal), and scene
source:{uri:} is a one-shot at scene setup (not per-frame) — so nothing
ari-generated blocks the render thread today. A DSL program that wants async
loading uses (fetch). An async scene source:{uri:} realize (so a large remote asset
doesn't block scene setup) is a follow-up.

Tests (ariadne_runtime_test AriadneNetIntrinsics, offline): (fetch) transparently
resolves a canned custom scheme with the bytes body threaded in; (await
(fetch-async …)) resolves the future. Full ariadne_runtime_test 106, 0/20 flaky.
@transfix
transfix merged commit 638dc57 into master Sep 29, 2026
13 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant