Skip to content

refactor(): route model calls through _invoke - #325

Merged
agviegas merged 1 commit into
ThatOpen:mainfrom
ShaMan123:refactor/model-invoke
Oct 11, 2026
Merged

agviegas merged 1 commit into
ThatOpen:mainfrom
ShaMan123:refactor/model-invoke

Conversation

@ShaMan123

@ShaMan123 ShaMan123 commented Oct 11, 2026 •

Copy link
Copy Markdown
Contributor

Part of a stack of six PRs that replaces #305. The branches live in a fork, so GitHub can't chain them: every PR is based on main, and the diff of each one includes the PRs below it. Each PR names the commits that are its own and links a comparison that shows only those. They are meant to merge in the order below, and PRs 2 to 6 stay drafts until the one before them is in.

The work. All model state, on both threads, is keyed by the consumer's modelId, and a modelId can be reused. Late async work of a model that was disposed or replaced (a worker reply, queued tiles, a material transfer, a progress event, an in-flight dispose) therefore lands on the next model loaded under the same ID. The stack gives each model an internal uid that is never reused and routes everything by it, adds load({ signal }) (#173), and types the messages between the threads, where most of the bugs it fixes were hidden behind any.

The stack, bottom to top, in merge order:

  1. refactor(): route model calls through _invoke #325 refactor(): route model calls through _invoke: mechanical groundwork, no behavior change
  2. fix(): type calls to a model's worker, rebuild what the worker copies #326 fix(): type calls to a model's worker, rebuild what the worker copies
  3. feat(): load abort signal + harden the message layer #327 feat(): load abort signal + harden the message layer
  4. fix(): key models by an internal uid, dispose synchronously #328 fix(): key models by an internal uid, dispose synchronously: the core fix
  5. fix(edit): key editor state by the model's uid #329 fix(edit): key editor state by the model's uid
  6. refactor(): type the requests workers send to the main thread #330 refactor(): type the requests workers send to the main thread

Every commit in the stack type-checks and passes the test suite on its own, and each PR builds. The top of the stack matches #305's branch merged with today's main, apart from one fix that merge needs (see PR 4) and two reworded lines.


This PR's own diff: all of it. It is the bottom of the stack.

Description

PR 1 of 6. Every call to a model's worker-side counterpart now goes through FragmentsModel._invoke(method, args) instead of spelling out model.threads.invoke(model.modelId, method, args) at each of the 89 call sites. The model becomes the one place that knows how its worker is addressed.

Nothing else changes here. The PRs above build on it: PR 2 types _invoke, and PR 4 switches what it addresses from modelId to uid in one line.

It is mechanical: 14 files, +165/−309, no test changes, and the suite passes as it does on main (143 tests).
A prerequisite to #330 .

One behavior detail. The four calls EditManager makes to a model's delta model now go through the delta model itself, looked up with _getDeltaModel(), instead of invoking deltaModelId. If that model is no longer in models.list, the call reads as "no edits". Before, the request was sent for a model that isn't loaded.

Additional context

_invoke doesn't exist on main. In #305 it arrived inside the uid commit, so none of the typing could merge ahead of it. This commit is new: it lifts those hunks out and routes by modelId for now.

Rebase next PRs

git fetch upstream
git switch refactor/typed-worker-requests
git rebase --update-refs --onto upstream/main <branch-that-just-merged>
git push --force-with-lease origin <the remaining branches>
gh pr ready <next PR>


What is the purpose of this pull request?

  • Bug fix
  • New Feature
  • Documentation update
  • Other

Before submitting the PR, please make sure you do the following:

  • Check that there isn't already a PR that solves the problem the same way to avoid creating a duplicate.
  • Follow the Conventional Commits v1.0.0 standard for PR naming (e.g. feat(examples): add hello-world example).
  • Provide a description in this PR that addresses what the PR is solving, or reference the issue that it solves (e.g. fixes #123).
  • Ideally, include relevant tests that fail without this PR but pass with it.

🤖 Generated with Claude Code

Every call to a model's worker goes through FragmentsModel._invoke()
instead of spelling out threads.invoke(model.modelId, …) at each of the
89 call sites. The model is now the one place that knows how its worker
is addressed, which is what the typing of these calls and the internal
uid build on.

Mechanical, with one behavior detail: the calls to a delta model go
through the delta model itself, looked up with _getDeltaModel(), instead
of invoking its modelId. A deltaModelId whose model is no longer loaded
now reads as "no edits" where it sent a request for a missing model.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

@ShaMan123 ShaMan123 left a comment

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ready

@agviegas
agviegas merged commit 6b04295 into ThatOpen:main Oct 11, 2026
1 check 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.

2 participants