@indigoai-us/hq-cloud 6.16.66 → 6.16.67
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/cli/share.test.js
CHANGED
|
@@ -2075,6 +2075,61 @@ describe("share", () => {
|
|
|
2075
2075
|
vi.mocked(uploadFile).mockResolvedValue({ etag: '"upload-etag"' });
|
|
2076
2076
|
}
|
|
2077
2077
|
});
|
|
2078
|
+
it("defers a file that vanishes between upload and journal as a diagnostic error", async () => {
|
|
2079
|
+
// Production (2026-09-19 02:02:57Z, agent Alpha, company equi):
|
|
2080
|
+
// workers/thread-police/data/run.lock was PUT, then deleted by the
|
|
2081
|
+
// worker before updateEntry's lstat. PrematureJournalEntryError is
|
|
2082
|
+
// correct (nothing journaled), but the catch used to emit a hard
|
|
2083
|
+
// type:"error" so hq-sync-runner exited 2. Same diagnostic deferral
|
|
2084
|
+
// as a rate-limited PUT; the next pass re-plans the key.
|
|
2085
|
+
const companyRoot = path.join(tmpDir, "companies", "acme");
|
|
2086
|
+
fs.mkdirSync(companyRoot, { recursive: true });
|
|
2087
|
+
const relativePath = "workers/thread-police/data/run.lock";
|
|
2088
|
+
const testFile = path.join(companyRoot, relativePath);
|
|
2089
|
+
fs.mkdirSync(path.dirname(testFile), { recursive: true });
|
|
2090
|
+
fs.writeFileSync(testFile, "pid");
|
|
2091
|
+
const journalPath = path.join(stateDir, "sync-journal.acme.json");
|
|
2092
|
+
seedJournalAt(journalPath, {
|
|
2093
|
+
version: "1",
|
|
2094
|
+
lastSync: new Date(Date.now() - 60_000).toISOString(),
|
|
2095
|
+
files: {},
|
|
2096
|
+
});
|
|
2097
|
+
vi.mocked(uploadFile).mockReset();
|
|
2098
|
+
let putAttempted = false;
|
|
2099
|
+
vi.mocked(uploadFile).mockImplementationOnce(async (_ctx, localPath, key) => {
|
|
2100
|
+
expect(key).toBe(relativePath);
|
|
2101
|
+
putAttempted = true;
|
|
2102
|
+
fs.unlinkSync(localPath);
|
|
2103
|
+
return { etag: '"upload-etag"' };
|
|
2104
|
+
});
|
|
2105
|
+
try {
|
|
2106
|
+
const events = [];
|
|
2107
|
+
const result = await share({
|
|
2108
|
+
paths: [testFile],
|
|
2109
|
+
company: "acme",
|
|
2110
|
+
vaultConfig: mockConfig,
|
|
2111
|
+
hqRoot: tmpDir,
|
|
2112
|
+
onEvent: (e) => events.push(e),
|
|
2113
|
+
});
|
|
2114
|
+
expect(putAttempted).toBe(true);
|
|
2115
|
+
expect(result.filesUploaded).toBe(0);
|
|
2116
|
+
expect(result.filesSkipped).toBeGreaterThanOrEqual(1);
|
|
2117
|
+
expect(journalAt(journalPath).files[relativePath]).toBeUndefined();
|
|
2118
|
+
const errorEvents = events.filter((e) => e.type === "error");
|
|
2119
|
+
expect(errorEvents).toHaveLength(1);
|
|
2120
|
+
expect(errorEvents[0]).toMatchObject({
|
|
2121
|
+
type: "error",
|
|
2122
|
+
diagnostic: true,
|
|
2123
|
+
path: relativePath,
|
|
2124
|
+
message: expect.stringContaining("PrematureJournalEntryError"),
|
|
2125
|
+
});
|
|
2126
|
+
expect(events.some((e) => e.type === "error" && e.diagnostic !== true)).toBe(false);
|
|
2127
|
+
}
|
|
2128
|
+
finally {
|
|
2129
|
+
vi.mocked(uploadFile).mockReset();
|
|
2130
|
+
vi.mocked(uploadFile).mockResolvedValue({ etag: '"upload-etag"' });
|
|
2131
|
+
}
|
|
2132
|
+
});
|
|
2078
2133
|
it("defers a breaker-tripped upload batch as one diagnostic company error", async () => {
|
|
2079
2134
|
// Production (2026-09-18 16:03Z brickcraft, 16:05Z mhi-media): the
|
|
2080
2135
|
// RateLimitBreaker tripped, remaining GET presigns all threw
|