@atproto/sync 0.3.6 → 0.3.7
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/CHANGELOG.md +18 -0
- package/dist/firehose/index.d.ts +1 -1
- package/dist/firehose/index.d.ts.map +1 -1
- package/dist/firehose/index.js +1 -1
- package/dist/firehose/index.js.map +1 -1
- package/package.json +21 -16
- package/jest.config.cjs +0 -22
- package/src/events.ts +0 -70
- package/src/firehose/index.ts +0 -419
- package/src/index.ts +0 -3
- package/src/runner/consecutive-list.ts +0 -44
- package/src/runner/index.ts +0 -3
- package/src/runner/memory-runner.ts +0 -79
- package/src/runner/types.ts +0 -8
- package/src/util.ts +0 -16
- package/tests/firehose.test.ts +0 -197
- package/tests/runner.test.ts +0 -129
- package/tsconfig.build.json +0 -8
- package/tsconfig.build.tsbuildinfo +0 -1
- package/tsconfig.json +0 -7
- package/tsconfig.tests.json +0 -8
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,23 @@
|
|
|
1
1
|
# @atproto/sync
|
|
2
2
|
|
|
3
|
+
## 0.3.7
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- [#5099](https://github.com/bluesky-social/atproto/pull/5099) [`b43ec31`](https://github.com/bluesky-social/atproto/commit/b43ec31f247f4461725b01226885f88bd430ca07) Thanks [@matthieusieben](https://github.com/matthieusieben)! - Update TypeScript build to rely on references to composite internal projects
|
|
8
|
+
|
|
9
|
+
- [#5099](https://github.com/bluesky-social/atproto/pull/5099) [`b43ec31`](https://github.com/bluesky-social/atproto/commit/b43ec31f247f4461725b01226885f88bd430ca07) Thanks [@matthieusieben](https://github.com/matthieusieben)! - Bundle only necessary files in the NPM tarball, including the `CHANGELOG.md` and `README.md` files (if present).
|
|
10
|
+
|
|
11
|
+
- [#5099](https://github.com/bluesky-social/atproto/pull/5099) [`b43ec31`](https://github.com/bluesky-social/atproto/commit/b43ec31f247f4461725b01226885f88bd430ca07) Thanks [@matthieusieben](https://github.com/matthieusieben)! - Build with `noImplicitAny` enabled
|
|
12
|
+
|
|
13
|
+
- Updated dependencies [[`28a0b58`](https://github.com/bluesky-social/atproto/commit/28a0b588147863eaef948cd2bb8fc0f19d08cda9), [`b43ec31`](https://github.com/bluesky-social/atproto/commit/b43ec31f247f4461725b01226885f88bd430ca07), [`b43ec31`](https://github.com/bluesky-social/atproto/commit/b43ec31f247f4461725b01226885f88bd430ca07), [`b43ec31`](https://github.com/bluesky-social/atproto/commit/b43ec31f247f4461725b01226885f88bd430ca07), [`b43ec31`](https://github.com/bluesky-social/atproto/commit/b43ec31f247f4461725b01226885f88bd430ca07), [`b43ec31`](https://github.com/bluesky-social/atproto/commit/b43ec31f247f4461725b01226885f88bd430ca07)]:
|
|
14
|
+
- @atproto/syntax@0.6.4
|
|
15
|
+
- @atproto/identity@0.5.3
|
|
16
|
+
- @atproto/xrpc-server@0.11.6
|
|
17
|
+
- @atproto/lex@0.1.7
|
|
18
|
+
- @atproto/common@0.6.5
|
|
19
|
+
- @atproto/repo@0.10.3
|
|
20
|
+
|
|
3
21
|
## 0.3.6
|
|
4
22
|
|
|
5
23
|
### Patch Changes
|
package/dist/firehose/index.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/firehose/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,IAAI,CAAA;AAEvC,OAAO,EAEL,UAAU,EAEX,MAAM,mBAAmB,CAAA;AAa1B,OAAO,EACL,UAAU,EAEV,SAAS,EAET,KAAK,EACL,WAAW,EACX,OAAO,EACR,MAAM,cAAc,CAAA;AACrB,OAAO,EAAE,GAAG,EAAE,MAAM,sBAAsB,CAAA;AAC1C,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAA;AAGhD,MAAM,MAAM,eAAe,GAAG,aAAa,GAAG;IAC5C,UAAU,EAAE,UAAU,CAAA;IAEtB,WAAW,EAAE,CAAC,GAAG,EAAE,KAAK,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;IACjD,OAAO,EAAE,CAAC,GAAG,EAAE,KAAK,KAAK,IAAI,CAAA;IAC7B,SAAS,CAAC,EAAE,MAAM,MAAM,GAAG,SAAS,GAAG,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CAAA;IAElE,MAAM,CAAC,EAAE,WAAW,CAAA;IAEpB,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,0BAA0B,CAAC,EAAE,MAAM,CAAA;IAEnC,sBAAsB,CAAC,EAAE,OAAO,CAAA;IAChC,sBAAsB,CAAC,EAAE,OAAO,CAAA;IAEhC,iBAAiB,CAAC,EAAE,MAAM,EAAE,CAAA;IAC5B,eAAe,CAAC,EAAE,OAAO,CAAA;IACzB,cAAc,CAAC,EAAE,OAAO,CAAA;IACxB,aAAa,CAAC,EAAE,OAAO,CAAA;IACvB,WAAW,CAAC,EAAE,OAAO,CAAA;CACtB,CAAA;AAED,qBAAa,QAAQ;IAMA,IAAI,EAAE,eAAe;IALxC,OAAO,CAAC,GAAG,CAAwD;IACnE,OAAO,CAAC,eAAe,CAAiB;IACxC,OAAO,CAAC,YAAY,CAAY;IAChC,OAAO,CAAC,eAAe,CAA0C;IAEjE,YAAmB,IAAI,EAAE,eAAe,EAgDvC;IAEK,KAAK,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/firehose/index.ts"],"names":[],"mappings":"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"}
|
package/dist/firehose/index.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/firehose/index.ts"],"names":[],"mappings":"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","sourcesContent":["import type { ClientOptions } from 'ws'\nimport { Deferrable, createDeferrable, wait } from '@atproto/common'\nimport {\n DidDocument,\n IdResolver,\n parseToAtprotoDocument,\n} from '@atproto/identity'\nimport { Cid } from '@atproto/lex'\nimport {\n RepoVerificationError,\n cborToLexRecord,\n formatDataKey,\n parseDataKey,\n readCar,\n readCarWithRoot,\n verifyProofs,\n} from '@atproto/repo'\nimport { AtUri } from '@atproto/syntax'\nimport { Subscription } from '@atproto/xrpc-server'\nimport {\n AccountEvt,\n AccountStatus,\n CommitEvt,\n CommitMeta,\n Event,\n IdentityEvt,\n SyncEvt,\n} from '../events.js'\nimport { com } from '../lexicons/index.js'\nimport { EventRunner } from '../runner/index.js'\nimport { didAndSeqForEvt } from '../util.js'\n\nexport type FirehoseOptions = ClientOptions & {\n idResolver: IdResolver\n\n handleEvent: (evt: Event) => void | Promise<void>\n onError: (err: Error) => void\n getCursor?: () => number | undefined | Promise<number | undefined>\n\n runner?: EventRunner // should only set getCursor *or* runner\n\n service?: string\n subscriptionReconnectDelay?: number\n\n unauthenticatedCommits?: boolean\n unauthenticatedHandles?: boolean\n\n filterCollections?: string[]\n excludeIdentity?: boolean\n excludeAccount?: boolean\n excludeCommit?: boolean\n excludeSync?: boolean\n}\n\nexport class Firehose {\n private sub: Subscription<com.atproto.sync.subscribeRepos.$Message>\n private abortController: AbortController\n private destoryDefer: Deferrable\n private matchCollection: ((col: string) => boolean) | null = null\n\n constructor(public opts: FirehoseOptions) {\n this.destoryDefer = createDeferrable()\n this.abortController = new AbortController()\n if (this.opts.getCursor && this.opts.runner) {\n throw new Error('Must set only `getCursor` or `runner`')\n }\n if (opts.filterCollections) {\n const exact = new Set<string>()\n const prefixes: string[] = []\n\n for (const pattern of opts.filterCollections) {\n if (pattern.endsWith('.*')) {\n prefixes.push(pattern.slice(0, -2))\n } else {\n exact.add(pattern)\n }\n }\n this.matchCollection = (col: string): boolean => {\n if (exact.has(col)) return true\n for (const prefix of prefixes) {\n if (col.startsWith(prefix)) return true\n }\n return false\n }\n }\n this.sub = new Subscription({\n ...opts,\n service: opts.service ?? 'wss://bsky.network',\n method: com.atproto.sync.subscribeRepos.$lxm,\n signal: this.abortController.signal,\n getParams: async () => {\n let cursor: number | undefined\n if (this.opts.runner) {\n cursor = await this.opts.runner.getCursor()\n } else if (this.opts.getCursor) {\n cursor = await this.opts.getCursor()\n }\n return cursor === undefined ? undefined : { cursor }\n },\n validate: (value: unknown) => {\n const result = com.atproto.sync.subscribeRepos.$message.safeParse(value)\n if (result.success) {\n return result.value\n } else {\n this.opts.onError(new FirehoseValidationError(result.reason, value))\n }\n },\n })\n }\n\n async start() {\n try {\n for await (const evt of this.sub) {\n if (this.opts.runner) {\n const parsed = didAndSeqForEvt(evt)\n if (!parsed) {\n continue\n }\n this.opts.runner.trackEvent(parsed.did, parsed.seq, async () => {\n const parsed = await this.parseEvt(evt)\n for (const write of parsed) {\n try {\n await this.opts.handleEvent(write)\n } catch (err) {\n this.opts.onError(new FirehoseHandlerError(err, write))\n }\n }\n })\n } else {\n await this.processEvt(evt)\n }\n }\n } catch (err) {\n if (err && err['name'] === 'AbortError') {\n this.destoryDefer.resolve()\n return\n }\n this.opts.onError(new FirehoseSubscriptionError(err))\n await wait(this.opts.subscriptionReconnectDelay ?? 3000)\n return this.start()\n }\n }\n\n private async parseEvt(\n evt: com.atproto.sync.subscribeRepos.$Message,\n ): Promise<Event[]> {\n try {\n if (com.atproto.sync.subscribeRepos.commit.$isTypeOf(evt)) {\n if (this.opts.excludeCommit) return []\n\n return this.opts.unauthenticatedCommits\n ? await parseCommitUnauthenticated(evt, this.matchCollection)\n : await parseCommitAuthenticated(\n this.opts.idResolver,\n evt,\n this.matchCollection,\n )\n } else if (com.atproto.sync.subscribeRepos.account.$isTypeOf(evt)) {\n if (this.opts.excludeAccount) return []\n\n const parsed = parseAccount(evt)\n return parsed ? [parsed] : []\n } else if (com.atproto.sync.subscribeRepos.identity.$isTypeOf(evt)) {\n if (this.opts.excludeIdentity) return []\n\n const parsed = await parseIdentity(\n this.opts.idResolver,\n evt,\n this.opts.unauthenticatedHandles,\n )\n return parsed ? [parsed] : []\n } else if (com.atproto.sync.subscribeRepos.sync.$isTypeOf(evt)) {\n if (this.opts.excludeSync) return []\n\n const parsed = await parseSync(evt)\n return parsed ? [parsed] : []\n } else {\n return []\n }\n } catch (err) {\n this.opts.onError(new FirehoseParseError(err, evt))\n return []\n }\n }\n\n private async processEvt(evt: com.atproto.sync.subscribeRepos.$Message) {\n const parsed = await this.parseEvt(evt)\n for (const write of parsed) {\n try {\n await this.opts.handleEvent(write)\n } catch (err) {\n this.opts.onError(new FirehoseHandlerError(err, write))\n }\n }\n }\n\n async destroy(): Promise<void> {\n this.abortController.abort()\n await this.destoryDefer.complete\n }\n}\n\nexport const parseCommitAuthenticated = async (\n idResolver: IdResolver,\n evt: com.atproto.sync.subscribeRepos.Commit,\n matchCollection?: ((col: string) => boolean) | null,\n forceKeyRefresh = false,\n): Promise<CommitEvt[]> => {\n const did = evt.repo\n const ops = maybeFilterOps(evt.ops, matchCollection)\n if (ops.length === 0) {\n return []\n }\n const claims = ops.map((op) => {\n const { collection, rkey } = parseDataKey(op.path)\n return {\n collection,\n rkey,\n cid: op.action === 'delete' ? null : op.cid,\n }\n })\n const key = await idResolver.did.resolveAtprotoKey(did, forceKeyRefresh)\n const verifiedCids: Record<string, Cid | null> = {}\n try {\n const results = await verifyProofs(evt.blocks, claims, did, key)\n results.verified.forEach((op) => {\n const path = formatDataKey(op.collection, op.rkey)\n verifiedCids[path] = op.cid\n })\n } catch (err) {\n if (err instanceof RepoVerificationError && !forceKeyRefresh) {\n return parseCommitAuthenticated(idResolver, evt, matchCollection, true)\n }\n throw err\n }\n const verifiedOps: com.atproto.sync.subscribeRepos.RepoOp[] = ops.filter(\n (op) => {\n const verifiedCid = verifiedCids[op.path]\n if (op.action === 'delete') {\n return verifiedCid === null\n } else {\n return (\n op.cid != null && verifiedCid != null && verifiedCid.equals(op.cid)\n )\n }\n },\n )\n return formatCommitOps(evt, verifiedOps, {\n skipCidVerification: true, // already checked via verifyProofs()\n })\n}\n\nexport const parseCommitUnauthenticated = async (\n evt: com.atproto.sync.subscribeRepos.Commit,\n matchCollection?: ((col: string) => boolean) | null,\n): Promise<CommitEvt[]> => {\n const ops = maybeFilterOps(evt.ops, matchCollection)\n return formatCommitOps(evt, ops)\n}\n\nconst maybeFilterOps = (\n ops: com.atproto.sync.subscribeRepos.RepoOp[],\n matchCollection?: ((col: string) => boolean) | null,\n): com.atproto.sync.subscribeRepos.RepoOp[] => {\n if (!matchCollection) return ops\n return ops.filter((op) => {\n const { collection } = parseDataKey(op.path)\n return matchCollection(collection)\n })\n}\n\nconst formatCommitOps = async (\n evt: com.atproto.sync.subscribeRepos.Commit,\n ops: com.atproto.sync.subscribeRepos.RepoOp[],\n options?: { skipCidVerification: boolean },\n) => {\n const car = await readCar(evt.blocks, options)\n\n const evts: CommitEvt[] = []\n\n for (const op of ops) {\n const uri = AtUri.make(evt.repo, op.path)\n\n const meta: CommitMeta = {\n seq: evt.seq,\n time: evt.time,\n commit: evt.commit,\n blocks: car.blocks,\n rev: evt.rev,\n uri,\n did: uri.did,\n collection: uri.collection,\n rkey: uri.rkey,\n }\n\n if (op.action === 'create' || op.action === 'update') {\n if (!op.cid) continue\n const recordBytes = car.blocks.get(op.cid)\n if (!recordBytes) continue\n const record = cborToLexRecord(recordBytes)\n evts.push({\n ...meta,\n event: op.action as 'create' | 'update',\n cid: op.cid,\n record,\n })\n }\n\n if (op.action === 'delete') {\n evts.push({\n ...meta,\n event: 'delete',\n })\n }\n }\n\n return evts\n}\n\nexport const parseSync = async (\n evt: com.atproto.sync.subscribeRepos.Sync,\n): Promise<SyncEvt | null> => {\n const car = await readCarWithRoot(evt.blocks)\n\n return {\n event: 'sync',\n seq: evt.seq,\n time: evt.time,\n did: evt.did,\n cid: car.root,\n rev: evt.rev,\n blocks: car.blocks,\n }\n}\n\nexport const parseIdentity = async (\n idResolver: IdResolver,\n evt: com.atproto.sync.subscribeRepos.Identity,\n unauthenticated = false,\n): Promise<IdentityEvt | null> => {\n const res = await idResolver.did.resolve(evt.did)\n const handle =\n res && !unauthenticated\n ? await verifyHandle(idResolver, evt.did, res)\n : undefined\n\n return {\n event: 'identity',\n seq: evt.seq,\n time: evt.time,\n did: evt.did,\n handle,\n didDocument: res ?? undefined,\n }\n}\n\nconst verifyHandle = async (\n idResolver: IdResolver,\n did: string,\n didDoc: DidDocument,\n): Promise<string | undefined> => {\n const { handle } = parseToAtprotoDocument(didDoc)\n if (!handle) {\n return undefined\n }\n const res = await idResolver.handle.resolve(handle)\n return res === did ? handle : undefined\n}\n\nexport const parseAccount = (\n evt: com.atproto.sync.subscribeRepos.Account,\n): AccountEvt | undefined => {\n if (evt.status && !isValidStatus(evt.status)) return\n return {\n event: 'account',\n seq: evt.seq,\n time: evt.time,\n did: evt.did,\n active: evt.active,\n status: evt.status as AccountStatus | undefined,\n }\n}\n\nconst isValidStatus = (str: string): str is AccountStatus => {\n return ['takendown', 'suspended', 'deleted', 'deactivated'].includes(str)\n}\n\nexport class FirehoseValidationError extends Error {\n constructor(\n err: unknown,\n public value: unknown,\n ) {\n super('error in firehose event lexicon validation', { cause: err })\n }\n}\n\nexport class FirehoseParseError extends Error {\n constructor(\n err: unknown,\n public event: com.atproto.sync.subscribeRepos.$Message,\n ) {\n super('error in parsing and authenticating firehose event', { cause: err })\n }\n}\n\nexport class FirehoseSubscriptionError extends Error {\n constructor(err: unknown) {\n super('error on firehose subscription', { cause: err })\n }\n}\n\nexport class FirehoseHandlerError extends Error {\n constructor(\n err: unknown,\n public event: Event,\n ) {\n super('error in firehose event handler', { cause: err })\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/firehose/index.ts"],"names":[],"mappings":"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","sourcesContent":["import type { ClientOptions } from 'ws'\nimport { Deferrable, createDeferrable, wait } from '@atproto/common'\nimport {\n DidDocument,\n IdResolver,\n parseToAtprotoDocument,\n} from '@atproto/identity'\nimport { Cid } from '@atproto/lex'\nimport {\n RepoVerificationError,\n cborToLexRecord,\n formatDataKey,\n parseDataKey,\n readCar,\n readCarWithRoot,\n verifyProofs,\n} from '@atproto/repo'\nimport { AtUri } from '@atproto/syntax'\nimport { Subscription } from '@atproto/xrpc-server'\nimport {\n AccountEvt,\n AccountStatus,\n CommitEvt,\n CommitMeta,\n Event,\n IdentityEvt,\n SyncEvt,\n} from '../events.js'\nimport { com } from '../lexicons/index.js'\nimport { EventRunner } from '../runner/index.js'\nimport { didAndSeqForEvt } from '../util.js'\n\nexport type FirehoseOptions = ClientOptions & {\n idResolver: IdResolver\n\n handleEvent: (evt: Event) => void | Promise<void>\n onError: (err: Error) => void\n getCursor?: () => number | undefined | Promise<number | undefined>\n\n runner?: EventRunner // should only set getCursor *or* runner\n\n service?: string\n subscriptionReconnectDelay?: number\n\n unauthenticatedCommits?: boolean\n unauthenticatedHandles?: boolean\n\n filterCollections?: string[]\n excludeIdentity?: boolean\n excludeAccount?: boolean\n excludeCommit?: boolean\n excludeSync?: boolean\n}\n\nexport class Firehose {\n private sub: Subscription<com.atproto.sync.subscribeRepos.$Message>\n private abortController: AbortController\n private destoryDefer: Deferrable\n private matchCollection: ((col: string) => boolean) | null = null\n\n constructor(public opts: FirehoseOptions) {\n this.destoryDefer = createDeferrable()\n this.abortController = new AbortController()\n if (this.opts.getCursor && this.opts.runner) {\n throw new Error('Must set only `getCursor` or `runner`')\n }\n if (opts.filterCollections) {\n const exact = new Set<string>()\n const prefixes: string[] = []\n\n for (const pattern of opts.filterCollections) {\n if (pattern.endsWith('.*')) {\n prefixes.push(pattern.slice(0, -2))\n } else {\n exact.add(pattern)\n }\n }\n this.matchCollection = (col: string): boolean => {\n if (exact.has(col)) return true\n for (const prefix of prefixes) {\n if (col.startsWith(prefix)) return true\n }\n return false\n }\n }\n this.sub = new Subscription({\n ...opts,\n service: opts.service ?? 'wss://bsky.network',\n method: com.atproto.sync.subscribeRepos.$lxm,\n signal: this.abortController.signal,\n getParams: async () => {\n let cursor: number | undefined\n if (this.opts.runner) {\n cursor = await this.opts.runner.getCursor()\n } else if (this.opts.getCursor) {\n cursor = await this.opts.getCursor()\n }\n return cursor === undefined ? undefined : { cursor }\n },\n validate: (value: unknown) => {\n const result = com.atproto.sync.subscribeRepos.$message.safeParse(value)\n if (result.success) {\n return result.value\n } else {\n this.opts.onError(new FirehoseValidationError(result.reason, value))\n }\n },\n })\n }\n\n async start(): Promise<void> {\n try {\n for await (const evt of this.sub) {\n if (this.opts.runner) {\n const parsed = didAndSeqForEvt(evt)\n if (!parsed) {\n continue\n }\n this.opts.runner.trackEvent(parsed.did, parsed.seq, async () => {\n const parsed = await this.parseEvt(evt)\n for (const write of parsed) {\n try {\n await this.opts.handleEvent(write)\n } catch (err) {\n this.opts.onError(new FirehoseHandlerError(err, write))\n }\n }\n })\n } else {\n await this.processEvt(evt)\n }\n }\n } catch (err) {\n if ((err as any)?.name === 'AbortError') {\n this.destoryDefer.resolve()\n return\n }\n this.opts.onError(new FirehoseSubscriptionError(err))\n await wait(this.opts.subscriptionReconnectDelay ?? 3000)\n return this.start()\n }\n }\n\n private async parseEvt(\n evt: com.atproto.sync.subscribeRepos.$Message,\n ): Promise<Event[]> {\n try {\n if (com.atproto.sync.subscribeRepos.commit.$isTypeOf(evt)) {\n if (this.opts.excludeCommit) return []\n\n return this.opts.unauthenticatedCommits\n ? await parseCommitUnauthenticated(evt, this.matchCollection)\n : await parseCommitAuthenticated(\n this.opts.idResolver,\n evt,\n this.matchCollection,\n )\n } else if (com.atproto.sync.subscribeRepos.account.$isTypeOf(evt)) {\n if (this.opts.excludeAccount) return []\n\n const parsed = parseAccount(evt)\n return parsed ? [parsed] : []\n } else if (com.atproto.sync.subscribeRepos.identity.$isTypeOf(evt)) {\n if (this.opts.excludeIdentity) return []\n\n const parsed = await parseIdentity(\n this.opts.idResolver,\n evt,\n this.opts.unauthenticatedHandles,\n )\n return parsed ? [parsed] : []\n } else if (com.atproto.sync.subscribeRepos.sync.$isTypeOf(evt)) {\n if (this.opts.excludeSync) return []\n\n const parsed = await parseSync(evt)\n return parsed ? [parsed] : []\n } else {\n return []\n }\n } catch (err) {\n this.opts.onError(new FirehoseParseError(err, evt))\n return []\n }\n }\n\n private async processEvt(evt: com.atproto.sync.subscribeRepos.$Message) {\n const parsed = await this.parseEvt(evt)\n for (const write of parsed) {\n try {\n await this.opts.handleEvent(write)\n } catch (err) {\n this.opts.onError(new FirehoseHandlerError(err, write))\n }\n }\n }\n\n async destroy(): Promise<void> {\n this.abortController.abort()\n await this.destoryDefer.complete\n }\n}\n\nexport const parseCommitAuthenticated = async (\n idResolver: IdResolver,\n evt: com.atproto.sync.subscribeRepos.Commit,\n matchCollection?: ((col: string) => boolean) | null,\n forceKeyRefresh = false,\n): Promise<CommitEvt[]> => {\n const did = evt.repo\n const ops = maybeFilterOps(evt.ops, matchCollection)\n if (ops.length === 0) {\n return []\n }\n const claims = ops.map((op) => {\n const { collection, rkey } = parseDataKey(op.path)\n return {\n collection,\n rkey,\n cid: op.action === 'delete' ? null : op.cid,\n }\n })\n const key = await idResolver.did.resolveAtprotoKey(did, forceKeyRefresh)\n const verifiedCids: Record<string, Cid | null> = {}\n try {\n const results = await verifyProofs(evt.blocks, claims, did, key)\n results.verified.forEach((op) => {\n const path = formatDataKey(op.collection, op.rkey)\n verifiedCids[path] = op.cid\n })\n } catch (err) {\n if (err instanceof RepoVerificationError && !forceKeyRefresh) {\n return parseCommitAuthenticated(idResolver, evt, matchCollection, true)\n }\n throw err\n }\n const verifiedOps: com.atproto.sync.subscribeRepos.RepoOp[] = ops.filter(\n (op) => {\n const verifiedCid = verifiedCids[op.path]\n if (op.action === 'delete') {\n return verifiedCid === null\n } else {\n return (\n op.cid != null && verifiedCid != null && verifiedCid.equals(op.cid)\n )\n }\n },\n )\n return formatCommitOps(evt, verifiedOps, {\n skipCidVerification: true, // already checked via verifyProofs()\n })\n}\n\nexport const parseCommitUnauthenticated = async (\n evt: com.atproto.sync.subscribeRepos.Commit,\n matchCollection?: ((col: string) => boolean) | null,\n): Promise<CommitEvt[]> => {\n const ops = maybeFilterOps(evt.ops, matchCollection)\n return formatCommitOps(evt, ops)\n}\n\nconst maybeFilterOps = (\n ops: com.atproto.sync.subscribeRepos.RepoOp[],\n matchCollection?: ((col: string) => boolean) | null,\n): com.atproto.sync.subscribeRepos.RepoOp[] => {\n if (!matchCollection) return ops\n return ops.filter((op) => {\n const { collection } = parseDataKey(op.path)\n return matchCollection(collection)\n })\n}\n\nconst formatCommitOps = async (\n evt: com.atproto.sync.subscribeRepos.Commit,\n ops: com.atproto.sync.subscribeRepos.RepoOp[],\n options?: { skipCidVerification: boolean },\n) => {\n const car = await readCar(evt.blocks, options)\n\n const evts: CommitEvt[] = []\n\n for (const op of ops) {\n const uri = AtUri.make(evt.repo, op.path)\n\n const meta: CommitMeta = {\n seq: evt.seq,\n time: evt.time,\n commit: evt.commit,\n blocks: car.blocks,\n rev: evt.rev,\n uri,\n did: uri.did,\n collection: uri.collection,\n rkey: uri.rkey,\n }\n\n if (op.action === 'create' || op.action === 'update') {\n if (!op.cid) continue\n const recordBytes = car.blocks.get(op.cid)\n if (!recordBytes) continue\n const record = cborToLexRecord(recordBytes)\n evts.push({\n ...meta,\n event: op.action as 'create' | 'update',\n cid: op.cid,\n record,\n })\n }\n\n if (op.action === 'delete') {\n evts.push({\n ...meta,\n event: 'delete',\n })\n }\n }\n\n return evts\n}\n\nexport const parseSync = async (\n evt: com.atproto.sync.subscribeRepos.Sync,\n): Promise<SyncEvt | null> => {\n const car = await readCarWithRoot(evt.blocks)\n\n return {\n event: 'sync',\n seq: evt.seq,\n time: evt.time,\n did: evt.did,\n cid: car.root,\n rev: evt.rev,\n blocks: car.blocks,\n }\n}\n\nexport const parseIdentity = async (\n idResolver: IdResolver,\n evt: com.atproto.sync.subscribeRepos.Identity,\n unauthenticated = false,\n): Promise<IdentityEvt | null> => {\n const res = await idResolver.did.resolve(evt.did)\n const handle =\n res && !unauthenticated\n ? await verifyHandle(idResolver, evt.did, res)\n : undefined\n\n return {\n event: 'identity',\n seq: evt.seq,\n time: evt.time,\n did: evt.did,\n handle,\n didDocument: res ?? undefined,\n }\n}\n\nconst verifyHandle = async (\n idResolver: IdResolver,\n did: string,\n didDoc: DidDocument,\n): Promise<string | undefined> => {\n const { handle } = parseToAtprotoDocument(didDoc)\n if (!handle) {\n return undefined\n }\n const res = await idResolver.handle.resolve(handle)\n return res === did ? handle : undefined\n}\n\nexport const parseAccount = (\n evt: com.atproto.sync.subscribeRepos.Account,\n): AccountEvt | undefined => {\n if (evt.status && !isValidStatus(evt.status)) return\n return {\n event: 'account',\n seq: evt.seq,\n time: evt.time,\n did: evt.did,\n active: evt.active,\n status: evt.status as AccountStatus | undefined,\n }\n}\n\nconst isValidStatus = (str: string): str is AccountStatus => {\n return ['takendown', 'suspended', 'deleted', 'deactivated'].includes(str)\n}\n\nexport class FirehoseValidationError extends Error {\n constructor(\n err: unknown,\n public value: unknown,\n ) {\n super('error in firehose event lexicon validation', { cause: err })\n }\n}\n\nexport class FirehoseParseError extends Error {\n constructor(\n err: unknown,\n public event: com.atproto.sync.subscribeRepos.$Message,\n ) {\n super('error in parsing and authenticating firehose event', { cause: err })\n }\n}\n\nexport class FirehoseSubscriptionError extends Error {\n constructor(err: unknown) {\n super('error on firehose subscription', { cause: err })\n }\n}\n\nexport class FirehoseHandlerError extends Error {\n constructor(\n err: unknown,\n public event: Event,\n ) {\n super('error in firehose event handler', { cause: err })\n }\n}\n"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@atproto/sync",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.7",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"description": "atproto sync library",
|
|
6
6
|
"keywords": [
|
|
@@ -15,33 +15,38 @@
|
|
|
15
15
|
"url": "https://github.com/bluesky-social/atproto",
|
|
16
16
|
"directory": "packages/sync"
|
|
17
17
|
},
|
|
18
|
+
"files": [
|
|
19
|
+
"./dist",
|
|
20
|
+
"./README.md",
|
|
21
|
+
"./CHANGELOG.md"
|
|
22
|
+
],
|
|
23
|
+
"type": "module",
|
|
24
|
+
"exports": {
|
|
25
|
+
".": {
|
|
26
|
+
"types": "./dist/index.d.ts",
|
|
27
|
+
"default": "./dist/index.js"
|
|
28
|
+
}
|
|
29
|
+
},
|
|
18
30
|
"engines": {
|
|
19
31
|
"node": ">=22"
|
|
20
32
|
},
|
|
21
33
|
"dependencies": {
|
|
22
34
|
"p-queue": "^8.0.0",
|
|
23
35
|
"ws": "^8.12.0",
|
|
24
|
-
"@atproto/common": "^0.6.
|
|
25
|
-
"@atproto/
|
|
26
|
-
"@atproto/
|
|
27
|
-
"@atproto/
|
|
28
|
-
"@atproto/xrpc-server": "^0.11.
|
|
29
|
-
"@atproto/
|
|
36
|
+
"@atproto/common": "^0.6.5",
|
|
37
|
+
"@atproto/identity": "^0.5.3",
|
|
38
|
+
"@atproto/lex": "^0.1.7",
|
|
39
|
+
"@atproto/syntax": "^0.6.4",
|
|
40
|
+
"@atproto/xrpc-server": "^0.11.6",
|
|
41
|
+
"@atproto/repo": "^0.10.3"
|
|
30
42
|
},
|
|
31
43
|
"devDependencies": {
|
|
32
44
|
"@types/ws": "^8.5.4",
|
|
33
45
|
"jest": "^30.0.0"
|
|
34
46
|
},
|
|
35
|
-
"type": "module",
|
|
36
|
-
"exports": {
|
|
37
|
-
".": {
|
|
38
|
-
"types": "./dist/index.d.ts",
|
|
39
|
-
"default": "./dist/index.js"
|
|
40
|
-
}
|
|
41
|
-
},
|
|
42
47
|
"scripts": {
|
|
43
|
-
"codegen": "lex build --clear --indexFile --lexicons ../../lexicons --include com.atproto.sync.subscribeRepos",
|
|
44
|
-
"prebuild": "pnpm run codegen",
|
|
48
|
+
"codegen:lex": "lex build --clear --indexFile --lexicons ../../lexicons --include com.atproto.sync.subscribeRepos",
|
|
49
|
+
"prebuild": "pnpm run '/^(codegen:.+)$/'",
|
|
45
50
|
"build": "tsgo --build tsconfig.build.json",
|
|
46
51
|
"test": "NODE_OPTIONS=--experimental-vm-modules ../dev-infra/with-test-redis-and-db.sh jest"
|
|
47
52
|
}
|
package/jest.config.cjs
DELETED
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
/** @type {import('jest').Config} */
|
|
2
|
-
module.exports = {
|
|
3
|
-
displayName: 'Sync',
|
|
4
|
-
transform: {
|
|
5
|
-
'^.+\\.(t|j)s$': [
|
|
6
|
-
'@swc/jest',
|
|
7
|
-
{
|
|
8
|
-
jsc: {
|
|
9
|
-
parser: { syntax: 'typescript', importAttributes: true },
|
|
10
|
-
experimental: { keepImportAttributes: true },
|
|
11
|
-
transform: {},
|
|
12
|
-
},
|
|
13
|
-
module: { type: 'es6' },
|
|
14
|
-
},
|
|
15
|
-
],
|
|
16
|
-
},
|
|
17
|
-
extensionsToTreatAsEsm: ['.ts'],
|
|
18
|
-
transformIgnorePatterns: [],
|
|
19
|
-
testTimeout: 60000,
|
|
20
|
-
setupFiles: ['<rootDir>/../../test.setup.ts'],
|
|
21
|
-
moduleNameMapper: { '^(\\.\\.?\\/.+)\\.js$': ['$1.ts', '$1.js'] },
|
|
22
|
-
}
|
package/src/events.ts
DELETED
|
@@ -1,70 +0,0 @@
|
|
|
1
|
-
import { DidDocument } from '@atproto/identity'
|
|
2
|
-
import { Cid, LexMap } from '@atproto/lex'
|
|
3
|
-
import { BlockMap } from '@atproto/repo'
|
|
4
|
-
import { AtUri, DidString } from '@atproto/syntax'
|
|
5
|
-
|
|
6
|
-
export type Event = CommitEvt | SyncEvt | IdentityEvt | AccountEvt
|
|
7
|
-
|
|
8
|
-
export type CommitMeta = {
|
|
9
|
-
seq: number
|
|
10
|
-
time: string
|
|
11
|
-
commit: Cid
|
|
12
|
-
blocks: BlockMap
|
|
13
|
-
rev: string
|
|
14
|
-
uri: AtUri
|
|
15
|
-
did: DidString
|
|
16
|
-
collection: string
|
|
17
|
-
rkey: string
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
export type CommitEvt = Create | Update | Delete
|
|
21
|
-
|
|
22
|
-
export type Create = CommitMeta & {
|
|
23
|
-
event: 'create'
|
|
24
|
-
record: LexMap
|
|
25
|
-
cid: Cid
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
export type Update = CommitMeta & {
|
|
29
|
-
event: 'update'
|
|
30
|
-
record: LexMap
|
|
31
|
-
cid: Cid
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
export type Delete = CommitMeta & {
|
|
35
|
-
event: 'delete'
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
export type SyncEvt = {
|
|
39
|
-
seq: number
|
|
40
|
-
time: string
|
|
41
|
-
event: 'sync'
|
|
42
|
-
did: DidString
|
|
43
|
-
cid: Cid
|
|
44
|
-
rev: string
|
|
45
|
-
blocks: BlockMap
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
export type IdentityEvt = {
|
|
49
|
-
seq: number
|
|
50
|
-
time: string
|
|
51
|
-
event: 'identity'
|
|
52
|
-
did: DidString
|
|
53
|
-
handle?: string
|
|
54
|
-
didDocument?: DidDocument
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
export type AccountEvt = {
|
|
58
|
-
seq: number
|
|
59
|
-
time: string
|
|
60
|
-
event: 'account'
|
|
61
|
-
did: DidString
|
|
62
|
-
active: boolean
|
|
63
|
-
status?: AccountStatus
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
export type AccountStatus =
|
|
67
|
-
| 'takendown'
|
|
68
|
-
| 'suspended'
|
|
69
|
-
| 'deleted'
|
|
70
|
-
| 'deactivated'
|
package/src/firehose/index.ts
DELETED
|
@@ -1,419 +0,0 @@
|
|
|
1
|
-
import type { ClientOptions } from 'ws'
|
|
2
|
-
import { Deferrable, createDeferrable, wait } from '@atproto/common'
|
|
3
|
-
import {
|
|
4
|
-
DidDocument,
|
|
5
|
-
IdResolver,
|
|
6
|
-
parseToAtprotoDocument,
|
|
7
|
-
} from '@atproto/identity'
|
|
8
|
-
import { Cid } from '@atproto/lex'
|
|
9
|
-
import {
|
|
10
|
-
RepoVerificationError,
|
|
11
|
-
cborToLexRecord,
|
|
12
|
-
formatDataKey,
|
|
13
|
-
parseDataKey,
|
|
14
|
-
readCar,
|
|
15
|
-
readCarWithRoot,
|
|
16
|
-
verifyProofs,
|
|
17
|
-
} from '@atproto/repo'
|
|
18
|
-
import { AtUri } from '@atproto/syntax'
|
|
19
|
-
import { Subscription } from '@atproto/xrpc-server'
|
|
20
|
-
import {
|
|
21
|
-
AccountEvt,
|
|
22
|
-
AccountStatus,
|
|
23
|
-
CommitEvt,
|
|
24
|
-
CommitMeta,
|
|
25
|
-
Event,
|
|
26
|
-
IdentityEvt,
|
|
27
|
-
SyncEvt,
|
|
28
|
-
} from '../events.js'
|
|
29
|
-
import { com } from '../lexicons/index.js'
|
|
30
|
-
import { EventRunner } from '../runner/index.js'
|
|
31
|
-
import { didAndSeqForEvt } from '../util.js'
|
|
32
|
-
|
|
33
|
-
export type FirehoseOptions = ClientOptions & {
|
|
34
|
-
idResolver: IdResolver
|
|
35
|
-
|
|
36
|
-
handleEvent: (evt: Event) => void | Promise<void>
|
|
37
|
-
onError: (err: Error) => void
|
|
38
|
-
getCursor?: () => number | undefined | Promise<number | undefined>
|
|
39
|
-
|
|
40
|
-
runner?: EventRunner // should only set getCursor *or* runner
|
|
41
|
-
|
|
42
|
-
service?: string
|
|
43
|
-
subscriptionReconnectDelay?: number
|
|
44
|
-
|
|
45
|
-
unauthenticatedCommits?: boolean
|
|
46
|
-
unauthenticatedHandles?: boolean
|
|
47
|
-
|
|
48
|
-
filterCollections?: string[]
|
|
49
|
-
excludeIdentity?: boolean
|
|
50
|
-
excludeAccount?: boolean
|
|
51
|
-
excludeCommit?: boolean
|
|
52
|
-
excludeSync?: boolean
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
export class Firehose {
|
|
56
|
-
private sub: Subscription<com.atproto.sync.subscribeRepos.$Message>
|
|
57
|
-
private abortController: AbortController
|
|
58
|
-
private destoryDefer: Deferrable
|
|
59
|
-
private matchCollection: ((col: string) => boolean) | null = null
|
|
60
|
-
|
|
61
|
-
constructor(public opts: FirehoseOptions) {
|
|
62
|
-
this.destoryDefer = createDeferrable()
|
|
63
|
-
this.abortController = new AbortController()
|
|
64
|
-
if (this.opts.getCursor && this.opts.runner) {
|
|
65
|
-
throw new Error('Must set only `getCursor` or `runner`')
|
|
66
|
-
}
|
|
67
|
-
if (opts.filterCollections) {
|
|
68
|
-
const exact = new Set<string>()
|
|
69
|
-
const prefixes: string[] = []
|
|
70
|
-
|
|
71
|
-
for (const pattern of opts.filterCollections) {
|
|
72
|
-
if (pattern.endsWith('.*')) {
|
|
73
|
-
prefixes.push(pattern.slice(0, -2))
|
|
74
|
-
} else {
|
|
75
|
-
exact.add(pattern)
|
|
76
|
-
}
|
|
77
|
-
}
|
|
78
|
-
this.matchCollection = (col: string): boolean => {
|
|
79
|
-
if (exact.has(col)) return true
|
|
80
|
-
for (const prefix of prefixes) {
|
|
81
|
-
if (col.startsWith(prefix)) return true
|
|
82
|
-
}
|
|
83
|
-
return false
|
|
84
|
-
}
|
|
85
|
-
}
|
|
86
|
-
this.sub = new Subscription({
|
|
87
|
-
...opts,
|
|
88
|
-
service: opts.service ?? 'wss://bsky.network',
|
|
89
|
-
method: com.atproto.sync.subscribeRepos.$lxm,
|
|
90
|
-
signal: this.abortController.signal,
|
|
91
|
-
getParams: async () => {
|
|
92
|
-
let cursor: number | undefined
|
|
93
|
-
if (this.opts.runner) {
|
|
94
|
-
cursor = await this.opts.runner.getCursor()
|
|
95
|
-
} else if (this.opts.getCursor) {
|
|
96
|
-
cursor = await this.opts.getCursor()
|
|
97
|
-
}
|
|
98
|
-
return cursor === undefined ? undefined : { cursor }
|
|
99
|
-
},
|
|
100
|
-
validate: (value: unknown) => {
|
|
101
|
-
const result = com.atproto.sync.subscribeRepos.$message.safeParse(value)
|
|
102
|
-
if (result.success) {
|
|
103
|
-
return result.value
|
|
104
|
-
} else {
|
|
105
|
-
this.opts.onError(new FirehoseValidationError(result.reason, value))
|
|
106
|
-
}
|
|
107
|
-
},
|
|
108
|
-
})
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
async start() {
|
|
112
|
-
try {
|
|
113
|
-
for await (const evt of this.sub) {
|
|
114
|
-
if (this.opts.runner) {
|
|
115
|
-
const parsed = didAndSeqForEvt(evt)
|
|
116
|
-
if (!parsed) {
|
|
117
|
-
continue
|
|
118
|
-
}
|
|
119
|
-
this.opts.runner.trackEvent(parsed.did, parsed.seq, async () => {
|
|
120
|
-
const parsed = await this.parseEvt(evt)
|
|
121
|
-
for (const write of parsed) {
|
|
122
|
-
try {
|
|
123
|
-
await this.opts.handleEvent(write)
|
|
124
|
-
} catch (err) {
|
|
125
|
-
this.opts.onError(new FirehoseHandlerError(err, write))
|
|
126
|
-
}
|
|
127
|
-
}
|
|
128
|
-
})
|
|
129
|
-
} else {
|
|
130
|
-
await this.processEvt(evt)
|
|
131
|
-
}
|
|
132
|
-
}
|
|
133
|
-
} catch (err) {
|
|
134
|
-
if (err && err['name'] === 'AbortError') {
|
|
135
|
-
this.destoryDefer.resolve()
|
|
136
|
-
return
|
|
137
|
-
}
|
|
138
|
-
this.opts.onError(new FirehoseSubscriptionError(err))
|
|
139
|
-
await wait(this.opts.subscriptionReconnectDelay ?? 3000)
|
|
140
|
-
return this.start()
|
|
141
|
-
}
|
|
142
|
-
}
|
|
143
|
-
|
|
144
|
-
private async parseEvt(
|
|
145
|
-
evt: com.atproto.sync.subscribeRepos.$Message,
|
|
146
|
-
): Promise<Event[]> {
|
|
147
|
-
try {
|
|
148
|
-
if (com.atproto.sync.subscribeRepos.commit.$isTypeOf(evt)) {
|
|
149
|
-
if (this.opts.excludeCommit) return []
|
|
150
|
-
|
|
151
|
-
return this.opts.unauthenticatedCommits
|
|
152
|
-
? await parseCommitUnauthenticated(evt, this.matchCollection)
|
|
153
|
-
: await parseCommitAuthenticated(
|
|
154
|
-
this.opts.idResolver,
|
|
155
|
-
evt,
|
|
156
|
-
this.matchCollection,
|
|
157
|
-
)
|
|
158
|
-
} else if (com.atproto.sync.subscribeRepos.account.$isTypeOf(evt)) {
|
|
159
|
-
if (this.opts.excludeAccount) return []
|
|
160
|
-
|
|
161
|
-
const parsed = parseAccount(evt)
|
|
162
|
-
return parsed ? [parsed] : []
|
|
163
|
-
} else if (com.atproto.sync.subscribeRepos.identity.$isTypeOf(evt)) {
|
|
164
|
-
if (this.opts.excludeIdentity) return []
|
|
165
|
-
|
|
166
|
-
const parsed = await parseIdentity(
|
|
167
|
-
this.opts.idResolver,
|
|
168
|
-
evt,
|
|
169
|
-
this.opts.unauthenticatedHandles,
|
|
170
|
-
)
|
|
171
|
-
return parsed ? [parsed] : []
|
|
172
|
-
} else if (com.atproto.sync.subscribeRepos.sync.$isTypeOf(evt)) {
|
|
173
|
-
if (this.opts.excludeSync) return []
|
|
174
|
-
|
|
175
|
-
const parsed = await parseSync(evt)
|
|
176
|
-
return parsed ? [parsed] : []
|
|
177
|
-
} else {
|
|
178
|
-
return []
|
|
179
|
-
}
|
|
180
|
-
} catch (err) {
|
|
181
|
-
this.opts.onError(new FirehoseParseError(err, evt))
|
|
182
|
-
return []
|
|
183
|
-
}
|
|
184
|
-
}
|
|
185
|
-
|
|
186
|
-
private async processEvt(evt: com.atproto.sync.subscribeRepos.$Message) {
|
|
187
|
-
const parsed = await this.parseEvt(evt)
|
|
188
|
-
for (const write of parsed) {
|
|
189
|
-
try {
|
|
190
|
-
await this.opts.handleEvent(write)
|
|
191
|
-
} catch (err) {
|
|
192
|
-
this.opts.onError(new FirehoseHandlerError(err, write))
|
|
193
|
-
}
|
|
194
|
-
}
|
|
195
|
-
}
|
|
196
|
-
|
|
197
|
-
async destroy(): Promise<void> {
|
|
198
|
-
this.abortController.abort()
|
|
199
|
-
await this.destoryDefer.complete
|
|
200
|
-
}
|
|
201
|
-
}
|
|
202
|
-
|
|
203
|
-
export const parseCommitAuthenticated = async (
|
|
204
|
-
idResolver: IdResolver,
|
|
205
|
-
evt: com.atproto.sync.subscribeRepos.Commit,
|
|
206
|
-
matchCollection?: ((col: string) => boolean) | null,
|
|
207
|
-
forceKeyRefresh = false,
|
|
208
|
-
): Promise<CommitEvt[]> => {
|
|
209
|
-
const did = evt.repo
|
|
210
|
-
const ops = maybeFilterOps(evt.ops, matchCollection)
|
|
211
|
-
if (ops.length === 0) {
|
|
212
|
-
return []
|
|
213
|
-
}
|
|
214
|
-
const claims = ops.map((op) => {
|
|
215
|
-
const { collection, rkey } = parseDataKey(op.path)
|
|
216
|
-
return {
|
|
217
|
-
collection,
|
|
218
|
-
rkey,
|
|
219
|
-
cid: op.action === 'delete' ? null : op.cid,
|
|
220
|
-
}
|
|
221
|
-
})
|
|
222
|
-
const key = await idResolver.did.resolveAtprotoKey(did, forceKeyRefresh)
|
|
223
|
-
const verifiedCids: Record<string, Cid | null> = {}
|
|
224
|
-
try {
|
|
225
|
-
const results = await verifyProofs(evt.blocks, claims, did, key)
|
|
226
|
-
results.verified.forEach((op) => {
|
|
227
|
-
const path = formatDataKey(op.collection, op.rkey)
|
|
228
|
-
verifiedCids[path] = op.cid
|
|
229
|
-
})
|
|
230
|
-
} catch (err) {
|
|
231
|
-
if (err instanceof RepoVerificationError && !forceKeyRefresh) {
|
|
232
|
-
return parseCommitAuthenticated(idResolver, evt, matchCollection, true)
|
|
233
|
-
}
|
|
234
|
-
throw err
|
|
235
|
-
}
|
|
236
|
-
const verifiedOps: com.atproto.sync.subscribeRepos.RepoOp[] = ops.filter(
|
|
237
|
-
(op) => {
|
|
238
|
-
const verifiedCid = verifiedCids[op.path]
|
|
239
|
-
if (op.action === 'delete') {
|
|
240
|
-
return verifiedCid === null
|
|
241
|
-
} else {
|
|
242
|
-
return (
|
|
243
|
-
op.cid != null && verifiedCid != null && verifiedCid.equals(op.cid)
|
|
244
|
-
)
|
|
245
|
-
}
|
|
246
|
-
},
|
|
247
|
-
)
|
|
248
|
-
return formatCommitOps(evt, verifiedOps, {
|
|
249
|
-
skipCidVerification: true, // already checked via verifyProofs()
|
|
250
|
-
})
|
|
251
|
-
}
|
|
252
|
-
|
|
253
|
-
export const parseCommitUnauthenticated = async (
|
|
254
|
-
evt: com.atproto.sync.subscribeRepos.Commit,
|
|
255
|
-
matchCollection?: ((col: string) => boolean) | null,
|
|
256
|
-
): Promise<CommitEvt[]> => {
|
|
257
|
-
const ops = maybeFilterOps(evt.ops, matchCollection)
|
|
258
|
-
return formatCommitOps(evt, ops)
|
|
259
|
-
}
|
|
260
|
-
|
|
261
|
-
const maybeFilterOps = (
|
|
262
|
-
ops: com.atproto.sync.subscribeRepos.RepoOp[],
|
|
263
|
-
matchCollection?: ((col: string) => boolean) | null,
|
|
264
|
-
): com.atproto.sync.subscribeRepos.RepoOp[] => {
|
|
265
|
-
if (!matchCollection) return ops
|
|
266
|
-
return ops.filter((op) => {
|
|
267
|
-
const { collection } = parseDataKey(op.path)
|
|
268
|
-
return matchCollection(collection)
|
|
269
|
-
})
|
|
270
|
-
}
|
|
271
|
-
|
|
272
|
-
const formatCommitOps = async (
|
|
273
|
-
evt: com.atproto.sync.subscribeRepos.Commit,
|
|
274
|
-
ops: com.atproto.sync.subscribeRepos.RepoOp[],
|
|
275
|
-
options?: { skipCidVerification: boolean },
|
|
276
|
-
) => {
|
|
277
|
-
const car = await readCar(evt.blocks, options)
|
|
278
|
-
|
|
279
|
-
const evts: CommitEvt[] = []
|
|
280
|
-
|
|
281
|
-
for (const op of ops) {
|
|
282
|
-
const uri = AtUri.make(evt.repo, op.path)
|
|
283
|
-
|
|
284
|
-
const meta: CommitMeta = {
|
|
285
|
-
seq: evt.seq,
|
|
286
|
-
time: evt.time,
|
|
287
|
-
commit: evt.commit,
|
|
288
|
-
blocks: car.blocks,
|
|
289
|
-
rev: evt.rev,
|
|
290
|
-
uri,
|
|
291
|
-
did: uri.did,
|
|
292
|
-
collection: uri.collection,
|
|
293
|
-
rkey: uri.rkey,
|
|
294
|
-
}
|
|
295
|
-
|
|
296
|
-
if (op.action === 'create' || op.action === 'update') {
|
|
297
|
-
if (!op.cid) continue
|
|
298
|
-
const recordBytes = car.blocks.get(op.cid)
|
|
299
|
-
if (!recordBytes) continue
|
|
300
|
-
const record = cborToLexRecord(recordBytes)
|
|
301
|
-
evts.push({
|
|
302
|
-
...meta,
|
|
303
|
-
event: op.action as 'create' | 'update',
|
|
304
|
-
cid: op.cid,
|
|
305
|
-
record,
|
|
306
|
-
})
|
|
307
|
-
}
|
|
308
|
-
|
|
309
|
-
if (op.action === 'delete') {
|
|
310
|
-
evts.push({
|
|
311
|
-
...meta,
|
|
312
|
-
event: 'delete',
|
|
313
|
-
})
|
|
314
|
-
}
|
|
315
|
-
}
|
|
316
|
-
|
|
317
|
-
return evts
|
|
318
|
-
}
|
|
319
|
-
|
|
320
|
-
export const parseSync = async (
|
|
321
|
-
evt: com.atproto.sync.subscribeRepos.Sync,
|
|
322
|
-
): Promise<SyncEvt | null> => {
|
|
323
|
-
const car = await readCarWithRoot(evt.blocks)
|
|
324
|
-
|
|
325
|
-
return {
|
|
326
|
-
event: 'sync',
|
|
327
|
-
seq: evt.seq,
|
|
328
|
-
time: evt.time,
|
|
329
|
-
did: evt.did,
|
|
330
|
-
cid: car.root,
|
|
331
|
-
rev: evt.rev,
|
|
332
|
-
blocks: car.blocks,
|
|
333
|
-
}
|
|
334
|
-
}
|
|
335
|
-
|
|
336
|
-
export const parseIdentity = async (
|
|
337
|
-
idResolver: IdResolver,
|
|
338
|
-
evt: com.atproto.sync.subscribeRepos.Identity,
|
|
339
|
-
unauthenticated = false,
|
|
340
|
-
): Promise<IdentityEvt | null> => {
|
|
341
|
-
const res = await idResolver.did.resolve(evt.did)
|
|
342
|
-
const handle =
|
|
343
|
-
res && !unauthenticated
|
|
344
|
-
? await verifyHandle(idResolver, evt.did, res)
|
|
345
|
-
: undefined
|
|
346
|
-
|
|
347
|
-
return {
|
|
348
|
-
event: 'identity',
|
|
349
|
-
seq: evt.seq,
|
|
350
|
-
time: evt.time,
|
|
351
|
-
did: evt.did,
|
|
352
|
-
handle,
|
|
353
|
-
didDocument: res ?? undefined,
|
|
354
|
-
}
|
|
355
|
-
}
|
|
356
|
-
|
|
357
|
-
const verifyHandle = async (
|
|
358
|
-
idResolver: IdResolver,
|
|
359
|
-
did: string,
|
|
360
|
-
didDoc: DidDocument,
|
|
361
|
-
): Promise<string | undefined> => {
|
|
362
|
-
const { handle } = parseToAtprotoDocument(didDoc)
|
|
363
|
-
if (!handle) {
|
|
364
|
-
return undefined
|
|
365
|
-
}
|
|
366
|
-
const res = await idResolver.handle.resolve(handle)
|
|
367
|
-
return res === did ? handle : undefined
|
|
368
|
-
}
|
|
369
|
-
|
|
370
|
-
export const parseAccount = (
|
|
371
|
-
evt: com.atproto.sync.subscribeRepos.Account,
|
|
372
|
-
): AccountEvt | undefined => {
|
|
373
|
-
if (evt.status && !isValidStatus(evt.status)) return
|
|
374
|
-
return {
|
|
375
|
-
event: 'account',
|
|
376
|
-
seq: evt.seq,
|
|
377
|
-
time: evt.time,
|
|
378
|
-
did: evt.did,
|
|
379
|
-
active: evt.active,
|
|
380
|
-
status: evt.status as AccountStatus | undefined,
|
|
381
|
-
}
|
|
382
|
-
}
|
|
383
|
-
|
|
384
|
-
const isValidStatus = (str: string): str is AccountStatus => {
|
|
385
|
-
return ['takendown', 'suspended', 'deleted', 'deactivated'].includes(str)
|
|
386
|
-
}
|
|
387
|
-
|
|
388
|
-
export class FirehoseValidationError extends Error {
|
|
389
|
-
constructor(
|
|
390
|
-
err: unknown,
|
|
391
|
-
public value: unknown,
|
|
392
|
-
) {
|
|
393
|
-
super('error in firehose event lexicon validation', { cause: err })
|
|
394
|
-
}
|
|
395
|
-
}
|
|
396
|
-
|
|
397
|
-
export class FirehoseParseError extends Error {
|
|
398
|
-
constructor(
|
|
399
|
-
err: unknown,
|
|
400
|
-
public event: com.atproto.sync.subscribeRepos.$Message,
|
|
401
|
-
) {
|
|
402
|
-
super('error in parsing and authenticating firehose event', { cause: err })
|
|
403
|
-
}
|
|
404
|
-
}
|
|
405
|
-
|
|
406
|
-
export class FirehoseSubscriptionError extends Error {
|
|
407
|
-
constructor(err: unknown) {
|
|
408
|
-
super('error on firehose subscription', { cause: err })
|
|
409
|
-
}
|
|
410
|
-
}
|
|
411
|
-
|
|
412
|
-
export class FirehoseHandlerError extends Error {
|
|
413
|
-
constructor(
|
|
414
|
-
err: unknown,
|
|
415
|
-
public event: Event,
|
|
416
|
-
) {
|
|
417
|
-
super('error in firehose event handler', { cause: err })
|
|
418
|
-
}
|
|
419
|
-
}
|
package/src/index.ts
DELETED
|
@@ -1,44 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Add items to a list, and mark those items as
|
|
3
|
-
* completed. Upon item completion, get list of consecutive
|
|
4
|
-
* items completed at the head of the list. Example:
|
|
5
|
-
*
|
|
6
|
-
* const consecutive = new ConsecutiveList<number>()
|
|
7
|
-
* const item1 = consecutive.push(1)
|
|
8
|
-
* const item2 = consecutive.push(2)
|
|
9
|
-
* const item3 = consecutive.push(3)
|
|
10
|
-
* item2.complete() // []
|
|
11
|
-
* item1.complete() // [1, 2]
|
|
12
|
-
* item3.complete() // [3]
|
|
13
|
-
*
|
|
14
|
-
*/
|
|
15
|
-
export class ConsecutiveList<T> {
|
|
16
|
-
list: ConsecutiveItem<T>[] = []
|
|
17
|
-
|
|
18
|
-
push(value: T) {
|
|
19
|
-
const item = new ConsecutiveItem<T>(this, value)
|
|
20
|
-
this.list.push(item)
|
|
21
|
-
return item
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
complete(): T[] {
|
|
25
|
-
let i = 0
|
|
26
|
-
while (this.list[i]?.isComplete) {
|
|
27
|
-
i += 1
|
|
28
|
-
}
|
|
29
|
-
return this.list.splice(0, i).map((item) => item.value)
|
|
30
|
-
}
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
export class ConsecutiveItem<T> {
|
|
34
|
-
isComplete = false
|
|
35
|
-
constructor(
|
|
36
|
-
private consecutive: ConsecutiveList<T>,
|
|
37
|
-
public value: T,
|
|
38
|
-
) {}
|
|
39
|
-
|
|
40
|
-
complete() {
|
|
41
|
-
this.isComplete = true
|
|
42
|
-
return this.consecutive.complete()
|
|
43
|
-
}
|
|
44
|
-
}
|
package/src/runner/index.ts
DELETED
|
@@ -1,79 +0,0 @@
|
|
|
1
|
-
import PQueue from 'p-queue'
|
|
2
|
-
import { ConsecutiveList } from './consecutive-list.js'
|
|
3
|
-
import { EventRunner } from './types.js'
|
|
4
|
-
|
|
5
|
-
export type MemoryRunnerOptions = {
|
|
6
|
-
setCursor?: (cursor: number) => Promise<void>
|
|
7
|
-
concurrency?: number
|
|
8
|
-
startCursor?: number
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
type Queue = InstanceType<typeof PQueue>
|
|
12
|
-
|
|
13
|
-
// A queue with arbitrarily many partitions, each processing work sequentially.
|
|
14
|
-
// Partitions are created lazily and taken out of memory when they go idle.
|
|
15
|
-
export class MemoryRunner implements EventRunner {
|
|
16
|
-
private destroyed = false
|
|
17
|
-
private readonly consecutive = new ConsecutiveList<number>()
|
|
18
|
-
private readonly mainQueue: Queue
|
|
19
|
-
private readonly partitions: Map<string, Queue> = new Map()
|
|
20
|
-
private cursor: number | undefined
|
|
21
|
-
|
|
22
|
-
constructor(public opts: MemoryRunnerOptions = {}) {
|
|
23
|
-
this.mainQueue = new PQueue({ concurrency: opts.concurrency ?? Infinity })
|
|
24
|
-
this.cursor = opts.startCursor
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
getCursor() {
|
|
28
|
-
return this.cursor
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
/** @deprecated internal use only */
|
|
32
|
-
get partitionCount() {
|
|
33
|
-
return this.partitions.size
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
async addTask(partitionId: string, task: () => Promise<void>) {
|
|
37
|
-
if (this.destroyed) return
|
|
38
|
-
return this.mainQueue.add(() => {
|
|
39
|
-
return this.getPartition(partitionId).add(task)
|
|
40
|
-
})
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
private getPartition(partitionId: string) {
|
|
44
|
-
let partition = this.partitions.get(partitionId)
|
|
45
|
-
if (!partition) {
|
|
46
|
-
partition = new PQueue({ concurrency: 1 })
|
|
47
|
-
partition.once('idle', () => this.partitions.delete(partitionId))
|
|
48
|
-
this.partitions.set(partitionId, partition)
|
|
49
|
-
}
|
|
50
|
-
return partition
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
async trackEvent(did: string, seq: number, handler: () => Promise<void>) {
|
|
54
|
-
if (this.destroyed) return
|
|
55
|
-
const item = this.consecutive.push(seq)
|
|
56
|
-
await this.addTask(did, async () => {
|
|
57
|
-
await handler()
|
|
58
|
-
const latest = item.complete().at(-1)
|
|
59
|
-
if (latest !== undefined) {
|
|
60
|
-
this.cursor = latest
|
|
61
|
-
if (this.opts.setCursor) {
|
|
62
|
-
await this.opts.setCursor(this.cursor)
|
|
63
|
-
}
|
|
64
|
-
}
|
|
65
|
-
})
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
async processAll() {
|
|
69
|
-
const queue = this.mainQueue
|
|
70
|
-
while (queue.size || queue.pending) await queue.onIdle()
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
async destroy() {
|
|
74
|
-
this.destroyed = true
|
|
75
|
-
this.mainQueue.clear()
|
|
76
|
-
this.partitions.forEach((p) => p.clear())
|
|
77
|
-
await this.processAll()
|
|
78
|
-
}
|
|
79
|
-
}
|
package/src/runner/types.ts
DELETED
package/src/util.ts
DELETED
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
import { com } from './lexicons/index.js'
|
|
2
|
-
|
|
3
|
-
export const didAndSeqForEvt = (
|
|
4
|
-
evt: com.atproto.sync.subscribeRepos.$Message,
|
|
5
|
-
): { did: string; seq: number } | undefined => {
|
|
6
|
-
if (com.atproto.sync.subscribeRepos.commit.$isTypeOf(evt)) {
|
|
7
|
-
return { seq: evt.seq, did: evt.repo }
|
|
8
|
-
} else if (
|
|
9
|
-
com.atproto.sync.subscribeRepos.account.$isTypeOf(evt) ||
|
|
10
|
-
com.atproto.sync.subscribeRepos.identity.$isTypeOf(evt) ||
|
|
11
|
-
com.atproto.sync.subscribeRepos.sync.$isTypeOf(evt)
|
|
12
|
-
) {
|
|
13
|
-
return { seq: evt.seq, did: evt.did }
|
|
14
|
-
}
|
|
15
|
-
return undefined
|
|
16
|
-
}
|
package/tests/firehose.test.ts
DELETED
|
@@ -1,197 +0,0 @@
|
|
|
1
|
-
import { createDeferrable, wait } from '@atproto/common'
|
|
2
|
-
import {
|
|
3
|
-
SeedClient,
|
|
4
|
-
TestNetworkNoAppView,
|
|
5
|
-
mockResolvers,
|
|
6
|
-
} from '@atproto/dev-env'
|
|
7
|
-
import { IdResolver } from '@atproto/identity'
|
|
8
|
-
import { DidString } from '@atproto/syntax'
|
|
9
|
-
import {
|
|
10
|
-
Create,
|
|
11
|
-
Event,
|
|
12
|
-
Firehose,
|
|
13
|
-
FirehoseOptions,
|
|
14
|
-
MemoryRunner,
|
|
15
|
-
} from '../src/index.js'
|
|
16
|
-
|
|
17
|
-
describe('firehose', () => {
|
|
18
|
-
let network: TestNetworkNoAppView
|
|
19
|
-
let sc: SeedClient
|
|
20
|
-
let idResolver: IdResolver
|
|
21
|
-
|
|
22
|
-
beforeAll(async () => {
|
|
23
|
-
network = await TestNetworkNoAppView.create({
|
|
24
|
-
dbPostgresSchema: 'sync_firehose',
|
|
25
|
-
})
|
|
26
|
-
idResolver = new IdResolver({ plcUrl: network.plc.url })
|
|
27
|
-
mockResolvers(idResolver, network.pds)
|
|
28
|
-
sc = network.getSeedClient()
|
|
29
|
-
})
|
|
30
|
-
|
|
31
|
-
afterAll(async () => {
|
|
32
|
-
await network?.close()
|
|
33
|
-
})
|
|
34
|
-
|
|
35
|
-
const createAndReadFirehose = async (
|
|
36
|
-
count: number,
|
|
37
|
-
opts: Partial<FirehoseOptions> = {},
|
|
38
|
-
addRandomWait = false,
|
|
39
|
-
): Promise<Event[]> => {
|
|
40
|
-
const defer = createDeferrable()
|
|
41
|
-
const evts: Event[] = []
|
|
42
|
-
const firehose = new Firehose({
|
|
43
|
-
idResolver,
|
|
44
|
-
service: network.pds.url.replace('http', 'ws'),
|
|
45
|
-
handleEvent: async (evt) => {
|
|
46
|
-
if (addRandomWait) {
|
|
47
|
-
const time = Math.floor(Math.random()) * 20
|
|
48
|
-
await wait(time)
|
|
49
|
-
}
|
|
50
|
-
evts.push(evt)
|
|
51
|
-
if (evts.length >= count) {
|
|
52
|
-
defer.resolve()
|
|
53
|
-
}
|
|
54
|
-
},
|
|
55
|
-
onError: (err) => {
|
|
56
|
-
defer.reject(err)
|
|
57
|
-
},
|
|
58
|
-
...opts,
|
|
59
|
-
})
|
|
60
|
-
try {
|
|
61
|
-
firehose.start()
|
|
62
|
-
await defer.complete
|
|
63
|
-
return evts
|
|
64
|
-
} finally {
|
|
65
|
-
await firehose.destroy()
|
|
66
|
-
}
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
let alice: DidString
|
|
70
|
-
|
|
71
|
-
it('reads events from firehose', async () => {
|
|
72
|
-
const evtsPromise = createAndReadFirehose(6)
|
|
73
|
-
await wait(10) // give the websocket just a second to spin up
|
|
74
|
-
const aliceRes = await sc.createAccount('alice', {
|
|
75
|
-
handle: 'alice.test',
|
|
76
|
-
email: 'alice@test.com',
|
|
77
|
-
password: 'alice-pass',
|
|
78
|
-
})
|
|
79
|
-
alice = aliceRes.did
|
|
80
|
-
await sc.post(alice, 'one')
|
|
81
|
-
await sc.post(alice, 'two')
|
|
82
|
-
await sc.post(alice, 'three')
|
|
83
|
-
|
|
84
|
-
const evts = await evtsPromise
|
|
85
|
-
expect(evts.length).toBe(6)
|
|
86
|
-
expect(evts.at(0)).toMatchObject({
|
|
87
|
-
event: 'identity',
|
|
88
|
-
did: alice,
|
|
89
|
-
handle: aliceRes.handle,
|
|
90
|
-
didDocument: {
|
|
91
|
-
id: alice,
|
|
92
|
-
},
|
|
93
|
-
})
|
|
94
|
-
expect(evts.at(1)).toMatchObject({
|
|
95
|
-
event: 'account',
|
|
96
|
-
did: alice,
|
|
97
|
-
active: true,
|
|
98
|
-
status: undefined,
|
|
99
|
-
})
|
|
100
|
-
expect(evts.at(2)).toMatchObject({
|
|
101
|
-
event: 'sync',
|
|
102
|
-
did: alice,
|
|
103
|
-
})
|
|
104
|
-
expect(evts.at(3)).toMatchObject({
|
|
105
|
-
event: 'create',
|
|
106
|
-
did: alice,
|
|
107
|
-
collection: 'app.bsky.feed.post',
|
|
108
|
-
record: {
|
|
109
|
-
text: 'one',
|
|
110
|
-
},
|
|
111
|
-
})
|
|
112
|
-
expect(evts.at(4)).toMatchObject({
|
|
113
|
-
event: 'create',
|
|
114
|
-
did: alice,
|
|
115
|
-
collection: 'app.bsky.feed.post',
|
|
116
|
-
record: {
|
|
117
|
-
text: 'two',
|
|
118
|
-
},
|
|
119
|
-
})
|
|
120
|
-
expect(evts.at(5)).toMatchObject({
|
|
121
|
-
event: 'create',
|
|
122
|
-
did: alice,
|
|
123
|
-
collection: 'app.bsky.feed.post',
|
|
124
|
-
record: {
|
|
125
|
-
text: 'three',
|
|
126
|
-
},
|
|
127
|
-
})
|
|
128
|
-
})
|
|
129
|
-
|
|
130
|
-
it('does not naively pass through invalid handle evts', async () => {
|
|
131
|
-
const evtsPromise = createAndReadFirehose(1)
|
|
132
|
-
await wait(10) // give the websocket just a second to spin up
|
|
133
|
-
await network.pds.ctx.sequencer.sequenceIdentity(alice, 'bad-handle.test')
|
|
134
|
-
const evts = await evtsPromise
|
|
135
|
-
expect(evts.at(0)).toMatchObject({ handle: 'alice.test' })
|
|
136
|
-
})
|
|
137
|
-
|
|
138
|
-
it('processes events through the sync queue', async () => {
|
|
139
|
-
const currCursor = await network.pds.ctx.sequencer.curr()
|
|
140
|
-
const runner = new MemoryRunner({
|
|
141
|
-
startCursor: currCursor ?? undefined,
|
|
142
|
-
})
|
|
143
|
-
const evtsPromise = createAndReadFirehose(24, { runner }, true)
|
|
144
|
-
const createAndPost = async (name: string) => {
|
|
145
|
-
const user = await sc.createAccount('name', {
|
|
146
|
-
handle: `${name}.test`,
|
|
147
|
-
email: `${name}@example.com`,
|
|
148
|
-
password: `${name}-pass`,
|
|
149
|
-
})
|
|
150
|
-
const did = user.did
|
|
151
|
-
const post1 = await sc.post(did, 'one')
|
|
152
|
-
const post2 = await sc.post(did, 'two')
|
|
153
|
-
const post3 = await sc.post(did, 'three')
|
|
154
|
-
return {
|
|
155
|
-
did,
|
|
156
|
-
post1: post1.ref.uriStr,
|
|
157
|
-
post2: post2.ref.uriStr,
|
|
158
|
-
post3: post3.ref.uriStr,
|
|
159
|
-
}
|
|
160
|
-
}
|
|
161
|
-
const res = await Promise.all([
|
|
162
|
-
createAndPost('user1'),
|
|
163
|
-
createAndPost('user2'),
|
|
164
|
-
createAndPost('user3'),
|
|
165
|
-
createAndPost('user4'),
|
|
166
|
-
])
|
|
167
|
-
const evts = await evtsPromise
|
|
168
|
-
const user1Evts = evts.filter((e) => e.did === res[0].did)
|
|
169
|
-
const user2Evts = evts.filter((e) => e.did === res[1].did)
|
|
170
|
-
const user3Evts = evts.filter((e) => e.did === res[2].did)
|
|
171
|
-
const user4Evts = evts.filter((e) => e.did === res[3].did)
|
|
172
|
-
const EVT_ORDER = [
|
|
173
|
-
'identity',
|
|
174
|
-
'account',
|
|
175
|
-
'sync',
|
|
176
|
-
'create',
|
|
177
|
-
'create',
|
|
178
|
-
'create',
|
|
179
|
-
]
|
|
180
|
-
expect(user1Evts.map((e) => e.event)).toEqual(EVT_ORDER)
|
|
181
|
-
expect(user2Evts.map((e) => e.event)).toEqual(EVT_ORDER)
|
|
182
|
-
expect(user3Evts.map((e) => e.event)).toEqual(EVT_ORDER)
|
|
183
|
-
expect(user4Evts.map((e) => e.event)).toEqual(EVT_ORDER)
|
|
184
|
-
expect(
|
|
185
|
-
user1Evts.slice(3, 6).map((e) => (e as Create).uri.toString()),
|
|
186
|
-
).toEqual([res[0].post1, res[0].post2, res[0].post3])
|
|
187
|
-
expect(
|
|
188
|
-
user2Evts.slice(3, 6).map((e) => (e as Create).uri.toString()),
|
|
189
|
-
).toEqual([res[1].post1, res[1].post2, res[1].post3])
|
|
190
|
-
expect(
|
|
191
|
-
user3Evts.slice(3, 6).map((e) => (e as Create).uri.toString()),
|
|
192
|
-
).toEqual([res[2].post1, res[2].post2, res[2].post3])
|
|
193
|
-
expect(
|
|
194
|
-
user4Evts.slice(3, 6).map((e) => (e as Create).uri.toString()),
|
|
195
|
-
).toEqual([res[3].post1, res[3].post2, res[3].post3])
|
|
196
|
-
})
|
|
197
|
-
})
|
package/tests/runner.test.ts
DELETED
|
@@ -1,129 +0,0 @@
|
|
|
1
|
-
import { wait } from '@atproto/common'
|
|
2
|
-
import { ConsecutiveList, MemoryRunner } from '../src/index.js'
|
|
3
|
-
|
|
4
|
-
describe('EventRunner utils', () => {
|
|
5
|
-
describe('ConsecutiveList', () => {
|
|
6
|
-
it('tracks consecutive complete items.', () => {
|
|
7
|
-
const consecutive = new ConsecutiveList<number>()
|
|
8
|
-
// add items
|
|
9
|
-
const item1 = consecutive.push(1)
|
|
10
|
-
const item2 = consecutive.push(2)
|
|
11
|
-
const item3 = consecutive.push(3)
|
|
12
|
-
expect(item1.isComplete).toEqual(false)
|
|
13
|
-
expect(item2.isComplete).toEqual(false)
|
|
14
|
-
expect(item3.isComplete).toEqual(false)
|
|
15
|
-
// complete items out of order
|
|
16
|
-
expect(consecutive.list.length).toBe(3)
|
|
17
|
-
expect(item2.complete()).toEqual([])
|
|
18
|
-
expect(item2.isComplete).toEqual(true)
|
|
19
|
-
expect(consecutive.list.length).toBe(3)
|
|
20
|
-
expect(item1.complete()).toEqual([1, 2])
|
|
21
|
-
expect(item1.isComplete).toEqual(true)
|
|
22
|
-
expect(consecutive.list.length).toBe(1)
|
|
23
|
-
expect(item3.complete()).toEqual([3])
|
|
24
|
-
expect(consecutive.list.length).toBe(0)
|
|
25
|
-
expect(item3.isComplete).toEqual(true)
|
|
26
|
-
})
|
|
27
|
-
})
|
|
28
|
-
|
|
29
|
-
describe('MemoryRunner', () => {
|
|
30
|
-
it('performs work in parallel across partitions, serial within a partition.', async () => {
|
|
31
|
-
const runner = new MemoryRunner({ concurrency: Infinity })
|
|
32
|
-
const complete: {
|
|
33
|
-
1: number[]
|
|
34
|
-
2: number[]
|
|
35
|
-
} = {
|
|
36
|
-
1: [],
|
|
37
|
-
2: [],
|
|
38
|
-
}
|
|
39
|
-
// partition 1 items start slow but get faster: slow should still complete first.
|
|
40
|
-
runner.addTask('1', async () => {
|
|
41
|
-
await wait(30)
|
|
42
|
-
complete[1].push(1)
|
|
43
|
-
})
|
|
44
|
-
runner.addTask('1', async () => {
|
|
45
|
-
await wait(20)
|
|
46
|
-
complete[1].push(2)
|
|
47
|
-
})
|
|
48
|
-
runner.addTask('1', async () => {
|
|
49
|
-
complete[1].push(3)
|
|
50
|
-
})
|
|
51
|
-
expect(runner.partitionCount).toEqual(1)
|
|
52
|
-
// partition 2 items complete quickly except the last, which is slowest of all events.
|
|
53
|
-
runner.addTask('2', async () => {
|
|
54
|
-
await wait(1)
|
|
55
|
-
complete[2].push(1)
|
|
56
|
-
})
|
|
57
|
-
runner.addTask('2', async () => {
|
|
58
|
-
await wait(1)
|
|
59
|
-
complete[2].push(2)
|
|
60
|
-
})
|
|
61
|
-
runner.addTask('2', async () => {
|
|
62
|
-
complete[2].push(3)
|
|
63
|
-
})
|
|
64
|
-
runner.addTask('2', async () => {
|
|
65
|
-
await wait(60)
|
|
66
|
-
complete[2].push(4)
|
|
67
|
-
})
|
|
68
|
-
expect(runner.partitionCount).toEqual(2)
|
|
69
|
-
await runner.processAll()
|
|
70
|
-
expect(complete).toEqual({
|
|
71
|
-
1: [1, 2, 3],
|
|
72
|
-
2: [1, 2, 3, 4],
|
|
73
|
-
})
|
|
74
|
-
expect(runner.partitionCount).toEqual(0)
|
|
75
|
-
})
|
|
76
|
-
|
|
77
|
-
it('limits overall concurrency.', async () => {
|
|
78
|
-
const runner = new MemoryRunner({ concurrency: 1 })
|
|
79
|
-
const complete: number[] = []
|
|
80
|
-
// if concurrency were not constrained, partition 1 would complete all items
|
|
81
|
-
// before any items from partition 2. since it is constrained, the work is complete in the order added.
|
|
82
|
-
runner.addTask('1', async () => {
|
|
83
|
-
await wait(1)
|
|
84
|
-
complete.push(11)
|
|
85
|
-
})
|
|
86
|
-
runner.addTask('2', async () => {
|
|
87
|
-
await wait(10)
|
|
88
|
-
complete.push(21)
|
|
89
|
-
})
|
|
90
|
-
runner.addTask('1', async () => {
|
|
91
|
-
await wait(1)
|
|
92
|
-
complete.push(12)
|
|
93
|
-
})
|
|
94
|
-
runner.addTask('2', async () => {
|
|
95
|
-
await wait(10)
|
|
96
|
-
complete.push(22)
|
|
97
|
-
})
|
|
98
|
-
// only partition 1 exists so far due to the concurrency
|
|
99
|
-
expect(runner.partitionCount).toEqual(1)
|
|
100
|
-
await runner.processAll()
|
|
101
|
-
expect(complete).toEqual([11, 21, 12, 22])
|
|
102
|
-
expect(runner.partitionCount).toEqual(0)
|
|
103
|
-
})
|
|
104
|
-
|
|
105
|
-
it('settles with many items.', async () => {
|
|
106
|
-
const runner = new MemoryRunner({ concurrency: 100 })
|
|
107
|
-
const complete: { partition: string; id: number }[] = []
|
|
108
|
-
const partitions = new Set<string>()
|
|
109
|
-
for (let i = 0; i < 500; ++i) {
|
|
110
|
-
const partition = Math.floor(Math.random() * 16).toString(10)
|
|
111
|
-
partitions.add(partition)
|
|
112
|
-
runner.addTask(partition, async () => {
|
|
113
|
-
await wait((i % 2) * 2)
|
|
114
|
-
complete.push({ partition, id: i })
|
|
115
|
-
})
|
|
116
|
-
}
|
|
117
|
-
expect(runner.partitionCount).toBeLessThanOrEqual(partitions.size)
|
|
118
|
-
await runner.processAll()
|
|
119
|
-
expect(complete.length).toEqual(500)
|
|
120
|
-
for (const partition of partitions) {
|
|
121
|
-
const ids = complete
|
|
122
|
-
.filter((item) => item.partition === partition)
|
|
123
|
-
.map((item) => item.id)
|
|
124
|
-
expect(ids).toEqual([...ids].sort((a, b) => a - b))
|
|
125
|
-
}
|
|
126
|
-
expect(runner.partitionCount).toEqual(0)
|
|
127
|
-
})
|
|
128
|
-
})
|
|
129
|
-
})
|
package/tsconfig.build.json
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":"7.0.0-dev.20260614.1","root":["./src/events.ts","./src/index.ts","./src/util.ts","./src/firehose/index.ts","./src/lexicons/com.ts","./src/lexicons/index.ts","./src/lexicons/com/atproto.ts","./src/lexicons/com/atproto/sync.ts","./src/lexicons/com/atproto/sync/subscribeRepos.defs.ts","./src/lexicons/com/atproto/sync/subscribeRepos.ts","./src/runner/consecutive-list.ts","./src/runner/index.ts","./src/runner/memory-runner.ts","./src/runner/types.ts"]}
|
package/tsconfig.json
DELETED