

























@@ -481,6 +481,45 @@ describe("skill upload store", () => {
481481expect(next.uploadId).not.toBe(committed.uploadId);
482482await expectMissingPath(path.join(rootDir, committed.uploadId));
483483});
484+485+it("clears the orphaned idempotency pointer when re-begin hits corrupt metadata before the active cap throws", async () => {
486+const rootDir = await makeTempDir();
487+const store = createSkillUploadStore({ rootDir });
488+const idempotencyKey = "orphan-pointer-key";
489+490+// begin with an idempotency key → writes the upload plus its idempotency pointer
491+const first = await store.begin({
492+kind: "skill-archive",
493+slug: "demo-skill",
494+sizeBytes: 8,
495+ idempotencyKey,
496+});
497+const idempotencyDir = path.join(rootDir, "idempotency");
498+const pointerFiles = await fs.readdir(idempotencyDir);
499+expect(pointerFiles).toHaveLength(1);
500+const pointerFile = pointerFiles[0];
501+502+// corrupt the upload metadata so readRecordIfPresent() returns null on re-begin
503+// (this also drops the upload from the active-upload count)
504+await fs.rm(path.join(rootDir, first.uploadId, "metadata.json"), { force: true });
505+506+// saturate the active-upload cap with unrelated uploads
507+for (let i = 0; i < MAX_ACTIVE_SKILL_UPLOADS; i++) {
508+await store.begin({ kind: "skill-archive", slug: `filler-${i}`, sizeBytes: 8 });
509+}
510+511+// re-begin the same key: the pointer still matches, but its upload metadata is gone,
512+// so the corrupt-metadata branch runs and then the active-upload cap throws before the
513+// pointer would be rewritten. The pointer must have been cleared by that branch — not
514+// left stranded pointing at the now-deleted (ghost) uploadId.
515+await expectUploadError(
516+store.begin({ kind: "skill-archive", slug: "demo-skill", sizeBytes: 8, idempotencyKey }),
517+"too many active skill uploads",
518+);
519+520+const remaining = await fs.readdir(idempotencyDir).catch(() => [] as string[]);
521+expect(remaining).not.toContain(pointerFile);
522+});
484523});
485524486525function toLintErrorObject(value: unknown, fallbackMessage: string): Error {
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。