Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 19 additions & 0 deletions .changeset/seed-replayer-skipped.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
---
"@objectstack/runtime": patch
---

feat(runtime): seed-replayer reports `skipped` so hosts can stamp seed-once on progress

The `seed-replayer` kernel service returned `{ inserted, updated, errors }` but
not `skipped`. A cloud host therefore could not tell an **all-skip replay**
(the env's seed data is already present — a no-op) apart from the
zero-summary early-returns that never ran the loader (no organization, no
metadata service, no datasets). Both looked like `inserted = updated = 0`, so
the host could not safely stamp its seed-once record for the all-skip case and
re-ran the full remote replay on every cold boot.

Add `skipped: result.summary.totalSkipped` to the replayer's return; the
early-returns report `skipped: 0`. This lets a host (cloud#853's
`decideSeedStamp`) stamp on progress — including an all-skip replay — while
still declining to stamp a genuine no-loader zero-summary. Additive and
backward compatible; existing consumers ignore the new field.
12 changes: 9 additions & 3 deletions packages/runtime/src/app-plugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -765,17 +765,17 @@ export class AppPlugin implements Plugin {
const metadataNow = ctx.getService('metadata') as IMetadataService | undefined;
const loggerRef = ctx.logger;
const replayer = async (organizationId: string) => {
if (!organizationId) return { inserted: 0, updated: 0, errors: [] as any[] };
if (!organizationId) return { inserted: 0, updated: 0, skipped: 0, errors: [] as any[] };
const md = metadataNow ?? (ctx.getService('metadata') as IMetadataService | undefined);
if (!md) {
loggerRef.warn('[seed-replayer] metadata service unavailable');
return { inserted: 0, updated: 0, errors: [] as any[] };
return { inserted: 0, updated: 0, skipped: 0, errors: [] as any[] };
}
const datasetsNow = (() => {
try { return kernel?.getService?.('seed-datasets'); } catch { return merged; }
})() ?? merged;
if (!Array.isArray(datasetsNow) || datasetsNow.length === 0) {
return { inserted: 0, updated: 0, errors: [] as any[] };
return { inserted: 0, updated: 0, skipped: 0, errors: [] as any[] };
}
const seedLoader = new SeedLoaderService(ql, md, loggerRef);
const { SeedLoaderRequestSchema } = await import('@objectstack/spec/data');
Expand All @@ -796,6 +796,12 @@ export class AppPlugin implements Plugin {
return {
inserted: result.summary.totalInserted,
updated: result.summary.totalUpdated,
// `skipped` lets a cloud host distinguish an all-skip
// replay (data already present) from the zero-summary
// early-returns above (which never ran the loader), so
// it can stamp its seed-once record on progress rather
// than re-replaying every cold boot (cloud#853).
skipped: result.summary.totalSkipped,
errors: result.errors,
};
};
Expand Down