Make full applySeed execution bounded on D1 #2839
oiwa-coder
started this conversation in
Ideas
Replies: 0 comments
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Uh oh!
There was an error while loading. Please reload this page.
Summary
The latest released EmDash still performs enough sequential database work during a realistic fresh seed to exceed a bounded Cloudflare Worker subrequest budget, even though the wide-schema problem fixed by #2128 is already resolved.
I would like to contribute a measured optimization for the remaining
applySeed()phases, starting with fresh content entries. Before writing it, I want to confirm whether maintainers prefer batching inside one setup request or a bounded, resumable seed protocol.Reproduction and measurements
The seed is representative of a corporate site rather than a huge import:
Using query instrumentation locally produced approximately:
These measurements were captured from our deployed integration. Inspection of the latest released implementation confirms that the remaining content, taxonomy, menu, redirect, widget, and section phases still use the same sequential processing shape.
These are SQL executions, not yet a count of raw D1 binding calls or
D1Database.batch()calls. A useful upstream regression should record both so that combining statements into one round trip is visible separately from reducing the statements themselves.In a Workers for Platforms deployment where the authenticated bootstrap dispatch was bounded to 1,000 subrequests, two setup attempts failed after about 23–24 seconds with the generic
SEED_ERROR. Raising the consumer-side limit is a workable short-term mitigation, but this amount of sequential work for 92 entries suggests there is still an upstream optimization opportunity.Existing work I found
SELECTcalls into one D1batch()round trip.Those changes do not batch the seed mutations themselves. Current
applySeed()still walks taxonomies, terms, bylines, content entries, menus, redirects, widgets, and sections through sequential loops. The content path performs per-entry existence checks and then repository operations for the entry, revisions, taxonomies, bylines, media usage, and publication state.Related: explicit seed ownership
Discussion #1044 identifies a related problem for embedded EmDash installations: middleware auto-seeding can run before an embedder's explicit
applySeed()call.Our integration uses the bundled
seed.json, so both passes use the same schema and do not cause the incorrect-schema failure described there. However, our authenticated bootstrap calls/_emdash/api/setup, whose handler explicitly applies the seed after runtime initialization may already have auto-seeded it. The second pass skips existing content instead of inserting it twice, but it still performs conflict lookups and leaves ownership of initialization ambiguous.If
applySeed()gains batching or resumable phases, embedded platforms also need a supported way to declare who owns initialization—for example,autoSeed: false. Otherwise middleware may begin a seed before the platform-owned bootstrap or recovery process does.This is separable from the mutation-batching implementation, but the two contracts should be designed together: one owner should start the seed, and that owner should be able to execute it within bounded Worker invocations.
Proposed direction
Add a fresh-seed fast path with a query-count regression around a representative multi-collection seed:
onConflictbehavior; keep the optimized path limited to cases where its semantics are unambiguous.I would start with content entries as one focused PR, with an explicit before/after ceiling, rather than attempting to rewrite every seed phase at once.
Questions
applySeed()remain a single-request operation, or should large seeds have a supported resumable/chunked execution path?applySeed()call the sole initialization owner, as proposed in Embedding API: opting out of middleware auto-seed #1044?All reactions