Skip to content

feat(kida,store,query)!: attach tasks to the signals they fill - #222

Merged
dangreen merged 1 commit into
mainfrom
feat/signal-tasks
Aug 31, 2026
Merged

dangreen merged 1 commit into
mainfrom
feat/signal-tasks

Conversation

@dangreen

Copy link
Copy Markdown
Member

The tasks pool made waiting imprecise by construction: waitTasks(pool) drained everything in flight, so a wait captured its neighbours' requests along with its own — measured in the streaming SSR prototype as a header segment ready at 168 ms but written at 318 ms, held by an unrelated request. This reworks tasks to live on the signals they fill, and derives "the tasks of a signal" the way agera derives mount state: never stored, collected by walking the dependency graph on demand.

task($to, taskOrFn) attaches a task to the signal or signals it fills — a task filling two stores attaches to both. waitTasks($of) collects the tasks of the signal and of every signal it depends on and drains them wave by wave, re-collecting after each one, so a task spawned by a task and a dependency linked by a settled value are awaited too. None of it touches mount machinery: tasks on plain signals work, mountable/onStart stay just the convenient way to start them, and a shared signal already in flight is visible to a second reader through its own pool.

In kida the walk doubles one Set as the queue and the visited set (a set iterator visits values appended during iteration), waves ride Promise.all over derived promises that cannot reject, and a pool entry removes itself before any wait wakes up. In @nano_kit/store, dehydrate starts the stores through one computed root and waits exactly them. In @nano_kit/query, baseQuery binds the client's task to the query's $data and mutation binds it to [$data, $error, $loading], so everything a query runs — fetches, retryOnError retries, persistence IO — lands in its own pool, and mutations keep the coverage the shared pool used to give them. The tasks() and ssr() settings are gone: queries track themselves, and hydratable() is the whole SSR setting.

Size pins move down along the chain: kida 4.6 → 4.55 kB brotli (4.95 gzip holds with room to spare), store 6.35 → 6.3 gzip and 5.85 → 5.8 brotli, query 4.7 → 4.65 gzip and 4.3 → 4.25 brotli; the mutations-only set pays 1.7 → 1.75 brotli for the mutation tracking while its gzip pin holds. hasTasks is deliberately not exported yet — its only consumer is the streaming renderer, and it arrives with that package.

Lint, tsc --noEmit, 75 kida, 55 store and 164 query tests, and size-limit across the whole chain are green.

@codecov

codecov Bot commented Aug 28, 2026 •

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 82.80%. Comparing base (5b15d22) to head (4430a70).

Additional details and impacted files
@@            Coverage Diff             @@
##             main     #222      +/-   ##
==========================================
+ Coverage   82.48%   82.80%   +0.31%     
==========================================
  Files          99       98       -1     
  Lines        2472     2471       -1     
  Branches      521      523       +2     
==========================================
+ Hits         2039     2046       +7     
+ Misses        322      315       -7     
+ Partials      111      110       -1     

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@dangreen
dangreen force-pushed the feat/signal-tasks branch 4 times, most recently from 316c38c to 29e3a50 Compare August 31, 2026 21:33
@dangreen
dangreen marked this pull request as ready for review August 31, 2026 21:33
Tasks now live on signal nodes and are collected by walking the dependency graph: `task($to, taskOrFn)` attaches a task to the signal or signals it fills, and `waitTasks($of)` drains the tasks of a signal and of everything it depends on, wave by wave. Queries and mutations attach their tasks themselves, and `dehydrate` waits exactly the stores it starts.

BREAKING CHANGE: the tasks pool is gone — `TasksPool$`, `TasksRunner$`, `tasksRunner`, `addTask`,
`waitCurrentTasks` and `taskPromise` are removed, `waitTasks` takes a signal instead of a pool, and
the `tasks()` and `ssr()` query settings are removed: `hydratable()` is the whole SSR setting.
@dangreen
dangreen merged commit 841acd1 into main Aug 31, 2026
10 checks passed
@dangreen
dangreen deleted the feat/signal-tasks branch August 31, 2026 23:03
@github-actions github-actions Bot mentioned this pull request Aug 31, 2026
dangreen added a commit that referenced this pull request Sep 28, 2026
…nd use `hydratable()` in the shared stores (#270)

The store factories called `queryKey()` on every run, and every injection context runs them again, so each server request registered another builder under the same name: the development build warned that the cache key shard was already registered from the second request on, and the module-level set of builders grew with every request. The keys are now module-level constants typed like the event-board ones, and `query()` takes its types from them.

The shared `stores-di/query.ts` of rick-and-morty and event-board still imported the `ssr` setting removed in #222. The examples themselves already use `hydratable()`, and a sync from `common` would have brought the removed import back.
dangreen added a commit that referenced this pull request Sep 28, 2026
… link `hydratable()` in its SSR rows

Stacked on the docs update, Agent Skills shared `order: 2` with the comparison page and came first by name: it moves to 3 and keeps the Store label of the pager, which the comparison page no longer needs. The `ssr()` setting and its section are gone since #222, so the SSR hydration row and the `@nanostores/query` section link `hydratable()` instead.
dangreen added a commit that referenced this pull request Oct 4, 2026
… link `hydratable()` in its SSR rows

Stacked on the docs update, Agent Skills shared `order: 2` with the comparison page and came first by name: it moves to 3 and keeps the Store label of the pager, which the comparison page no longer needs. The `ssr()` setting and its section are gone since #222, so the SSR hydration row and the `@nanostores/query` section link `hydratable()` instead.
dangreen added a commit that referenced this pull request Oct 7, 2026
… link `hydratable()` in its SSR rows

Stacked on the docs update, Agent Skills shared `order: 2` with the comparison page and came first by name: it moves to 3 and keeps the Store label of the pager, which the comparison page no longer needs. The `ssr()` setting and its section are gone since #222, so the SSR hydration row and the `@nanostores/query` section link `hydratable()` instead.
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