Skip to content

Fix loader lifecycle and promise adapter selection - #82

Merged
mcg-web merged 2 commits into
overblog:masterfrom
simPod:fix/promise-adapter-selection
Aug 18, 2026
Merged

mcg-web merged 2 commits into
overblog:masterfrom
simPod:fix/promise-adapter-selection

Conversation

@simPod

@simPod simPod commented Aug 18, 2026 •

Copy link
Copy Markdown
Contributor

Summary

  • Track loader instances and promise adapters with weak references.
  • Keep loaders strongly referenced only while they have queued work.
  • Resolve each promise with its producing adapter, including mixed-adapter use.
  • Settle adapter callbacks created by dispatch before no-argument await() returns.

Lifecycle Decision

DataLoader::await() must dispatch queued loaders, settle the dispatched work,
and use the adapter that owns the supplied promise. A strong global registry
retained every loader and its cache, and selecting the first loader could use
the wrong adapter in mixed-adapter applications.

Use weak references for loader instances and promise ownership. Retain a loader
strongly only while it has queued work, and remove it when dispatch starts. For
promises without recorded ownership, select a live adapter that recognizes the
promise before using a compatibility fallback. Drain the owning adapter after
dispatch so no-argument await() does not return before callbacks settle. A
loader destructor cancels only its own queued promises.

Idle and dispatched loaders can be collected, inline temporary loaders remain
alive until dispatch, and queued work remains retained until the application
dispatches or cancels it.

@simPod
simPod force-pushed the fix/promise-adapter-selection branch from a96ff7c to 1dfdbfa Compare August 18, 2026 06:54
@simPod

simPod commented Aug 18, 2026 •

Copy link
Copy Markdown
Contributor Author

Blackfire Performance Profile

The CLI workload creates and immediately awaits 2,000 temporary DataLoader
instances with the Webonyx synchronous promise adapter.

Revision Wall time, median CPU time, median Memory
Previous dataloader-php master 0ee3ee2 2.11 s 2.10 s 4.17 MB
Changed loader registry 114 ms 90.9 ms 1.20 MB

This is an 18.5x wall-time improvement, 23.1x lower CPU time, and 71.2% lower
memory use. The medians use three alternating Blackfire profiles per revision.

The profile targets the loader lifecycle path changed in this PR. Xdebug and
PCOV were loaded for both revisions, so the relative difference is the useful
result.

@simPod
simPod force-pushed the fix/promise-adapter-selection branch from 1dfdbfa to 2fac2bc Compare August 18, 2026 06:59
@simPod
simPod marked this pull request as draft August 18, 2026 07:00
@simPod
simPod force-pushed the fix/promise-adapter-selection branch from 2fac2bc to 58a17b1 Compare August 18, 2026 07:05
@simPod
simPod marked this pull request as ready for review August 18, 2026 07:08
@simPod
simPod force-pushed the fix/promise-adapter-selection branch from 58a17b1 to 872c41f Compare August 18, 2026 07:24
@simPod
simPod force-pushed the fix/promise-adapter-selection branch from 872c41f to b955119 Compare August 18, 2026 07:57
Context: Dispatch can enqueue adapter callbacks after the pre-dispatch drain.

Decision: Drain the owning adapter again after each queue dispatch.

Consequences: No-argument await settles dispatched batches before returning.
@mcg-web
mcg-web merged commit c47da1b into overblog:master Aug 18, 2026
9 checks passed
@simPod
simPod deleted the fix/promise-adapter-selection branch August 18, 2026 12:20
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