chadtmiller.com/pds.js
An atproto PDS in JavaScript, for Cloudflare Workers and Node
0
0
// Orphan cleanup deletes blobs the link table says nothing points at. A space
// record is a reference the table can be missing — spaces turned on after the
// records existed, a link write that failed — so the guard that cross-checks
// record content has to read space records as well as public ones.
import { describe, expect, it } from 'vitest';
import { PersonalDataServer } from '../packages/core/src/pds.js';
import { createFakeSpaceStorage } from './helpers/fake-space-storage.js';
const DID = 'did:plc:reapaccount23456789012';
const SPACE = 'at://did:plc:authority/space/com.example.forum/general';
const BLOB_CID = 'bafkreiaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa';
/** @param {string} cid */
function postWith(cid) {
return {
$type: 'com.example.post',
image: { $type: 'blob', ref: { $link: cid }, mimeType: 'image/png' },
};
}
/**
* A PDS holding one blob that nothing in the public repo references, and one
* space record that does.
* @param {{withSpaces: boolean}} opts
*/
function createPds({ withSpaces }) {
/** @type {string[]} */
const deleted = [];
const spaceRecord = {
space: SPACE,
collection: 'com.example.post',
rkey: 'a',
value: postWith(BLOB_CID),
};
const pds = new PersonalDataServer({
actorStorage: /** @type {any} */ ({
async getDid() {
return DID;
},
async listAllRecords() {
return [];
},
async getRecord() {
return null;
},
// The link table has never heard of the space record.
async getOrphanedBlobs() {
return [BLOB_CID];
},
async linkBlobToRecord() {},
async deleteBlob(/** @type {string} */ cid) {
deleted.push(cid);
},
}),
sharedStorage: /** @type {any} */ ({}),
blobs: /** @type {any} */ ({
async delete(/** @type {string} */ _did, /** @type {string} */ cid) {
deleted.push(cid);
},
}),
spaceStorage: withSpaces
? createFakeSpaceStorage({
spaces: [{ uri: SPACE }],
records: { [SPACE]: [{ ...spaceRecord, cid: 'bafyspace' }] },
})
: undefined,
jwtSecret: 'test-secret',
});
return { pds, deleted };
}
describe('orphan reaping with permissioned data', () => {
it('spares a blob only a space record references', async () => {
const { pds, deleted } = createPds({ withSpaces: true });
await pds.reapOrphanedBlobs(DID, Date.now() + 1000);
expect(deleted).toEqual([]);
});
it('counts a space record among the referenced blobs', async () => {
const { pds } = createPds({ withSpaces: true });
const refs = await pds.collectReferencedBlobs();
expect(refs).toEqual([
{
cid: BLOB_CID,
recordUri: `${SPACE}/${DID}/com.example.post/a`,
recordTime: null,
},
]);
});
it('reaps the same blob when the account holds no spaces', async () => {
const { pds, deleted } = createPds({ withSpaces: false });
await pds.reapOrphanedBlobs(DID, Date.now() + 1000);
expect(deleted).toContain(BLOB_CID);
});
});