Skip to content

Commit af2811c

Browse files
committed
test(service-storage): open the seeded chunked sessions on the real adapter so a same-organization completion assembles
Claude-Session: https://claude.ai/code/session_01WkL6Eijt432S1Y7ekb6ovQ Co-authored-by: Claude <noreply@anthropic.com>
1 parent 4f96ff8 commit af2811c

1 file changed

Lines changed: 20 additions & 14 deletions

File tree

‎packages/services/service-storage/src/storage-routes.metadata-outage.test.ts‎

Lines changed: 20 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -320,8 +320,14 @@ describe('Storage routes: an organization change is not an outage (#22175)', ()
320320
await httpServer._getHandler(method, path)!(createMockReq({ ...req, headers: { 'x-test-as': as } }), res);
321321
return res;
322322
};
323-
/** A pending upload Alice started in `org_a`: its file row and, for the chunked door, its session. */
323+
/**
324+
* A pending upload Alice started in `org_a`: its file row and, for the
325+
* chunked door, its session — opened on the real adapter, so a completion
326+
* that gets past the doors' questions really assembles. Sets {@link uploadId}.
327+
*/
328+
let uploadId: string;
324329
const seed = async (store: StorageMetadataStore, sessionOrganization: string | undefined = 'org_a') => {
330+
uploadId = await adapter.initiateChunkedUpload('user/f1.bin', { contentType: 'application/octet-stream' });
325331
await store.createFile({
326332
id: 'f1',
327333
key: 'user/f1.bin',
@@ -331,7 +337,7 @@ describe('Storage routes: an organization change is not an outage (#22175)', ()
331337
organization_id: 'org_a',
332338
});
333339
await store.createSession({
334-
id: 'u1',
340+
id: uploadId,
335341
file_id: 'f1',
336342
key: 'user/f1.bin',
337343
filename: 'f1.bin',
@@ -430,20 +436,20 @@ describe('Storage routes: an organization change is not an outage (#22175)', ()
430436
it('answers 409 RESOURCE_CONFLICT naming the change, moves neither row, and logs the cause', async () => {
431437
const engine = createFakeEngine();
432438
await seed(mount(engine));
433-
const res = await drive('POST', CHUNKED_COMPLETE, 'alice@b', { params: { uploadId: 'u1' }, body: { parts: [] } });
439+
const res = await drive('POST', CHUNKED_COMPLETE, 'alice@b', { params: { uploadId }, body: { parts: [] } });
434440
expectOrganizationChanged(res, 'chunked completion from org_b');
435441
expect(engine._rows('sys_upload_session')[0]).toMatchObject({ status: 'in_progress' });
436442
expect(engine._rows('sys_file')[0]).toMatchObject({ status: 'pending' });
437443
expect(warnings).toHaveLength(1);
438-
expect(warnings[0]).toContain("'u1'");
444+
expect(warnings[0]).toContain(`'${uploadId}'`);
439445
expect(warnings[0]).toContain("'org_a'");
440446
expect(warnings[0]).toContain("'org_b'");
441447
});
442448

443449
it('a session row with no organization still answers 409 when its FILE row is out of reach — that write would miss', async () => {
444450
const engine = createFakeEngine();
445451
await seed(mount(engine), undefined);
446-
const res = await drive('POST', CHUNKED_COMPLETE, 'alice@b', { params: { uploadId: 'u1' }, body: { parts: [] } });
452+
const res = await drive('POST', CHUNKED_COMPLETE, 'alice@b', { params: { uploadId }, body: { parts: [] } });
447453
expectOrganizationChanged(res, 'org-less session, file in org_a');
448454
expect(engine._rows('sys_upload_session')[0]).toMatchObject({ status: 'in_progress' });
449455
expect(engine._rows('sys_file')[0]).toMatchObject({ status: 'pending' });
@@ -453,22 +459,22 @@ describe('Storage routes: an organization change is not an outage (#22175)', ()
453459
const engine = createFakeEngine();
454460
const store = mount(engine);
455461
await seed(store);
456-
await store.updateSession('u1', { expires_at: new Date(Date.now() - 60_000).toISOString() });
462+
await store.updateSession(uploadId, { expires_at: new Date(Date.now() - 60_000).toISOString() });
457463
expectOrganizationChanged(
458-
await drive('POST', CHUNKED_COMPLETE, 'alice@b', { params: { uploadId: 'u1' }, body: { parts: [] } }),
464+
await drive('POST', CHUNKED_COMPLETE, 'alice@b', { params: { uploadId }, body: { parts: [] } }),
459465
'expired, from org_b',
460466
);
461467
expect(engine._rows('sys_upload_session')[0]).toMatchObject({ status: 'in_progress' });
462468
// Control: from its own organization the uploader reaches the expiry branch, which does write.
463-
const home = await drive('POST', CHUNKED_COMPLETE, 'alice@a', { params: { uploadId: 'u1' }, body: { parts: [] } });
469+
const home = await drive('POST', CHUNKED_COMPLETE, 'alice@a', { params: { uploadId }, body: { parts: [] } });
464470
expect(home._status).toBe(410);
465471
expect(engine._rows('sys_upload_session')[0]).toMatchObject({ status: 'expired' });
466472
});
467473

468474
it('CONTROL — same organization: completes as before, and logs nothing', async () => {
469475
const engine = createFakeEngine();
470476
await seed(mount(engine));
471-
const res = await drive('POST', CHUNKED_COMPLETE, 'alice@a', { params: { uploadId: 'u1' }, body: { parts: [] } });
477+
const res = await drive('POST', CHUNKED_COMPLETE, 'alice@a', { params: { uploadId }, body: { parts: [] } });
472478
expect(res._status).toBe(200);
473479
expect(engine._rows('sys_upload_session')[0]).toMatchObject({ status: 'completed' });
474480
expect(engine._rows('sys_file')[0]).toMatchObject({ status: 'committed' });
@@ -479,7 +485,7 @@ describe('Storage routes: an organization change is not an outage (#22175)', ()
479485
const engine = createFakeEngine();
480486
await seed(mount(engine));
481487
engine._setFailing('update', true);
482-
const res = await drive('POST', CHUNKED_COMPLETE, 'alice@a', { params: { uploadId: 'u1' }, body: { parts: [] } });
488+
const res = await drive('POST', CHUNKED_COMPLETE, 'alice@a', { params: { uploadId }, body: { parts: [] } });
483489
expect(res._status).toBe(500);
484490
expect(res._json.error.code).toBe('INTERNAL');
485491
expect(res._json.error.message).toContain('Restore the data engine');
@@ -489,7 +495,7 @@ describe('Storage routes: an organization change is not an outage (#22175)', ()
489495
it('the ownership rule runs FIRST: a non-uploader acting in another organization learns nothing of it', async () => {
490496
const engine = createFakeEngine();
491497
await seed(mount(engine));
492-
const res = await drive('POST', CHUNKED_COMPLETE, 'carol@b', { params: { uploadId: 'u1' }, body: { parts: [] } });
498+
const res = await drive('POST', CHUNKED_COMPLETE, 'carol@b', { params: { uploadId }, body: { parts: [] } });
493499
expect(res._status).toBe(403);
494500
expect(res._json.error.code).toBe('PERMISSION_DENIED');
495501
expect(JSON.stringify(res._json)).not.toContain('organization');
@@ -501,7 +507,7 @@ describe('Storage routes: an organization change is not an outage (#22175)', ()
501507
it('the progress door still answers the uploader after the switch — it is a read', async () => {
502508
const engine = createFakeEngine();
503509
await seed(mount(engine));
504-
const res = await drive('GET', PROGRESS, 'alice@b', { params: { uploadId: 'u1' } });
510+
const res = await drive('GET', PROGRESS, 'alice@b', { params: { uploadId } });
505511
expect(res._status).toBe(200);
506512
expect(res._json.data.fileId).toBe('f1');
507513
expect(warnings).toEqual([]);
@@ -512,9 +518,9 @@ describe('Storage routes: an organization change is not an outage (#22175)', ()
512518
await seed(store);
513519
expect((await drive('POST', COMMIT, 'alice@b', { body: { fileId: 'f1' } }))._status).toBe(200);
514520
expect((await store.getFile('f1'))?.status).toBe('committed');
515-
const chunked = await drive('POST', CHUNKED_COMPLETE, 'alice@b', { params: { uploadId: 'u1' }, body: { parts: [] } });
521+
const chunked = await drive('POST', CHUNKED_COMPLETE, 'alice@b', { params: { uploadId }, body: { parts: [] } });
516522
expect(chunked._status).toBe(200);
517-
expect((await store.getSession('u1'))?.status).toBe('completed');
523+
expect((await store.getSession(uploadId))?.status).toBe('completed');
518524
expect(warnings).toEqual([]);
519525
});
520526
});

0 commit comments

Comments
 (0)