@dxos/teleport-extension-object-sync 0.3.8-next.f4e0086 → 0.3.8

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.
@@ -18,7 +18,7 @@ function _ts_decorate(decorators, target, key, desc) {
18
18
  r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
19
19
  return c > 3 && r && Object.defineProperty(target, key, r), r;
20
20
  }
21
- var __dxlog_file = "/home/runner/work/dxos/dxos/packages/core/mesh/teleport-extension-object-sync/src/blob-sync-extension.ts";
21
+ var __dxlog_file = "/home/circleci/project/packages/core/mesh/teleport-extension-object-sync/src/blob-sync-extension.ts";
22
22
  var MIN_WANT_LIST_UPDATE_INTERVAL = false ? 5 : 500;
23
23
  var MAX_CONCURRENT_UPLOADS = 20;
24
24
  var BlobSyncExtension = class extends RpcExtension {
@@ -39,7 +39,7 @@ var BlobSyncExtension = class extends RpcExtension {
39
39
  this._ctx = new Context({
40
40
  onError: (err) => log.catch(err, void 0, {
41
41
  F: __dxlog_file,
42
- L: 33,
42
+ L: 34,
43
43
  S: this,
44
44
  C: (f, a) => f(...a)
45
45
  })
@@ -59,7 +59,7 @@ var BlobSyncExtension = class extends RpcExtension {
59
59
  list: this._localWantList
60
60
  }, {
61
61
  F: __dxlog_file,
62
- L: 47,
62
+ L: 48,
63
63
  S: this,
64
64
  C: (f, a) => f(...a)
65
65
  });
@@ -88,7 +88,7 @@ var BlobSyncExtension = class extends RpcExtension {
88
88
  err
89
89
  }, {
90
90
  F: __dxlog_file,
91
- L: 74,
91
+ L: 75,
92
92
  S: this,
93
93
  C: (f, a) => f(...a)
94
94
  });
@@ -105,7 +105,7 @@ var BlobSyncExtension = class extends RpcExtension {
105
105
  async onOpen(context) {
106
106
  log("open", void 0, {
107
107
  F: __dxlog_file,
108
- L: 106,
108
+ L: 107,
109
109
  S: this,
110
110
  C: (f, a) => f(...a)
111
111
  });
@@ -115,7 +115,7 @@ var BlobSyncExtension = class extends RpcExtension {
115
115
  async onClose(err) {
116
116
  log("close", void 0, {
117
117
  F: __dxlog_file,
118
- L: 112,
118
+ L: 113,
119
119
  S: this,
120
120
  C: (f, a) => f(...a)
121
121
  });
@@ -123,6 +123,17 @@ var BlobSyncExtension = class extends RpcExtension {
123
123
  await this._params.onClose();
124
124
  await super.onClose(err);
125
125
  }
126
+ async onAbort(err) {
127
+ log("abort", void 0, {
128
+ F: __dxlog_file,
129
+ L: 120,
130
+ S: this,
131
+ C: (f, a) => f(...a)
132
+ });
133
+ await this._ctx.dispose();
134
+ await this._params.onAbort();
135
+ await super.onAbort(err);
136
+ }
126
137
  async getHandlers() {
127
138
  return {
128
139
  BlobSyncService: {
@@ -131,7 +142,7 @@ var BlobSyncExtension = class extends RpcExtension {
131
142
  remoteWantList: wantList
132
143
  }, {
133
144
  F: __dxlog_file,
134
- L: 122,
145
+ L: 130,
135
146
  S: this,
136
147
  C: (f, a) => f(...a)
137
148
  });
@@ -143,7 +154,7 @@ var BlobSyncExtension = class extends RpcExtension {
143
154
  data
144
155
  }, {
145
156
  F: __dxlog_file,
146
- L: 127,
157
+ L: 135,
147
158
  S: this,
148
159
  C: (f, a) => f(...a)
149
160
  });
@@ -160,7 +171,7 @@ var BlobSyncExtension = class extends RpcExtension {
160
171
  data
161
172
  }, {
162
173
  F: __dxlog_file,
163
- L: 139,
174
+ L: 147,
164
175
  S: this,
165
176
  C: (f, a) => f(...a)
166
177
  });
@@ -197,7 +208,7 @@ var BlobSyncExtension = class extends RpcExtension {
197
208
  }
198
209
  invariant(meta.bitfield, void 0, {
199
210
  F: __dxlog_file,
200
- L: 178,
211
+ L: 186,
201
212
  S: this,
202
213
  A: [
203
214
  "meta.bitfield",
@@ -206,7 +217,7 @@ var BlobSyncExtension = class extends RpcExtension {
206
217
  });
207
218
  invariant(meta.chunkSize, void 0, {
208
219
  F: __dxlog_file,
209
- L: 179,
220
+ L: 187,
210
221
  S: this,
211
222
  A: [
212
223
  "meta.chunkSize",
@@ -215,7 +226,7 @@ var BlobSyncExtension = class extends RpcExtension {
215
226
  });
216
227
  invariant(meta.length, void 0, {
217
228
  F: __dxlog_file,
218
- L: 180,
229
+ L: 188,
219
230
  S: this,
220
231
  A: [
221
232
  "meta.length",
@@ -228,7 +239,7 @@ var BlobSyncExtension = class extends RpcExtension {
228
239
  meta
229
240
  }, {
230
241
  F: __dxlog_file,
231
- L: 183,
242
+ L: 191,
232
243
  S: this,
233
244
  C: (f, a) => f(...a)
234
245
  });
@@ -279,7 +290,7 @@ function _ts_decorate2(decorators, target, key, desc) {
279
290
  r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
280
291
  return c > 3 && r && Object.defineProperty(target, key, r), r;
281
292
  }
282
- var __dxlog_file2 = "/home/runner/work/dxos/dxos/packages/core/mesh/teleport-extension-object-sync/src/blob-sync.ts";
293
+ var __dxlog_file2 = "/home/circleci/project/packages/core/mesh/teleport-extension-object-sync/src/blob-sync.ts";
283
294
  var BlobSync = class BlobSync2 {
284
295
  constructor(_params) {
285
296
  this._params = _params;
@@ -365,6 +376,15 @@ var BlobSync = class BlobSync2 {
365
376
  });
366
377
  this._extensions.delete(extension);
367
378
  },
379
+ onAbort: async () => {
380
+ log2("extension aborted", void 0, {
381
+ F: __dxlog_file2,
382
+ L: 114,
383
+ S: this,
384
+ C: (f, a) => f(...a)
385
+ });
386
+ this._extensions.delete(extension);
387
+ },
368
388
  onPush: async (blobChunk) => {
369
389
  if (!this._downloadRequests.has(blobChunk.id)) {
370
390
  return;
@@ -373,7 +393,7 @@ var BlobSync = class BlobSync2 {
373
393
  blobChunk
374
394
  }, {
375
395
  F: __dxlog_file2,
376
- L: 117,
396
+ L: 121,
377
397
  S: this,
378
398
  C: (f, a) => f(...a)
379
399
  });
@@ -384,7 +404,7 @@ var BlobSync = class BlobSync2 {
384
404
  } else {
385
405
  invariant2(meta.bitfield, void 0, {
386
406
  F: __dxlog_file2,
387
- L: 123,
407
+ L: 127,
388
408
  S: this,
389
409
  A: [
390
410
  "meta.bitfield",
@@ -444,7 +464,7 @@ function _ts_decorate3(decorators, target, key, desc) {
444
464
  r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
445
465
  return c > 3 && r && Object.defineProperty(target, key, r), r;
446
466
  }
447
- var __dxlog_file3 = "/home/runner/work/dxos/dxos/packages/core/mesh/teleport-extension-object-sync/src/blob-store.ts";
467
+ var __dxlog_file3 = "/home/circleci/project/packages/core/mesh/teleport-extension-object-sync/src/blob-store.ts";
448
468
  var DEFAULT_CHUNK_SIZE = 4096;
449
469
  var BlobMetaCodec = schema2.getCodecForType("dxos.echo.blob.BlobMeta");
450
470
  var BlobStore = class {
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../src/blob-sync-extension.ts", "../../../src/blob-sync.ts", "../../../src/blob-store.ts"],
4
- "sourcesContent": ["//\n\n//\n// Copyright 2023 DXOS.org\n//\n\nimport { DeferredTask, sleep, synchronized } from '@dxos/async';\nimport { Context } from '@dxos/context';\nimport { invariant } from '@dxos/invariant';\nimport { log } from '@dxos/log';\nimport { RpcClosedError, schema } from '@dxos/protocols';\nimport { type BlobChunk, type BlobSyncService, type WantList } from '@dxos/protocols/proto/dxos/mesh/teleport/blobsync';\nimport { type ExtensionContext, RpcExtension } from '@dxos/teleport';\nimport { BitField } from '@dxos/util';\n\nimport { type BlobStore } from './blob-store';\n\nexport type BlobSyncExtensionParams = {\n blobStore: BlobStore;\n onOpen: () => Promise<void>;\n onClose: () => Promise<void>;\n onPush: (data: BlobChunk) => Promise<void>;\n};\n\nconst MIN_WANT_LIST_UPDATE_INTERVAL = process.env.NODE_ENV === 'test' ? 5 : 500;\n\nconst MAX_CONCURRENT_UPLOADS = 20;\n\n/**\n * Manages replication between a set of feeds for a single teleport session.\n */\nexport class BlobSyncExtension extends RpcExtension<ServiceBundle, ServiceBundle> {\n private readonly _ctx = new Context({ onError: (err) => log.catch(err) });\n\n private _lastWantListUpdate = 0;\n private _localWantList: WantList = { blobs: [] };\n\n private readonly _updateWantList = new DeferredTask(this._ctx, async () => {\n // Throttle want list updates.\n if (this._lastWantListUpdate + MIN_WANT_LIST_UPDATE_INTERVAL > Date.now()) {\n await sleep(this._lastWantListUpdate + MIN_WANT_LIST_UPDATE_INTERVAL - Date.now());\n if (this._ctx.disposed) {\n return;\n }\n }\n\n log('want', { list: this._localWantList });\n await this.rpc.BlobSyncService.want(this._localWantList);\n this._lastWantListUpdate = Date.now();\n });\n\n private _currentUploads = 0;\n\n private readonly _upload = new DeferredTask(this._ctx, async () => {\n if (this._currentUploads >= MAX_CONCURRENT_UPLOADS) {\n return;\n }\n const blobChunks = await this._pickBlobChunks(MAX_CONCURRENT_UPLOADS - this._currentUploads);\n if (!blobChunks) {\n return;\n }\n for (const blobChunk of blobChunks) {\n if (this._ctx.disposed) {\n break;\n }\n\n this._currentUploads++;\n\n this.push(blobChunk)\n .catch((err) => {\n if (err instanceof RpcClosedError) {\n return;\n }\n log.warn('push failed', { err });\n })\n .finally(() => {\n this._currentUploads--;\n this.reconcileUploads();\n });\n }\n });\n\n /**\n * Set of id's remote peer wants.\n */\n public remoteWantList: WantList = { blobs: [] };\n\n constructor(\n private readonly _params: BlobSyncExtensionParams, // to not conflict with the base class\n ) {\n super({\n exposed: {\n BlobSyncService: schema.getService('dxos.mesh.teleport.blobsync.BlobSyncService'),\n },\n requested: {\n BlobSyncService: schema.getService('dxos.mesh.teleport.blobsync.BlobSyncService'),\n },\n timeout: 20_000,\n encodingOptions: {\n preserveAny: true,\n },\n });\n }\n\n override async onOpen(context: ExtensionContext): Promise<void> {\n log('open');\n await super.onOpen(context);\n await this._params.onOpen();\n }\n\n override async onClose(err?: Error | undefined): Promise<void> {\n log('close');\n await this._ctx.dispose();\n await this._params.onClose();\n await super.onClose(err);\n }\n\n protected async getHandlers(): Promise<ServiceBundle> {\n return {\n BlobSyncService: {\n want: async (wantList) => {\n log('remote want', { remoteWantList: wantList });\n this.remoteWantList = wantList;\n this.reconcileUploads();\n },\n push: async (data) => {\n log('received', { data });\n await this._params.onPush(data);\n },\n },\n };\n }\n\n @synchronized\n async push(data: BlobChunk) {\n if (this._ctx.disposed) {\n return;\n }\n log('push', { data });\n await this.rpc.BlobSyncService.push(data);\n }\n\n updateWantList(wantList: WantList) {\n if (this._ctx.disposed) {\n return;\n }\n this._localWantList = wantList;\n this._updateWantList.schedule();\n }\n\n reconcileUploads() {\n if (this._ctx.disposed) {\n return;\n }\n this._upload.schedule();\n }\n\n private async _pickBlobChunks(amount = 1): Promise<BlobChunk[] | void> {\n if (this._ctx.disposed) {\n return;\n }\n\n if (!this.remoteWantList.blobs || this.remoteWantList.blobs?.length === 0) {\n return;\n }\n\n const shuffled = [...this.remoteWantList.blobs].sort(() => Math.random() - 0.5);\n\n const chunks: BlobChunk[] = [];\n\n for (const header of shuffled) {\n const meta = await this._params.blobStore.getMeta(header.id);\n\n if (!meta) {\n // Skip this header\n continue;\n }\n invariant(meta.bitfield);\n invariant(meta.chunkSize);\n invariant(meta.length);\n\n if (header.chunkSize && header.chunkSize !== meta.chunkSize) {\n log.warn('Invalid chunk size', { header, meta });\n continue;\n }\n\n const requestBitfield = header.bitfield ?? BitField.ones(meta.length / meta.chunkSize);\n\n const presentData = BitField.and(requestBitfield, meta.bitfield);\n const chunkIndices = BitField.findIndexes(presentData).sort(() => Math.random() - 0.5);\n\n for (const idx of chunkIndices) {\n const chunkData = await this._params.blobStore.get(header.id, {\n offset: idx * meta.chunkSize,\n length: Math.min(meta.chunkSize, meta.length - idx * meta.chunkSize),\n });\n chunks.push({\n id: header.id,\n totalLength: meta.length,\n chunkSize: meta.chunkSize,\n chunkOffset: idx * meta.chunkSize,\n payload: chunkData,\n });\n\n if (chunks.length >= amount) {\n return chunks;\n }\n }\n }\n\n return chunks;\n }\n}\n\ntype ServiceBundle = {\n BlobSyncService: BlobSyncService;\n};\n", "//\n// Copyright 2023 DXOS.org\n//\n\nimport { trackLeaks, Trigger, Lock } from '@dxos/async';\nimport { cancelWithContext, Context } from '@dxos/context';\nimport { invariant } from '@dxos/invariant';\nimport { PublicKey } from '@dxos/keys';\nimport { log } from '@dxos/log';\nimport { BlobMeta } from '@dxos/protocols/proto/dxos/echo/blob';\nimport { type WantList } from '@dxos/protocols/proto/dxos/mesh/teleport/blobsync';\nimport { BitField, ComplexMap } from '@dxos/util';\n\nimport { type BlobStore } from './blob-store';\nimport { BlobSyncExtension } from './blob-sync-extension';\n\nexport type BlobSyncParams = {\n blobStore: BlobStore;\n};\n\ntype DownloadRequest = {\n trigger: Trigger<void>;\n counter: number;\n want: WantList.Entry;\n};\n\n// TODO(dmaretskyi): Rename to blob-sync.\n@trackLeaks('open', 'close')\nexport class BlobSync {\n private readonly _ctx = new Context();\n private readonly _lock = new Lock();\n\n private readonly _downloadRequests = new ComplexMap<Uint8Array, DownloadRequest>((key) =>\n PublicKey.from(key).toHex(),\n );\n\n private readonly _extensions = new Set<BlobSyncExtension>();\n\n constructor(private readonly _params: BlobSyncParams) {}\n\n async open() {}\n\n async close() {\n await this._ctx.dispose();\n }\n\n /**\n * Resolves when the object with the given id is fully downloaded in the blob store.\n *\n * @param id hex-encoded id of the object to download.\n */\n async download(ctx: Context, id: Uint8Array): Promise<void> {\n log('download', { id });\n const request = await this._lock.executeSynchronized(async () => {\n const existingRequest = this._downloadRequests.get(id);\n\n if (existingRequest) {\n existingRequest.counter++;\n return existingRequest;\n }\n\n const meta = await this._params.blobStore.getMeta(id);\n const request: DownloadRequest = {\n trigger: new Trigger(),\n counter: 1,\n want: {\n id,\n chunkSize: meta?.chunkSize,\n bitfield: meta?.bitfield && Uint8Array.from(BitField.invert(meta.bitfield)),\n },\n };\n\n // Check if the object is already fully downloaded.\n if (meta?.state === BlobMeta.State.FULLY_PRESENT) {\n request.trigger.wake();\n } else {\n this._downloadRequests.set(id, request);\n this._updateExtensionsWantList();\n }\n\n return request;\n });\n\n ctx?.onDispose(() =>\n this._lock.executeSynchronized(async () => {\n // Remove request if context is disposed and nobody else requests it.\n const request = this._downloadRequests.get(id);\n if (!request) {\n return;\n }\n if (--request.counter === 0) {\n this._downloadRequests.delete(id);\n }\n this._updateExtensionsWantList();\n }),\n );\n\n return ctx ? cancelWithContext(ctx, request.trigger.wait()) : request.trigger.wait();\n }\n\n createExtension() {\n const extension = new BlobSyncExtension({\n blobStore: this._params.blobStore,\n onOpen: async () => {\n log('extension opened');\n this._extensions.add(extension);\n extension.updateWantList(this._getWantList());\n },\n onClose: async () => {\n log('extension closed');\n this._extensions.delete(extension);\n },\n onPush: async (blobChunk) => {\n if (!this._downloadRequests.has(blobChunk.id)) {\n return;\n }\n log('received', { blobChunk });\n const meta = await this._params.blobStore.setChunk(blobChunk);\n if (meta.state === BlobMeta.State.FULLY_PRESENT) {\n this._downloadRequests.get(blobChunk.id)?.trigger.wake();\n this._downloadRequests.delete(blobChunk.id);\n } else {\n invariant(meta.bitfield);\n this._downloadRequests.get(blobChunk.id)!.want.bitfield = BitField.invert(meta.bitfield);\n }\n\n this._updateExtensionsWantList();\n this._reconcileUploads();\n },\n });\n return extension;\n }\n\n /**\n * Notify extensions that a blob with the given id was added to the blob store.\n */\n async notifyBlobAdded(_id: Uint8Array) {\n this._reconcileUploads();\n }\n\n private _getWantList(): WantList {\n return {\n blobs: Array.from(this._downloadRequests.values()).map((request) => request.want),\n };\n }\n\n private _reconcileUploads() {\n for (const extension of this._extensions) {\n extension.reconcileUploads();\n }\n }\n\n private _updateExtensionsWantList() {\n for (const extension of this._extensions) {\n extension.updateWantList(this._getWantList());\n }\n }\n}\n", "//\n// Copyright 2023 DXOS.org\n//\n\nimport path from 'node:path';\n\nimport { synchronized } from '@dxos/async';\nimport { subtleCrypto } from '@dxos/crypto';\nimport { invariant } from '@dxos/invariant';\nimport { PublicKey } from '@dxos/keys';\nimport { schema } from '@dxos/protocols';\nimport { BlobMeta } from '@dxos/protocols/proto/dxos/echo/blob';\nimport { type BlobChunk } from '@dxos/protocols/proto/dxos/mesh/teleport/blobsync';\nimport { type Directory } from '@dxos/random-access-storage';\nimport { BitField, arrayToBuffer } from '@dxos/util';\n\nexport type GetOptions = {\n offset?: number;\n length?: number;\n};\n\nexport const DEFAULT_CHUNK_SIZE = 4096;\n\nconst BlobMetaCodec = schema.getCodecForType('dxos.echo.blob.BlobMeta');\n\nexport class BlobStore {\n constructor(private readonly _directory: Directory) {}\n\n @synchronized\n async getMeta(id: Uint8Array): Promise<BlobMeta | undefined> {\n return this._getMeta(id);\n }\n\n /**\n * @throws If range is not available.\n */\n @synchronized\n async get(id: Uint8Array, options: GetOptions = {}): Promise<Uint8Array> {\n const metadata = await this._getMeta(id);\n\n if (!metadata) {\n throw new Error('Blob not available');\n }\n\n const { offset = 0, length = metadata.length } = options;\n\n if (offset + length > metadata.length) {\n throw new Error('Invalid range');\n }\n\n if (metadata.state === BlobMeta.State.FULLY_PRESENT) {\n const file = this._getDataFile(id);\n return file.read(offset, length);\n } else if (options.offset === undefined && options.length === undefined) {\n throw new Error('Blob not available');\n }\n\n const beginChunk = Math.floor(offset / metadata.chunkSize);\n const endChunk = Math.ceil((offset + length) / metadata.chunkSize);\n\n invariant(metadata.bitfield, 'Bitfield not present');\n invariant(metadata.bitfield.length * 8 >= endChunk, 'Invalid bitfield length');\n\n const present = BitField.count(metadata.bitfield, beginChunk, endChunk) === endChunk - beginChunk;\n\n if (!present) {\n throw new Error('Blob not available');\n }\n\n const file = this._getDataFile(id);\n return file.read(offset, length);\n }\n\n @synchronized\n async list(): Promise<BlobMeta[]> {\n /*\n Weird path formatting:\n\n \"e9b9aa7a21c2c55a9eca333cd59975633157562ca0a0f4f243d4778f192c291e_meta\"\n \"e9b9aa7a21c2c55a9eca333cd59975633157562ca0a0f4f243d4778f192c291e_data\"\n \"5001de5a47191357c075aeee6451c4cc323f3a8ada24dd1191e83403608a38d5_meta\n */\n const files = new Set((await this._directory.list()).map((f) => f.split('_')[0]));\n\n const res: BlobMeta[] = [];\n\n for (const file of files) {\n const id = PublicKey.from(file).asUint8Array();\n const meta = await this._getMeta(id);\n if (meta) {\n res.push(meta);\n }\n }\n\n return res;\n }\n\n @synchronized\n async set(data: Uint8Array): Promise<BlobMeta> {\n const id = new Uint8Array(await subtleCrypto.digest('SHA-256', data));\n const bitfield = BitField.ones(data.length / DEFAULT_CHUNK_SIZE);\n\n const meta: BlobMeta = {\n id,\n state: BlobMeta.State.FULLY_PRESENT,\n length: data.length,\n chunkSize: DEFAULT_CHUNK_SIZE,\n bitfield,\n created: new Date(),\n updated: new Date(),\n };\n\n await this._getDataFile(id).write(0, arrayToBuffer(data));\n await this._writeMeta(id, meta);\n return meta;\n }\n\n // TODO(dmaretskyi): Optimize locking.\n @synchronized\n async setChunk(chunk: BlobChunk): Promise<BlobMeta> {\n // Init metadata.\n let meta = await this._getMeta(chunk.id);\n if (!meta) {\n invariant(chunk.totalLength, 'totalLength is not present');\n meta = {\n id: chunk.id,\n state: BlobMeta.State.PARTIALLY_PRESENT,\n length: chunk.totalLength,\n chunkSize: chunk.chunkSize ?? DEFAULT_CHUNK_SIZE,\n created: new Date(),\n };\n meta.bitfield = BitField.zeros(meta.length / meta.chunkSize);\n }\n\n if (chunk.chunkSize && chunk.chunkSize !== meta.chunkSize) {\n throw new Error('Invalid chunk size');\n }\n\n invariant(meta.bitfield, 'Bitfield not present');\n invariant(chunk.chunkOffset !== undefined, 'chunkOffset is not present');\n\n // Write chunk.\n await this._getDataFile(chunk.id).write(chunk.chunkOffset, arrayToBuffer(chunk.payload));\n\n // Update bitfield.\n BitField.set(meta.bitfield, Math.floor(chunk.chunkOffset / meta.chunkSize), true);\n\n // Update metadata.\n if (BitField.count(meta.bitfield, 0, meta.length) * meta.chunkSize >= meta.length) {\n meta.state = BlobMeta.State.FULLY_PRESENT;\n }\n meta.updated = new Date();\n\n await this._writeMeta(chunk.id, meta);\n\n return meta;\n }\n\n private async _writeMeta(id: Uint8Array, meta: BlobMeta): Promise<void> {\n const encoded = arrayToBuffer(BlobMetaCodec.encode(meta));\n const data = Buffer.alloc(encoded.length + 4);\n data.writeUInt32LE(encoded.length, 0);\n encoded.copy(data, 4);\n\n // Write metadata.\n await this._getMetaFile(id).write(0, data);\n }\n\n private async _getMeta(id: Uint8Array): Promise<BlobMeta | undefined> {\n const file = this._getMetaFile(id);\n const size = (await file.stat()).size;\n if (size === 0) {\n return;\n }\n const data = await file.read(0, size);\n const protoSize = data.readUInt32LE(0);\n return BlobMetaCodec.decode(data.subarray(4, protoSize + 4));\n }\n\n private _getMetaFile(id: Uint8Array) {\n return this._directory.getOrCreateFile(path.join(arrayToBuffer(id).toString('hex'), 'meta'));\n }\n\n private _getDataFile(id: Uint8Array) {\n return this._directory.getOrCreateFile(path.join(arrayToBuffer(id).toString('hex'), 'data'));\n }\n}\n"],
5
- "mappings": "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",
6
- "names": ["DeferredTask", "sleep", "synchronized", "Context", "invariant", "log", "RpcClosedError", "schema", "RpcExtension", "BitField", "MIN_WANT_LIST_UPDATE_INTERVAL", "process", "MAX_CONCURRENT_UPLOADS", "BlobSyncExtension", "constructor", "_params", "exposed", "BlobSyncService", "getService", "requested", "timeout", "encodingOptions", "preserveAny", "_ctx", "onError", "err", "catch", "_lastWantListUpdate", "_localWantList", "blobs", "_updateWantList", "Date", "now", "disposed", "list", "rpc", "want", "_currentUploads", "_upload", "blobChunks", "_pickBlobChunks", "blobChunk", "push", "warn", "finally", "reconcileUploads", "remoteWantList", "onOpen", "context", "onClose", "dispose", "getHandlers", "wantList", "data", "onPush", "updateWantList", "schedule", "amount", "length", "shuffled", "sort", "Math", "random", "chunks", "header", "meta", "blobStore", "getMeta", "id", "bitfield", "chunkSize", "requestBitfield", "ones", "presentData", "and", "chunkIndices", "findIndexes", "idx", "chunkData", "get", "offset", "min", "totalLength", "chunkOffset", "payload", "trackLeaks", "Trigger", "Lock", "cancelWithContext", "Context", "invariant", "PublicKey", "log", "BlobMeta", "BitField", "ComplexMap", "BlobSync", "constructor", "_params", "_ctx", "Context", "_lock", "Lock", "_downloadRequests", "ComplexMap", "key", "PublicKey", "from", "toHex", "_extensions", "Set", "open", "close", "dispose", "download", "ctx", "id", "log", "request", "executeSynchronized", "existingRequest", "get", "counter", "meta", "blobStore", "getMeta", "trigger", "Trigger", "want", "chunkSize", "bitfield", "Uint8Array", "BitField", "invert", "state", "BlobMeta", "State", "FULLY_PRESENT", "wake", "set", "_updateExtensionsWantList", "onDispose", "delete", "cancelWithContext", "wait", "createExtension", "extension", "BlobSyncExtension", "onOpen", "add", "updateWantList", "_getWantList", "onClose", "onPush", "blobChunk", "has", "setChunk", "invariant", "_reconcileUploads", "notifyBlobAdded", "_id", "blobs", "Array", "values", "map", "reconcileUploads", "trackLeaks", "path", "synchronized", "subtleCrypto", "invariant", "PublicKey", "schema", "BlobMeta", "BitField", "arrayToBuffer", "DEFAULT_CHUNK_SIZE", "BlobMetaCodec", "getCodecForType", "BlobStore", "constructor", "_directory", "getMeta", "id", "_getMeta", "get", "options", "metadata", "Error", "offset", "length", "state", "State", "FULLY_PRESENT", "file", "_getDataFile", "read", "undefined", "beginChunk", "Math", "floor", "chunkSize", "endChunk", "ceil", "bitfield", "present", "count", "list", "files", "Set", "map", "f", "split", "res", "from", "asUint8Array", "meta", "push", "set", "data", "Uint8Array", "digest", "ones", "created", "Date", "updated", "write", "_writeMeta", "setChunk", "chunk", "totalLength", "PARTIALLY_PRESENT", "zeros", "chunkOffset", "payload", "encoded", "encode", "Buffer", "alloc", "writeUInt32LE", "copy", "_getMetaFile", "size", "stat", "protoSize", "readUInt32LE", "decode", "subarray", "getOrCreateFile", "join", "toString"]
4
+ "sourcesContent": ["//\n\n//\n// Copyright 2023 DXOS.org\n//\n\nimport { DeferredTask, sleep, synchronized } from '@dxos/async';\nimport { Context } from '@dxos/context';\nimport { invariant } from '@dxos/invariant';\nimport { log } from '@dxos/log';\nimport { RpcClosedError, schema } from '@dxos/protocols';\nimport { type BlobChunk, type BlobSyncService, type WantList } from '@dxos/protocols/proto/dxos/mesh/teleport/blobsync';\nimport { type ExtensionContext, RpcExtension } from '@dxos/teleport';\nimport { BitField } from '@dxos/util';\n\nimport { type BlobStore } from './blob-store';\n\nexport type BlobSyncExtensionParams = {\n blobStore: BlobStore;\n onOpen: () => Promise<void>;\n onClose: () => Promise<void>;\n onAbort: () => Promise<void>;\n onPush: (data: BlobChunk) => Promise<void>;\n};\n\nconst MIN_WANT_LIST_UPDATE_INTERVAL = process.env.NODE_ENV === 'test' ? 5 : 500;\n\nconst MAX_CONCURRENT_UPLOADS = 20;\n\n/**\n * Manages replication between a set of feeds for a single teleport session.\n */\nexport class BlobSyncExtension extends RpcExtension<ServiceBundle, ServiceBundle> {\n private readonly _ctx = new Context({ onError: (err) => log.catch(err) });\n\n private _lastWantListUpdate = 0;\n private _localWantList: WantList = { blobs: [] };\n\n private readonly _updateWantList = new DeferredTask(this._ctx, async () => {\n // Throttle want list updates.\n if (this._lastWantListUpdate + MIN_WANT_LIST_UPDATE_INTERVAL > Date.now()) {\n await sleep(this._lastWantListUpdate + MIN_WANT_LIST_UPDATE_INTERVAL - Date.now());\n if (this._ctx.disposed) {\n return;\n }\n }\n\n log('want', { list: this._localWantList });\n await this.rpc.BlobSyncService.want(this._localWantList);\n this._lastWantListUpdate = Date.now();\n });\n\n private _currentUploads = 0;\n\n private readonly _upload = new DeferredTask(this._ctx, async () => {\n if (this._currentUploads >= MAX_CONCURRENT_UPLOADS) {\n return;\n }\n const blobChunks = await this._pickBlobChunks(MAX_CONCURRENT_UPLOADS - this._currentUploads);\n if (!blobChunks) {\n return;\n }\n for (const blobChunk of blobChunks) {\n if (this._ctx.disposed) {\n break;\n }\n\n this._currentUploads++;\n\n this.push(blobChunk)\n .catch((err) => {\n if (err instanceof RpcClosedError) {\n return;\n }\n log.warn('push failed', { err });\n })\n .finally(() => {\n this._currentUploads--;\n this.reconcileUploads();\n });\n }\n });\n\n /**\n * Set of id's remote peer wants.\n */\n public remoteWantList: WantList = { blobs: [] };\n\n constructor(\n private readonly _params: BlobSyncExtensionParams, // to not conflict with the base class\n ) {\n super({\n exposed: {\n BlobSyncService: schema.getService('dxos.mesh.teleport.blobsync.BlobSyncService'),\n },\n requested: {\n BlobSyncService: schema.getService('dxos.mesh.teleport.blobsync.BlobSyncService'),\n },\n timeout: 20_000,\n encodingOptions: {\n preserveAny: true,\n },\n });\n }\n\n override async onOpen(context: ExtensionContext): Promise<void> {\n log('open');\n await super.onOpen(context);\n await this._params.onOpen();\n }\n\n override async onClose(err?: Error | undefined): Promise<void> {\n log('close');\n await this._ctx.dispose();\n await this._params.onClose();\n await super.onClose(err);\n }\n\n override async onAbort(err?: Error | undefined): Promise<void> {\n log('abort');\n await this._ctx.dispose();\n await this._params.onAbort();\n await super.onAbort(err);\n }\n\n protected async getHandlers(): Promise<ServiceBundle> {\n return {\n BlobSyncService: {\n want: async (wantList) => {\n log('remote want', { remoteWantList: wantList });\n this.remoteWantList = wantList;\n this.reconcileUploads();\n },\n push: async (data) => {\n log('received', { data });\n await this._params.onPush(data);\n },\n },\n };\n }\n\n @synchronized\n async push(data: BlobChunk) {\n if (this._ctx.disposed) {\n return;\n }\n log('push', { data });\n await this.rpc.BlobSyncService.push(data);\n }\n\n updateWantList(wantList: WantList) {\n if (this._ctx.disposed) {\n return;\n }\n this._localWantList = wantList;\n this._updateWantList.schedule();\n }\n\n reconcileUploads() {\n if (this._ctx.disposed) {\n return;\n }\n this._upload.schedule();\n }\n\n private async _pickBlobChunks(amount = 1): Promise<BlobChunk[] | void> {\n if (this._ctx.disposed) {\n return;\n }\n\n if (!this.remoteWantList.blobs || this.remoteWantList.blobs?.length === 0) {\n return;\n }\n\n const shuffled = [...this.remoteWantList.blobs].sort(() => Math.random() - 0.5);\n\n const chunks: BlobChunk[] = [];\n\n for (const header of shuffled) {\n const meta = await this._params.blobStore.getMeta(header.id);\n\n if (!meta) {\n // Skip this header\n continue;\n }\n invariant(meta.bitfield);\n invariant(meta.chunkSize);\n invariant(meta.length);\n\n if (header.chunkSize && header.chunkSize !== meta.chunkSize) {\n log.warn('Invalid chunk size', { header, meta });\n continue;\n }\n\n const requestBitfield = header.bitfield ?? BitField.ones(meta.length / meta.chunkSize);\n\n const presentData = BitField.and(requestBitfield, meta.bitfield);\n const chunkIndices = BitField.findIndexes(presentData).sort(() => Math.random() - 0.5);\n\n for (const idx of chunkIndices) {\n const chunkData = await this._params.blobStore.get(header.id, {\n offset: idx * meta.chunkSize,\n length: Math.min(meta.chunkSize, meta.length - idx * meta.chunkSize),\n });\n chunks.push({\n id: header.id,\n totalLength: meta.length,\n chunkSize: meta.chunkSize,\n chunkOffset: idx * meta.chunkSize,\n payload: chunkData,\n });\n\n if (chunks.length >= amount) {\n return chunks;\n }\n }\n }\n\n return chunks;\n }\n}\n\ntype ServiceBundle = {\n BlobSyncService: BlobSyncService;\n};\n", "//\n// Copyright 2023 DXOS.org\n//\n\nimport { trackLeaks, Trigger, Lock } from '@dxos/async';\nimport { cancelWithContext, Context } from '@dxos/context';\nimport { invariant } from '@dxos/invariant';\nimport { PublicKey } from '@dxos/keys';\nimport { log } from '@dxos/log';\nimport { BlobMeta } from '@dxos/protocols/proto/dxos/echo/blob';\nimport { type WantList } from '@dxos/protocols/proto/dxos/mesh/teleport/blobsync';\nimport { BitField, ComplexMap } from '@dxos/util';\n\nimport { type BlobStore } from './blob-store';\nimport { BlobSyncExtension } from './blob-sync-extension';\n\nexport type BlobSyncParams = {\n blobStore: BlobStore;\n};\n\ntype DownloadRequest = {\n trigger: Trigger<void>;\n counter: number;\n want: WantList.Entry;\n};\n\n// TODO(dmaretskyi): Rename to blob-sync.\n@trackLeaks('open', 'close')\nexport class BlobSync {\n private readonly _ctx = new Context();\n private readonly _lock = new Lock();\n\n private readonly _downloadRequests = new ComplexMap<Uint8Array, DownloadRequest>((key) =>\n PublicKey.from(key).toHex(),\n );\n\n private readonly _extensions = new Set<BlobSyncExtension>();\n\n constructor(private readonly _params: BlobSyncParams) {}\n\n async open() {}\n\n async close() {\n await this._ctx.dispose();\n }\n\n /**\n * Resolves when the object with the given id is fully downloaded in the blob store.\n *\n * @param id hex-encoded id of the object to download.\n */\n async download(ctx: Context, id: Uint8Array): Promise<void> {\n log('download', { id });\n const request = await this._lock.executeSynchronized(async () => {\n const existingRequest = this._downloadRequests.get(id);\n\n if (existingRequest) {\n existingRequest.counter++;\n return existingRequest;\n }\n\n const meta = await this._params.blobStore.getMeta(id);\n const request: DownloadRequest = {\n trigger: new Trigger(),\n counter: 1,\n want: {\n id,\n chunkSize: meta?.chunkSize,\n bitfield: meta?.bitfield && Uint8Array.from(BitField.invert(meta.bitfield)),\n },\n };\n\n // Check if the object is already fully downloaded.\n if (meta?.state === BlobMeta.State.FULLY_PRESENT) {\n request.trigger.wake();\n } else {\n this._downloadRequests.set(id, request);\n this._updateExtensionsWantList();\n }\n\n return request;\n });\n\n ctx?.onDispose(() =>\n this._lock.executeSynchronized(async () => {\n // Remove request if context is disposed and nobody else requests it.\n const request = this._downloadRequests.get(id);\n if (!request) {\n return;\n }\n if (--request.counter === 0) {\n this._downloadRequests.delete(id);\n }\n this._updateExtensionsWantList();\n }),\n );\n\n return ctx ? cancelWithContext(ctx, request.trigger.wait()) : request.trigger.wait();\n }\n\n createExtension() {\n const extension = new BlobSyncExtension({\n blobStore: this._params.blobStore,\n onOpen: async () => {\n log('extension opened');\n this._extensions.add(extension);\n extension.updateWantList(this._getWantList());\n },\n onClose: async () => {\n log('extension closed');\n this._extensions.delete(extension);\n },\n onAbort: async () => {\n log('extension aborted');\n this._extensions.delete(extension);\n },\n onPush: async (blobChunk) => {\n if (!this._downloadRequests.has(blobChunk.id)) {\n return;\n }\n log('received', { blobChunk });\n const meta = await this._params.blobStore.setChunk(blobChunk);\n if (meta.state === BlobMeta.State.FULLY_PRESENT) {\n this._downloadRequests.get(blobChunk.id)?.trigger.wake();\n this._downloadRequests.delete(blobChunk.id);\n } else {\n invariant(meta.bitfield);\n this._downloadRequests.get(blobChunk.id)!.want.bitfield = BitField.invert(meta.bitfield);\n }\n\n this._updateExtensionsWantList();\n this._reconcileUploads();\n },\n });\n return extension;\n }\n\n /**\n * Notify extensions that a blob with the given id was added to the blob store.\n */\n async notifyBlobAdded(_id: Uint8Array) {\n this._reconcileUploads();\n }\n\n private _getWantList(): WantList {\n return {\n blobs: Array.from(this._downloadRequests.values()).map((request) => request.want),\n };\n }\n\n private _reconcileUploads() {\n for (const extension of this._extensions) {\n extension.reconcileUploads();\n }\n }\n\n private _updateExtensionsWantList() {\n for (const extension of this._extensions) {\n extension.updateWantList(this._getWantList());\n }\n }\n}\n", "//\n// Copyright 2023 DXOS.org\n//\n\nimport path from 'node:path';\n\nimport { synchronized } from '@dxos/async';\nimport { subtleCrypto } from '@dxos/crypto';\nimport { invariant } from '@dxos/invariant';\nimport { PublicKey } from '@dxos/keys';\nimport { schema } from '@dxos/protocols';\nimport { BlobMeta } from '@dxos/protocols/proto/dxos/echo/blob';\nimport { type BlobChunk } from '@dxos/protocols/proto/dxos/mesh/teleport/blobsync';\nimport { type Directory } from '@dxos/random-access-storage';\nimport { BitField, arrayToBuffer } from '@dxos/util';\n\nexport type GetOptions = {\n offset?: number;\n length?: number;\n};\n\nexport const DEFAULT_CHUNK_SIZE = 4096;\n\nconst BlobMetaCodec = schema.getCodecForType('dxos.echo.blob.BlobMeta');\n\nexport class BlobStore {\n constructor(private readonly _directory: Directory) {}\n\n @synchronized\n async getMeta(id: Uint8Array): Promise<BlobMeta | undefined> {\n return this._getMeta(id);\n }\n\n /**\n * @throws If range is not available.\n */\n @synchronized\n async get(id: Uint8Array, options: GetOptions = {}): Promise<Uint8Array> {\n const metadata = await this._getMeta(id);\n\n if (!metadata) {\n throw new Error('Blob not available');\n }\n\n const { offset = 0, length = metadata.length } = options;\n\n if (offset + length > metadata.length) {\n throw new Error('Invalid range');\n }\n\n if (metadata.state === BlobMeta.State.FULLY_PRESENT) {\n const file = this._getDataFile(id);\n return file.read(offset, length);\n } else if (options.offset === undefined && options.length === undefined) {\n throw new Error('Blob not available');\n }\n\n const beginChunk = Math.floor(offset / metadata.chunkSize);\n const endChunk = Math.ceil((offset + length) / metadata.chunkSize);\n\n invariant(metadata.bitfield, 'Bitfield not present');\n invariant(metadata.bitfield.length * 8 >= endChunk, 'Invalid bitfield length');\n\n const present = BitField.count(metadata.bitfield, beginChunk, endChunk) === endChunk - beginChunk;\n\n if (!present) {\n throw new Error('Blob not available');\n }\n\n const file = this._getDataFile(id);\n return file.read(offset, length);\n }\n\n @synchronized\n async list(): Promise<BlobMeta[]> {\n /*\n Weird path formatting:\n\n \"e9b9aa7a21c2c55a9eca333cd59975633157562ca0a0f4f243d4778f192c291e_meta\"\n \"e9b9aa7a21c2c55a9eca333cd59975633157562ca0a0f4f243d4778f192c291e_data\"\n \"5001de5a47191357c075aeee6451c4cc323f3a8ada24dd1191e83403608a38d5_meta\n */\n const files = new Set((await this._directory.list()).map((f) => f.split('_')[0]));\n\n const res: BlobMeta[] = [];\n\n for (const file of files) {\n const id = PublicKey.from(file).asUint8Array();\n const meta = await this._getMeta(id);\n if (meta) {\n res.push(meta);\n }\n }\n\n return res;\n }\n\n @synchronized\n async set(data: Uint8Array): Promise<BlobMeta> {\n const id = new Uint8Array(await subtleCrypto.digest('SHA-256', data));\n const bitfield = BitField.ones(data.length / DEFAULT_CHUNK_SIZE);\n\n const meta: BlobMeta = {\n id,\n state: BlobMeta.State.FULLY_PRESENT,\n length: data.length,\n chunkSize: DEFAULT_CHUNK_SIZE,\n bitfield,\n created: new Date(),\n updated: new Date(),\n };\n\n await this._getDataFile(id).write(0, arrayToBuffer(data));\n await this._writeMeta(id, meta);\n return meta;\n }\n\n // TODO(dmaretskyi): Optimize locking.\n @synchronized\n async setChunk(chunk: BlobChunk): Promise<BlobMeta> {\n // Init metadata.\n let meta = await this._getMeta(chunk.id);\n if (!meta) {\n invariant(chunk.totalLength, 'totalLength is not present');\n meta = {\n id: chunk.id,\n state: BlobMeta.State.PARTIALLY_PRESENT,\n length: chunk.totalLength,\n chunkSize: chunk.chunkSize ?? DEFAULT_CHUNK_SIZE,\n created: new Date(),\n };\n meta.bitfield = BitField.zeros(meta.length / meta.chunkSize);\n }\n\n if (chunk.chunkSize && chunk.chunkSize !== meta.chunkSize) {\n throw new Error('Invalid chunk size');\n }\n\n invariant(meta.bitfield, 'Bitfield not present');\n invariant(chunk.chunkOffset !== undefined, 'chunkOffset is not present');\n\n // Write chunk.\n await this._getDataFile(chunk.id).write(chunk.chunkOffset, arrayToBuffer(chunk.payload));\n\n // Update bitfield.\n BitField.set(meta.bitfield, Math.floor(chunk.chunkOffset / meta.chunkSize), true);\n\n // Update metadata.\n if (BitField.count(meta.bitfield, 0, meta.length) * meta.chunkSize >= meta.length) {\n meta.state = BlobMeta.State.FULLY_PRESENT;\n }\n meta.updated = new Date();\n\n await this._writeMeta(chunk.id, meta);\n\n return meta;\n }\n\n private async _writeMeta(id: Uint8Array, meta: BlobMeta): Promise<void> {\n const encoded = arrayToBuffer(BlobMetaCodec.encode(meta));\n const data = Buffer.alloc(encoded.length + 4);\n data.writeUInt32LE(encoded.length, 0);\n encoded.copy(data, 4);\n\n // Write metadata.\n await this._getMetaFile(id).write(0, data);\n }\n\n private async _getMeta(id: Uint8Array): Promise<BlobMeta | undefined> {\n const file = this._getMetaFile(id);\n const size = (await file.stat()).size;\n if (size === 0) {\n return;\n }\n const data = await file.read(0, size);\n const protoSize = data.readUInt32LE(0);\n return BlobMetaCodec.decode(data.subarray(4, protoSize + 4));\n }\n\n private _getMetaFile(id: Uint8Array) {\n return this._directory.getOrCreateFile(path.join(arrayToBuffer(id).toString('hex'), 'meta'));\n }\n\n private _getDataFile(id: Uint8Array) {\n return this._directory.getOrCreateFile(path.join(arrayToBuffer(id).toString('hex'), 'data'));\n }\n}\n"],
5
+ "mappings": "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",
6
+ "names": ["DeferredTask", "sleep", "synchronized", "Context", "invariant", "log", "RpcClosedError", "schema", "RpcExtension", "BitField", "MIN_WANT_LIST_UPDATE_INTERVAL", "process", "MAX_CONCURRENT_UPLOADS", "BlobSyncExtension", "constructor", "_params", "exposed", "BlobSyncService", "getService", "requested", "timeout", "encodingOptions", "preserveAny", "_ctx", "onError", "err", "catch", "_lastWantListUpdate", "_localWantList", "blobs", "_updateWantList", "Date", "now", "disposed", "list", "rpc", "want", "_currentUploads", "_upload", "blobChunks", "_pickBlobChunks", "blobChunk", "push", "warn", "finally", "reconcileUploads", "remoteWantList", "onOpen", "context", "onClose", "dispose", "onAbort", "getHandlers", "wantList", "data", "onPush", "updateWantList", "schedule", "amount", "length", "shuffled", "sort", "Math", "random", "chunks", "header", "meta", "blobStore", "getMeta", "id", "bitfield", "chunkSize", "requestBitfield", "ones", "presentData", "and", "chunkIndices", "findIndexes", "idx", "chunkData", "get", "offset", "min", "totalLength", "chunkOffset", "payload", "trackLeaks", "Trigger", "Lock", "cancelWithContext", "Context", "invariant", "PublicKey", "log", "BlobMeta", "BitField", "ComplexMap", "BlobSync", "constructor", "_params", "_ctx", "Context", "_lock", "Lock", "_downloadRequests", "ComplexMap", "key", "PublicKey", "from", "toHex", "_extensions", "Set", "open", "close", "dispose", "download", "ctx", "id", "log", "request", "executeSynchronized", "existingRequest", "get", "counter", "meta", "blobStore", "getMeta", "trigger", "Trigger", "want", "chunkSize", "bitfield", "Uint8Array", "BitField", "invert", "state", "BlobMeta", "State", "FULLY_PRESENT", "wake", "set", "_updateExtensionsWantList", "onDispose", "delete", "cancelWithContext", "wait", "createExtension", "extension", "BlobSyncExtension", "onOpen", "add", "updateWantList", "_getWantList", "onClose", "onAbort", "onPush", "blobChunk", "has", "setChunk", "invariant", "_reconcileUploads", "notifyBlobAdded", "_id", "blobs", "Array", "values", "map", "reconcileUploads", "trackLeaks", "path", "synchronized", "subtleCrypto", "invariant", "PublicKey", "schema", "BlobMeta", "BitField", "arrayToBuffer", "DEFAULT_CHUNK_SIZE", "BlobMetaCodec", "getCodecForType", "BlobStore", "constructor", "_directory", "getMeta", "id", "_getMeta", "get", "options", "metadata", "Error", "offset", "length", "state", "State", "FULLY_PRESENT", "file", "_getDataFile", "read", "undefined", "beginChunk", "Math", "floor", "chunkSize", "endChunk", "ceil", "bitfield", "present", "count", "list", "files", "Set", "map", "f", "split", "res", "from", "asUint8Array", "meta", "push", "set", "data", "Uint8Array", "digest", "ones", "created", "Date", "updated", "write", "_writeMeta", "setChunk", "chunk", "totalLength", "PARTIALLY_PRESENT", "zeros", "chunkOffset", "payload", "encoded", "encode", "Buffer", "alloc", "writeUInt32LE", "copy", "_getMetaFile", "size", "stat", "protoSize", "readUInt32LE", "decode", "subarray", "getOrCreateFile", "join", "toString"]
7
7
  }
@@ -1 +1 @@
1
- {"inputs":{"packages/core/mesh/teleport-extension-object-sync/src/blob-sync-extension.ts":{"bytes":24384,"imports":[{"path":"@dxos/async","kind":"import-statement","external":true},{"path":"@dxos/context","kind":"import-statement","external":true},{"path":"@dxos/invariant","kind":"import-statement","external":true},{"path":"@dxos/log","kind":"import-statement","external":true},{"path":"@dxos/protocols","kind":"import-statement","external":true},{"path":"@dxos/teleport","kind":"import-statement","external":true},{"path":"@dxos/util","kind":"import-statement","external":true}],"format":"esm"},"packages/core/mesh/teleport-extension-object-sync/src/blob-sync.ts":{"bytes":17817,"imports":[{"path":"@dxos/async","kind":"import-statement","external":true},{"path":"@dxos/context","kind":"import-statement","external":true},{"path":"@dxos/invariant","kind":"import-statement","external":true},{"path":"@dxos/keys","kind":"import-statement","external":true},{"path":"@dxos/log","kind":"import-statement","external":true},{"path":"@dxos/protocols/proto/dxos/echo/blob","kind":"import-statement","external":true},{"path":"@dxos/util","kind":"import-statement","external":true},{"path":"packages/core/mesh/teleport-extension-object-sync/src/blob-sync-extension.ts","kind":"import-statement","original":"./blob-sync-extension"}],"format":"esm"},"packages/core/mesh/teleport-extension-object-sync/src/blob-store.ts":{"bytes":22281,"imports":[{"path":"@dxos/node-std/path","kind":"import-statement","external":true},{"path":"@dxos/async","kind":"import-statement","external":true},{"path":"@dxos/crypto","kind":"import-statement","external":true},{"path":"@dxos/invariant","kind":"import-statement","external":true},{"path":"@dxos/keys","kind":"import-statement","external":true},{"path":"@dxos/protocols","kind":"import-statement","external":true},{"path":"@dxos/protocols/proto/dxos/echo/blob","kind":"import-statement","external":true},{"path":"@dxos/util","kind":"import-statement","external":true}],"format":"esm"},"packages/core/mesh/teleport-extension-object-sync/src/index.ts":{"bytes":703,"imports":[{"path":"packages/core/mesh/teleport-extension-object-sync/src/blob-sync-extension.ts","kind":"import-statement","original":"./blob-sync-extension"},{"path":"packages/core/mesh/teleport-extension-object-sync/src/blob-sync.ts","kind":"import-statement","original":"./blob-sync"},{"path":"packages/core/mesh/teleport-extension-object-sync/src/blob-store.ts","kind":"import-statement","original":"./blob-store"}],"format":"esm"}},"outputs":{"packages/core/mesh/teleport-extension-object-sync/dist/lib/browser/index.mjs.map":{"imports":[],"exports":[],"inputs":{},"bytes":29905},"packages/core/mesh/teleport-extension-object-sync/dist/lib/browser/index.mjs":{"imports":[{"path":"@dxos/async","kind":"import-statement","external":true},{"path":"@dxos/context","kind":"import-statement","external":true},{"path":"@dxos/invariant","kind":"import-statement","external":true},{"path":"@dxos/log","kind":"import-statement","external":true},{"path":"@dxos/protocols","kind":"import-statement","external":true},{"path":"@dxos/teleport","kind":"import-statement","external":true},{"path":"@dxos/util","kind":"import-statement","external":true},{"path":"@dxos/async","kind":"import-statement","external":true},{"path":"@dxos/context","kind":"import-statement","external":true},{"path":"@dxos/invariant","kind":"import-statement","external":true},{"path":"@dxos/keys","kind":"import-statement","external":true},{"path":"@dxos/log","kind":"import-statement","external":true},{"path":"@dxos/protocols/proto/dxos/echo/blob","kind":"import-statement","external":true},{"path":"@dxos/util","kind":"import-statement","external":true},{"path":"@dxos/node-std/path","kind":"import-statement","external":true},{"path":"@dxos/async","kind":"import-statement","external":true},{"path":"@dxos/crypto","kind":"import-statement","external":true},{"path":"@dxos/invariant","kind":"import-statement","external":true},{"path":"@dxos/keys","kind":"import-statement","external":true},{"path":"@dxos/protocols","kind":"import-statement","external":true},{"path":"@dxos/protocols/proto/dxos/echo/blob","kind":"import-statement","external":true},{"path":"@dxos/util","kind":"import-statement","external":true}],"exports":["BlobStore","BlobSync","BlobSyncExtension","DEFAULT_CHUNK_SIZE"],"entryPoint":"packages/core/mesh/teleport-extension-object-sync/src/index.ts","inputs":{"packages/core/mesh/teleport-extension-object-sync/src/blob-sync-extension.ts":{"bytesInOutput":7121},"packages/core/mesh/teleport-extension-object-sync/src/index.ts":{"bytesInOutput":0},"packages/core/mesh/teleport-extension-object-sync/src/blob-sync.ts":{"bytesInOutput":5176},"packages/core/mesh/teleport-extension-object-sync/src/blob-store.ts":{"bytesInOutput":6547}},"bytes":19215}}}
1
+ {"inputs":{"packages/core/mesh/teleport-extension-object-sync/src/blob-sync-extension.ts":{"bytes":25193,"imports":[{"path":"@dxos/async","kind":"import-statement","external":true},{"path":"@dxos/context","kind":"import-statement","external":true},{"path":"@dxos/invariant","kind":"import-statement","external":true},{"path":"@dxos/log","kind":"import-statement","external":true},{"path":"@dxos/protocols","kind":"import-statement","external":true},{"path":"@dxos/teleport","kind":"import-statement","external":true},{"path":"@dxos/util","kind":"import-statement","external":true}],"format":"esm"},"packages/core/mesh/teleport-extension-object-sync/src/blob-sync.ts":{"bytes":18388,"imports":[{"path":"@dxos/async","kind":"import-statement","external":true},{"path":"@dxos/context","kind":"import-statement","external":true},{"path":"@dxos/invariant","kind":"import-statement","external":true},{"path":"@dxos/keys","kind":"import-statement","external":true},{"path":"@dxos/log","kind":"import-statement","external":true},{"path":"@dxos/protocols/proto/dxos/echo/blob","kind":"import-statement","external":true},{"path":"@dxos/util","kind":"import-statement","external":true},{"path":"packages/core/mesh/teleport-extension-object-sync/src/blob-sync-extension.ts","kind":"import-statement","original":"./blob-sync-extension"}],"format":"esm"},"packages/core/mesh/teleport-extension-object-sync/src/blob-store.ts":{"bytes":22276,"imports":[{"path":"@dxos/node-std/path","kind":"import-statement","external":true},{"path":"@dxos/async","kind":"import-statement","external":true},{"path":"@dxos/crypto","kind":"import-statement","external":true},{"path":"@dxos/invariant","kind":"import-statement","external":true},{"path":"@dxos/keys","kind":"import-statement","external":true},{"path":"@dxos/protocols","kind":"import-statement","external":true},{"path":"@dxos/protocols/proto/dxos/echo/blob","kind":"import-statement","external":true},{"path":"@dxos/util","kind":"import-statement","external":true}],"format":"esm"},"packages/core/mesh/teleport-extension-object-sync/src/index.ts":{"bytes":698,"imports":[{"path":"packages/core/mesh/teleport-extension-object-sync/src/blob-sync-extension.ts","kind":"import-statement","original":"./blob-sync-extension"},{"path":"packages/core/mesh/teleport-extension-object-sync/src/blob-sync.ts","kind":"import-statement","original":"./blob-sync"},{"path":"packages/core/mesh/teleport-extension-object-sync/src/blob-store.ts","kind":"import-statement","original":"./blob-store"}],"format":"esm"}},"outputs":{"packages/core/mesh/teleport-extension-object-sync/dist/lib/browser/index.mjs.map":{"imports":[],"exports":[],"inputs":{},"bytes":30506},"packages/core/mesh/teleport-extension-object-sync/dist/lib/browser/index.mjs":{"imports":[{"path":"@dxos/async","kind":"import-statement","external":true},{"path":"@dxos/context","kind":"import-statement","external":true},{"path":"@dxos/invariant","kind":"import-statement","external":true},{"path":"@dxos/log","kind":"import-statement","external":true},{"path":"@dxos/protocols","kind":"import-statement","external":true},{"path":"@dxos/teleport","kind":"import-statement","external":true},{"path":"@dxos/util","kind":"import-statement","external":true},{"path":"@dxos/async","kind":"import-statement","external":true},{"path":"@dxos/context","kind":"import-statement","external":true},{"path":"@dxos/invariant","kind":"import-statement","external":true},{"path":"@dxos/keys","kind":"import-statement","external":true},{"path":"@dxos/log","kind":"import-statement","external":true},{"path":"@dxos/protocols/proto/dxos/echo/blob","kind":"import-statement","external":true},{"path":"@dxos/util","kind":"import-statement","external":true},{"path":"@dxos/node-std/path","kind":"import-statement","external":true},{"path":"@dxos/async","kind":"import-statement","external":true},{"path":"@dxos/crypto","kind":"import-statement","external":true},{"path":"@dxos/invariant","kind":"import-statement","external":true},{"path":"@dxos/keys","kind":"import-statement","external":true},{"path":"@dxos/protocols","kind":"import-statement","external":true},{"path":"@dxos/protocols/proto/dxos/echo/blob","kind":"import-statement","external":true},{"path":"@dxos/util","kind":"import-statement","external":true}],"exports":["BlobStore","BlobSync","BlobSyncExtension","DEFAULT_CHUNK_SIZE"],"entryPoint":"packages/core/mesh/teleport-extension-object-sync/src/index.ts","inputs":{"packages/core/mesh/teleport-extension-object-sync/src/blob-sync-extension.ts":{"bytesInOutput":7352},"packages/core/mesh/teleport-extension-object-sync/src/index.ts":{"bytesInOutput":0},"packages/core/mesh/teleport-extension-object-sync/src/blob-sync.ts":{"bytesInOutput":5405},"packages/core/mesh/teleport-extension-object-sync/src/blob-store.ts":{"bytesInOutput":6542}},"bytes":19670}}}
@@ -26,18 +26,14 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
26
26
  mod
27
27
  ));
28
28
  var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
29
-
30
- // packages/core/mesh/teleport-extension-object-sync/src/index.ts
31
- var src_exports = {};
32
- __export(src_exports, {
29
+ var node_exports = {};
30
+ __export(node_exports, {
33
31
  BlobStore: () => BlobStore,
34
32
  BlobSync: () => BlobSync,
35
33
  BlobSyncExtension: () => BlobSyncExtension,
36
34
  DEFAULT_CHUNK_SIZE: () => DEFAULT_CHUNK_SIZE
37
35
  });
38
- module.exports = __toCommonJS(src_exports);
39
-
40
- // packages/core/mesh/teleport-extension-object-sync/src/blob-sync-extension.ts
36
+ module.exports = __toCommonJS(node_exports);
41
37
  var import_async = require("@dxos/async");
42
38
  var import_context = require("@dxos/context");
43
39
  var import_invariant = require("@dxos/invariant");
@@ -45,6 +41,21 @@ var import_log = require("@dxos/log");
45
41
  var import_protocols = require("@dxos/protocols");
46
42
  var import_teleport = require("@dxos/teleport");
47
43
  var import_util = require("@dxos/util");
44
+ var import_async2 = require("@dxos/async");
45
+ var import_context2 = require("@dxos/context");
46
+ var import_invariant2 = require("@dxos/invariant");
47
+ var import_keys = require("@dxos/keys");
48
+ var import_log2 = require("@dxos/log");
49
+ var import_blob = require("@dxos/protocols/proto/dxos/echo/blob");
50
+ var import_util2 = require("@dxos/util");
51
+ var import_node_path = __toESM(require("node:path"));
52
+ var import_async3 = require("@dxos/async");
53
+ var import_crypto = require("@dxos/crypto");
54
+ var import_invariant3 = require("@dxos/invariant");
55
+ var import_keys2 = require("@dxos/keys");
56
+ var import_protocols2 = require("@dxos/protocols");
57
+ var import_blob2 = require("@dxos/protocols/proto/dxos/echo/blob");
58
+ var import_util3 = require("@dxos/util");
48
59
  function _ts_decorate(decorators, target, key, desc) {
49
60
  var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
50
61
  if (typeof Reflect === "object" && typeof Reflect.decorate === "function")
@@ -55,7 +66,7 @@ function _ts_decorate(decorators, target, key, desc) {
55
66
  r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
56
67
  return c > 3 && r && Object.defineProperty(target, key, r), r;
57
68
  }
58
- var __dxlog_file = "/home/runner/work/dxos/dxos/packages/core/mesh/teleport-extension-object-sync/src/blob-sync-extension.ts";
69
+ var __dxlog_file = "/home/circleci/project/packages/core/mesh/teleport-extension-object-sync/src/blob-sync-extension.ts";
59
70
  var MIN_WANT_LIST_UPDATE_INTERVAL = process.env.NODE_ENV === "test" ? 5 : 500;
60
71
  var MAX_CONCURRENT_UPLOADS = 20;
61
72
  var BlobSyncExtension = class extends import_teleport.RpcExtension {
@@ -76,7 +87,7 @@ var BlobSyncExtension = class extends import_teleport.RpcExtension {
76
87
  this._ctx = new import_context.Context({
77
88
  onError: (err) => import_log.log.catch(err, void 0, {
78
89
  F: __dxlog_file,
79
- L: 33,
90
+ L: 34,
80
91
  S: this,
81
92
  C: (f, a) => f(...a)
82
93
  })
@@ -96,7 +107,7 @@ var BlobSyncExtension = class extends import_teleport.RpcExtension {
96
107
  list: this._localWantList
97
108
  }, {
98
109
  F: __dxlog_file,
99
- L: 47,
110
+ L: 48,
100
111
  S: this,
101
112
  C: (f, a) => f(...a)
102
113
  });
@@ -125,7 +136,7 @@ var BlobSyncExtension = class extends import_teleport.RpcExtension {
125
136
  err
126
137
  }, {
127
138
  F: __dxlog_file,
128
- L: 74,
139
+ L: 75,
129
140
  S: this,
130
141
  C: (f, a) => f(...a)
131
142
  });
@@ -142,7 +153,7 @@ var BlobSyncExtension = class extends import_teleport.RpcExtension {
142
153
  async onOpen(context) {
143
154
  (0, import_log.log)("open", void 0, {
144
155
  F: __dxlog_file,
145
- L: 106,
156
+ L: 107,
146
157
  S: this,
147
158
  C: (f, a) => f(...a)
148
159
  });
@@ -152,7 +163,7 @@ var BlobSyncExtension = class extends import_teleport.RpcExtension {
152
163
  async onClose(err) {
153
164
  (0, import_log.log)("close", void 0, {
154
165
  F: __dxlog_file,
155
- L: 112,
166
+ L: 113,
156
167
  S: this,
157
168
  C: (f, a) => f(...a)
158
169
  });
@@ -160,6 +171,17 @@ var BlobSyncExtension = class extends import_teleport.RpcExtension {
160
171
  await this._params.onClose();
161
172
  await super.onClose(err);
162
173
  }
174
+ async onAbort(err) {
175
+ (0, import_log.log)("abort", void 0, {
176
+ F: __dxlog_file,
177
+ L: 120,
178
+ S: this,
179
+ C: (f, a) => f(...a)
180
+ });
181
+ await this._ctx.dispose();
182
+ await this._params.onAbort();
183
+ await super.onAbort(err);
184
+ }
163
185
  async getHandlers() {
164
186
  return {
165
187
  BlobSyncService: {
@@ -168,7 +190,7 @@ var BlobSyncExtension = class extends import_teleport.RpcExtension {
168
190
  remoteWantList: wantList
169
191
  }, {
170
192
  F: __dxlog_file,
171
- L: 122,
193
+ L: 130,
172
194
  S: this,
173
195
  C: (f, a) => f(...a)
174
196
  });
@@ -180,7 +202,7 @@ var BlobSyncExtension = class extends import_teleport.RpcExtension {
180
202
  data
181
203
  }, {
182
204
  F: __dxlog_file,
183
- L: 127,
205
+ L: 135,
184
206
  S: this,
185
207
  C: (f, a) => f(...a)
186
208
  });
@@ -197,7 +219,7 @@ var BlobSyncExtension = class extends import_teleport.RpcExtension {
197
219
  data
198
220
  }, {
199
221
  F: __dxlog_file,
200
- L: 139,
222
+ L: 147,
201
223
  S: this,
202
224
  C: (f, a) => f(...a)
203
225
  });
@@ -234,7 +256,7 @@ var BlobSyncExtension = class extends import_teleport.RpcExtension {
234
256
  }
235
257
  (0, import_invariant.invariant)(meta.bitfield, void 0, {
236
258
  F: __dxlog_file,
237
- L: 178,
259
+ L: 186,
238
260
  S: this,
239
261
  A: [
240
262
  "meta.bitfield",
@@ -243,7 +265,7 @@ var BlobSyncExtension = class extends import_teleport.RpcExtension {
243
265
  });
244
266
  (0, import_invariant.invariant)(meta.chunkSize, void 0, {
245
267
  F: __dxlog_file,
246
- L: 179,
268
+ L: 187,
247
269
  S: this,
248
270
  A: [
249
271
  "meta.chunkSize",
@@ -252,7 +274,7 @@ var BlobSyncExtension = class extends import_teleport.RpcExtension {
252
274
  });
253
275
  (0, import_invariant.invariant)(meta.length, void 0, {
254
276
  F: __dxlog_file,
255
- L: 180,
277
+ L: 188,
256
278
  S: this,
257
279
  A: [
258
280
  "meta.length",
@@ -265,7 +287,7 @@ var BlobSyncExtension = class extends import_teleport.RpcExtension {
265
287
  meta
266
288
  }, {
267
289
  F: __dxlog_file,
268
- L: 183,
290
+ L: 191,
269
291
  S: this,
270
292
  C: (f, a) => f(...a)
271
293
  });
@@ -297,15 +319,6 @@ var BlobSyncExtension = class extends import_teleport.RpcExtension {
297
319
  _ts_decorate([
298
320
  import_async.synchronized
299
321
  ], BlobSyncExtension.prototype, "push", null);
300
-
301
- // packages/core/mesh/teleport-extension-object-sync/src/blob-sync.ts
302
- var import_async2 = require("@dxos/async");
303
- var import_context2 = require("@dxos/context");
304
- var import_invariant2 = require("@dxos/invariant");
305
- var import_keys = require("@dxos/keys");
306
- var import_log2 = require("@dxos/log");
307
- var import_blob = require("@dxos/protocols/proto/dxos/echo/blob");
308
- var import_util2 = require("@dxos/util");
309
322
  function _ts_decorate2(decorators, target, key, desc) {
310
323
  var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
311
324
  if (typeof Reflect === "object" && typeof Reflect.decorate === "function")
@@ -316,7 +329,7 @@ function _ts_decorate2(decorators, target, key, desc) {
316
329
  r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
317
330
  return c > 3 && r && Object.defineProperty(target, key, r), r;
318
331
  }
319
- var __dxlog_file2 = "/home/runner/work/dxos/dxos/packages/core/mesh/teleport-extension-object-sync/src/blob-sync.ts";
332
+ var __dxlog_file2 = "/home/circleci/project/packages/core/mesh/teleport-extension-object-sync/src/blob-sync.ts";
320
333
  var BlobSync = class BlobSync2 {
321
334
  constructor(_params) {
322
335
  this._params = _params;
@@ -402,6 +415,15 @@ var BlobSync = class BlobSync2 {
402
415
  });
403
416
  this._extensions.delete(extension);
404
417
  },
418
+ onAbort: async () => {
419
+ (0, import_log2.log)("extension aborted", void 0, {
420
+ F: __dxlog_file2,
421
+ L: 114,
422
+ S: this,
423
+ C: (f, a) => f(...a)
424
+ });
425
+ this._extensions.delete(extension);
426
+ },
405
427
  onPush: async (blobChunk) => {
406
428
  if (!this._downloadRequests.has(blobChunk.id)) {
407
429
  return;
@@ -410,7 +432,7 @@ var BlobSync = class BlobSync2 {
410
432
  blobChunk
411
433
  }, {
412
434
  F: __dxlog_file2,
413
- L: 117,
435
+ L: 121,
414
436
  S: this,
415
437
  C: (f, a) => f(...a)
416
438
  });
@@ -421,7 +443,7 @@ var BlobSync = class BlobSync2 {
421
443
  } else {
422
444
  (0, import_invariant2.invariant)(meta.bitfield, void 0, {
423
445
  F: __dxlog_file2,
424
- L: 123,
446
+ L: 127,
425
447
  S: this,
426
448
  A: [
427
449
  "meta.bitfield",
@@ -461,16 +483,6 @@ var BlobSync = class BlobSync2 {
461
483
  BlobSync = _ts_decorate2([
462
484
  (0, import_async2.trackLeaks)("open", "close")
463
485
  ], BlobSync);
464
-
465
- // packages/core/mesh/teleport-extension-object-sync/src/blob-store.ts
466
- var import_node_path = __toESM(require("node:path"));
467
- var import_async3 = require("@dxos/async");
468
- var import_crypto = require("@dxos/crypto");
469
- var import_invariant3 = require("@dxos/invariant");
470
- var import_keys2 = require("@dxos/keys");
471
- var import_protocols2 = require("@dxos/protocols");
472
- var import_blob2 = require("@dxos/protocols/proto/dxos/echo/blob");
473
- var import_util3 = require("@dxos/util");
474
486
  function _ts_decorate3(decorators, target, key, desc) {
475
487
  var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
476
488
  if (typeof Reflect === "object" && typeof Reflect.decorate === "function")
@@ -481,7 +493,7 @@ function _ts_decorate3(decorators, target, key, desc) {
481
493
  r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
482
494
  return c > 3 && r && Object.defineProperty(target, key, r), r;
483
495
  }
484
- var __dxlog_file3 = "/home/runner/work/dxos/dxos/packages/core/mesh/teleport-extension-object-sync/src/blob-store.ts";
496
+ var __dxlog_file3 = "/home/circleci/project/packages/core/mesh/teleport-extension-object-sync/src/blob-store.ts";
485
497
  var DEFAULT_CHUNK_SIZE = 4096;
486
498
  var BlobMetaCodec = import_protocols2.schema.getCodecForType("dxos.echo.blob.BlobMeta");
487
499
  var BlobStore = class {
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
- "sources": ["../../../src/index.ts", "../../../src/blob-sync-extension.ts", "../../../src/blob-sync.ts", "../../../src/blob-store.ts"],
4
- "sourcesContent": ["//\n// Copyright 2022 DXOS.org\n//\n\nexport * from './blob-sync-extension';\nexport * from './blob-sync';\nexport * from './blob-store';\n", "//\n\n//\n// Copyright 2023 DXOS.org\n//\n\nimport { DeferredTask, sleep, synchronized } from '@dxos/async';\nimport { Context } from '@dxos/context';\nimport { invariant } from '@dxos/invariant';\nimport { log } from '@dxos/log';\nimport { RpcClosedError, schema } from '@dxos/protocols';\nimport { type BlobChunk, type BlobSyncService, type WantList } from '@dxos/protocols/proto/dxos/mesh/teleport/blobsync';\nimport { type ExtensionContext, RpcExtension } from '@dxos/teleport';\nimport { BitField } from '@dxos/util';\n\nimport { type BlobStore } from './blob-store';\n\nexport type BlobSyncExtensionParams = {\n blobStore: BlobStore;\n onOpen: () => Promise<void>;\n onClose: () => Promise<void>;\n onPush: (data: BlobChunk) => Promise<void>;\n};\n\nconst MIN_WANT_LIST_UPDATE_INTERVAL = process.env.NODE_ENV === 'test' ? 5 : 500;\n\nconst MAX_CONCURRENT_UPLOADS = 20;\n\n/**\n * Manages replication between a set of feeds for a single teleport session.\n */\nexport class BlobSyncExtension extends RpcExtension<ServiceBundle, ServiceBundle> {\n private readonly _ctx = new Context({ onError: (err) => log.catch(err) });\n\n private _lastWantListUpdate = 0;\n private _localWantList: WantList = { blobs: [] };\n\n private readonly _updateWantList = new DeferredTask(this._ctx, async () => {\n // Throttle want list updates.\n if (this._lastWantListUpdate + MIN_WANT_LIST_UPDATE_INTERVAL > Date.now()) {\n await sleep(this._lastWantListUpdate + MIN_WANT_LIST_UPDATE_INTERVAL - Date.now());\n if (this._ctx.disposed) {\n return;\n }\n }\n\n log('want', { list: this._localWantList });\n await this.rpc.BlobSyncService.want(this._localWantList);\n this._lastWantListUpdate = Date.now();\n });\n\n private _currentUploads = 0;\n\n private readonly _upload = new DeferredTask(this._ctx, async () => {\n if (this._currentUploads >= MAX_CONCURRENT_UPLOADS) {\n return;\n }\n const blobChunks = await this._pickBlobChunks(MAX_CONCURRENT_UPLOADS - this._currentUploads);\n if (!blobChunks) {\n return;\n }\n for (const blobChunk of blobChunks) {\n if (this._ctx.disposed) {\n break;\n }\n\n this._currentUploads++;\n\n this.push(blobChunk)\n .catch((err) => {\n if (err instanceof RpcClosedError) {\n return;\n }\n log.warn('push failed', { err });\n })\n .finally(() => {\n this._currentUploads--;\n this.reconcileUploads();\n });\n }\n });\n\n /**\n * Set of id's remote peer wants.\n */\n public remoteWantList: WantList = { blobs: [] };\n\n constructor(\n private readonly _params: BlobSyncExtensionParams, // to not conflict with the base class\n ) {\n super({\n exposed: {\n BlobSyncService: schema.getService('dxos.mesh.teleport.blobsync.BlobSyncService'),\n },\n requested: {\n BlobSyncService: schema.getService('dxos.mesh.teleport.blobsync.BlobSyncService'),\n },\n timeout: 20_000,\n encodingOptions: {\n preserveAny: true,\n },\n });\n }\n\n override async onOpen(context: ExtensionContext): Promise<void> {\n log('open');\n await super.onOpen(context);\n await this._params.onOpen();\n }\n\n override async onClose(err?: Error | undefined): Promise<void> {\n log('close');\n await this._ctx.dispose();\n await this._params.onClose();\n await super.onClose(err);\n }\n\n protected async getHandlers(): Promise<ServiceBundle> {\n return {\n BlobSyncService: {\n want: async (wantList) => {\n log('remote want', { remoteWantList: wantList });\n this.remoteWantList = wantList;\n this.reconcileUploads();\n },\n push: async (data) => {\n log('received', { data });\n await this._params.onPush(data);\n },\n },\n };\n }\n\n @synchronized\n async push(data: BlobChunk) {\n if (this._ctx.disposed) {\n return;\n }\n log('push', { data });\n await this.rpc.BlobSyncService.push(data);\n }\n\n updateWantList(wantList: WantList) {\n if (this._ctx.disposed) {\n return;\n }\n this._localWantList = wantList;\n this._updateWantList.schedule();\n }\n\n reconcileUploads() {\n if (this._ctx.disposed) {\n return;\n }\n this._upload.schedule();\n }\n\n private async _pickBlobChunks(amount = 1): Promise<BlobChunk[] | void> {\n if (this._ctx.disposed) {\n return;\n }\n\n if (!this.remoteWantList.blobs || this.remoteWantList.blobs?.length === 0) {\n return;\n }\n\n const shuffled = [...this.remoteWantList.blobs].sort(() => Math.random() - 0.5);\n\n const chunks: BlobChunk[] = [];\n\n for (const header of shuffled) {\n const meta = await this._params.blobStore.getMeta(header.id);\n\n if (!meta) {\n // Skip this header\n continue;\n }\n invariant(meta.bitfield);\n invariant(meta.chunkSize);\n invariant(meta.length);\n\n if (header.chunkSize && header.chunkSize !== meta.chunkSize) {\n log.warn('Invalid chunk size', { header, meta });\n continue;\n }\n\n const requestBitfield = header.bitfield ?? BitField.ones(meta.length / meta.chunkSize);\n\n const presentData = BitField.and(requestBitfield, meta.bitfield);\n const chunkIndices = BitField.findIndexes(presentData).sort(() => Math.random() - 0.5);\n\n for (const idx of chunkIndices) {\n const chunkData = await this._params.blobStore.get(header.id, {\n offset: idx * meta.chunkSize,\n length: Math.min(meta.chunkSize, meta.length - idx * meta.chunkSize),\n });\n chunks.push({\n id: header.id,\n totalLength: meta.length,\n chunkSize: meta.chunkSize,\n chunkOffset: idx * meta.chunkSize,\n payload: chunkData,\n });\n\n if (chunks.length >= amount) {\n return chunks;\n }\n }\n }\n\n return chunks;\n }\n}\n\ntype ServiceBundle = {\n BlobSyncService: BlobSyncService;\n};\n", "//\n// Copyright 2023 DXOS.org\n//\n\nimport { trackLeaks, Trigger, Lock } from '@dxos/async';\nimport { cancelWithContext, Context } from '@dxos/context';\nimport { invariant } from '@dxos/invariant';\nimport { PublicKey } from '@dxos/keys';\nimport { log } from '@dxos/log';\nimport { BlobMeta } from '@dxos/protocols/proto/dxos/echo/blob';\nimport { type WantList } from '@dxos/protocols/proto/dxos/mesh/teleport/blobsync';\nimport { BitField, ComplexMap } from '@dxos/util';\n\nimport { type BlobStore } from './blob-store';\nimport { BlobSyncExtension } from './blob-sync-extension';\n\nexport type BlobSyncParams = {\n blobStore: BlobStore;\n};\n\ntype DownloadRequest = {\n trigger: Trigger<void>;\n counter: number;\n want: WantList.Entry;\n};\n\n// TODO(dmaretskyi): Rename to blob-sync.\n@trackLeaks('open', 'close')\nexport class BlobSync {\n private readonly _ctx = new Context();\n private readonly _lock = new Lock();\n\n private readonly _downloadRequests = new ComplexMap<Uint8Array, DownloadRequest>((key) =>\n PublicKey.from(key).toHex(),\n );\n\n private readonly _extensions = new Set<BlobSyncExtension>();\n\n constructor(private readonly _params: BlobSyncParams) {}\n\n async open() {}\n\n async close() {\n await this._ctx.dispose();\n }\n\n /**\n * Resolves when the object with the given id is fully downloaded in the blob store.\n *\n * @param id hex-encoded id of the object to download.\n */\n async download(ctx: Context, id: Uint8Array): Promise<void> {\n log('download', { id });\n const request = await this._lock.executeSynchronized(async () => {\n const existingRequest = this._downloadRequests.get(id);\n\n if (existingRequest) {\n existingRequest.counter++;\n return existingRequest;\n }\n\n const meta = await this._params.blobStore.getMeta(id);\n const request: DownloadRequest = {\n trigger: new Trigger(),\n counter: 1,\n want: {\n id,\n chunkSize: meta?.chunkSize,\n bitfield: meta?.bitfield && Uint8Array.from(BitField.invert(meta.bitfield)),\n },\n };\n\n // Check if the object is already fully downloaded.\n if (meta?.state === BlobMeta.State.FULLY_PRESENT) {\n request.trigger.wake();\n } else {\n this._downloadRequests.set(id, request);\n this._updateExtensionsWantList();\n }\n\n return request;\n });\n\n ctx?.onDispose(() =>\n this._lock.executeSynchronized(async () => {\n // Remove request if context is disposed and nobody else requests it.\n const request = this._downloadRequests.get(id);\n if (!request) {\n return;\n }\n if (--request.counter === 0) {\n this._downloadRequests.delete(id);\n }\n this._updateExtensionsWantList();\n }),\n );\n\n return ctx ? cancelWithContext(ctx, request.trigger.wait()) : request.trigger.wait();\n }\n\n createExtension() {\n const extension = new BlobSyncExtension({\n blobStore: this._params.blobStore,\n onOpen: async () => {\n log('extension opened');\n this._extensions.add(extension);\n extension.updateWantList(this._getWantList());\n },\n onClose: async () => {\n log('extension closed');\n this._extensions.delete(extension);\n },\n onPush: async (blobChunk) => {\n if (!this._downloadRequests.has(blobChunk.id)) {\n return;\n }\n log('received', { blobChunk });\n const meta = await this._params.blobStore.setChunk(blobChunk);\n if (meta.state === BlobMeta.State.FULLY_PRESENT) {\n this._downloadRequests.get(blobChunk.id)?.trigger.wake();\n this._downloadRequests.delete(blobChunk.id);\n } else {\n invariant(meta.bitfield);\n this._downloadRequests.get(blobChunk.id)!.want.bitfield = BitField.invert(meta.bitfield);\n }\n\n this._updateExtensionsWantList();\n this._reconcileUploads();\n },\n });\n return extension;\n }\n\n /**\n * Notify extensions that a blob with the given id was added to the blob store.\n */\n async notifyBlobAdded(_id: Uint8Array) {\n this._reconcileUploads();\n }\n\n private _getWantList(): WantList {\n return {\n blobs: Array.from(this._downloadRequests.values()).map((request) => request.want),\n };\n }\n\n private _reconcileUploads() {\n for (const extension of this._extensions) {\n extension.reconcileUploads();\n }\n }\n\n private _updateExtensionsWantList() {\n for (const extension of this._extensions) {\n extension.updateWantList(this._getWantList());\n }\n }\n}\n", "//\n// Copyright 2023 DXOS.org\n//\n\nimport path from 'node:path';\n\nimport { synchronized } from '@dxos/async';\nimport { subtleCrypto } from '@dxos/crypto';\nimport { invariant } from '@dxos/invariant';\nimport { PublicKey } from '@dxos/keys';\nimport { schema } from '@dxos/protocols';\nimport { BlobMeta } from '@dxos/protocols/proto/dxos/echo/blob';\nimport { type BlobChunk } from '@dxos/protocols/proto/dxos/mesh/teleport/blobsync';\nimport { type Directory } from '@dxos/random-access-storage';\nimport { BitField, arrayToBuffer } from '@dxos/util';\n\nexport type GetOptions = {\n offset?: number;\n length?: number;\n};\n\nexport const DEFAULT_CHUNK_SIZE = 4096;\n\nconst BlobMetaCodec = schema.getCodecForType('dxos.echo.blob.BlobMeta');\n\nexport class BlobStore {\n constructor(private readonly _directory: Directory) {}\n\n @synchronized\n async getMeta(id: Uint8Array): Promise<BlobMeta | undefined> {\n return this._getMeta(id);\n }\n\n /**\n * @throws If range is not available.\n */\n @synchronized\n async get(id: Uint8Array, options: GetOptions = {}): Promise<Uint8Array> {\n const metadata = await this._getMeta(id);\n\n if (!metadata) {\n throw new Error('Blob not available');\n }\n\n const { offset = 0, length = metadata.length } = options;\n\n if (offset + length > metadata.length) {\n throw new Error('Invalid range');\n }\n\n if (metadata.state === BlobMeta.State.FULLY_PRESENT) {\n const file = this._getDataFile(id);\n return file.read(offset, length);\n } else if (options.offset === undefined && options.length === undefined) {\n throw new Error('Blob not available');\n }\n\n const beginChunk = Math.floor(offset / metadata.chunkSize);\n const endChunk = Math.ceil((offset + length) / metadata.chunkSize);\n\n invariant(metadata.bitfield, 'Bitfield not present');\n invariant(metadata.bitfield.length * 8 >= endChunk, 'Invalid bitfield length');\n\n const present = BitField.count(metadata.bitfield, beginChunk, endChunk) === endChunk - beginChunk;\n\n if (!present) {\n throw new Error('Blob not available');\n }\n\n const file = this._getDataFile(id);\n return file.read(offset, length);\n }\n\n @synchronized\n async list(): Promise<BlobMeta[]> {\n /*\n Weird path formatting:\n\n \"e9b9aa7a21c2c55a9eca333cd59975633157562ca0a0f4f243d4778f192c291e_meta\"\n \"e9b9aa7a21c2c55a9eca333cd59975633157562ca0a0f4f243d4778f192c291e_data\"\n \"5001de5a47191357c075aeee6451c4cc323f3a8ada24dd1191e83403608a38d5_meta\n */\n const files = new Set((await this._directory.list()).map((f) => f.split('_')[0]));\n\n const res: BlobMeta[] = [];\n\n for (const file of files) {\n const id = PublicKey.from(file).asUint8Array();\n const meta = await this._getMeta(id);\n if (meta) {\n res.push(meta);\n }\n }\n\n return res;\n }\n\n @synchronized\n async set(data: Uint8Array): Promise<BlobMeta> {\n const id = new Uint8Array(await subtleCrypto.digest('SHA-256', data));\n const bitfield = BitField.ones(data.length / DEFAULT_CHUNK_SIZE);\n\n const meta: BlobMeta = {\n id,\n state: BlobMeta.State.FULLY_PRESENT,\n length: data.length,\n chunkSize: DEFAULT_CHUNK_SIZE,\n bitfield,\n created: new Date(),\n updated: new Date(),\n };\n\n await this._getDataFile(id).write(0, arrayToBuffer(data));\n await this._writeMeta(id, meta);\n return meta;\n }\n\n // TODO(dmaretskyi): Optimize locking.\n @synchronized\n async setChunk(chunk: BlobChunk): Promise<BlobMeta> {\n // Init metadata.\n let meta = await this._getMeta(chunk.id);\n if (!meta) {\n invariant(chunk.totalLength, 'totalLength is not present');\n meta = {\n id: chunk.id,\n state: BlobMeta.State.PARTIALLY_PRESENT,\n length: chunk.totalLength,\n chunkSize: chunk.chunkSize ?? DEFAULT_CHUNK_SIZE,\n created: new Date(),\n };\n meta.bitfield = BitField.zeros(meta.length / meta.chunkSize);\n }\n\n if (chunk.chunkSize && chunk.chunkSize !== meta.chunkSize) {\n throw new Error('Invalid chunk size');\n }\n\n invariant(meta.bitfield, 'Bitfield not present');\n invariant(chunk.chunkOffset !== undefined, 'chunkOffset is not present');\n\n // Write chunk.\n await this._getDataFile(chunk.id).write(chunk.chunkOffset, arrayToBuffer(chunk.payload));\n\n // Update bitfield.\n BitField.set(meta.bitfield, Math.floor(chunk.chunkOffset / meta.chunkSize), true);\n\n // Update metadata.\n if (BitField.count(meta.bitfield, 0, meta.length) * meta.chunkSize >= meta.length) {\n meta.state = BlobMeta.State.FULLY_PRESENT;\n }\n meta.updated = new Date();\n\n await this._writeMeta(chunk.id, meta);\n\n return meta;\n }\n\n private async _writeMeta(id: Uint8Array, meta: BlobMeta): Promise<void> {\n const encoded = arrayToBuffer(BlobMetaCodec.encode(meta));\n const data = Buffer.alloc(encoded.length + 4);\n data.writeUInt32LE(encoded.length, 0);\n encoded.copy(data, 4);\n\n // Write metadata.\n await this._getMetaFile(id).write(0, data);\n }\n\n private async _getMeta(id: Uint8Array): Promise<BlobMeta | undefined> {\n const file = this._getMetaFile(id);\n const size = (await file.stat()).size;\n if (size === 0) {\n return;\n }\n const data = await file.read(0, size);\n const protoSize = data.readUInt32LE(0);\n return BlobMetaCodec.decode(data.subarray(4, protoSize + 4));\n }\n\n private _getMetaFile(id: Uint8Array) {\n return this._directory.getOrCreateFile(path.join(arrayToBuffer(id).toString('hex'), 'meta'));\n }\n\n private _getDataFile(id: Uint8Array) {\n return this._directory.getOrCreateFile(path.join(arrayToBuffer(id).toString('hex'), 'data'));\n }\n}\n"],
5
- "mappings": "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",
6
- "names": ["MIN_WANT_LIST_UPDATE_INTERVAL", "process", "env", "NODE_ENV", "MAX_CONCURRENT_UPLOADS", "BlobSyncExtension", "RpcExtension", "constructor", "_params", "exposed", "BlobSyncService", "schema", "getService", "requested", "timeout", "encodingOptions", "preserveAny", "_ctx", "Context", "onError", "err", "log", "catch", "_lastWantListUpdate", "_localWantList", "blobs", "_updateWantList", "DeferredTask", "Date", "now", "sleep", "disposed", "list", "rpc", "want", "_currentUploads", "_upload", "blobChunks", "_pickBlobChunks", "blobChunk", "push", "RpcClosedError", "warn", "finally", "reconcileUploads", "remoteWantList", "onOpen", "context", "onClose", "dispose", "getHandlers", "wantList", "data", "onPush", "updateWantList", "schedule", "amount", "length", "shuffled", "sort", "Math", "random", "chunks", "header", "meta", "blobStore", "getMeta", "id", "invariant", "bitfield", "chunkSize", "requestBitfield", "BitField", "ones", "presentData", "and", "chunkIndices", "findIndexes", "idx", "chunkData", "get", "offset", "min", "totalLength", "chunkOffset", "payload", "synchronized", "import_async", "import_context", "import_invariant", "import_log", "import_util", "BlobSync", "constructor", "_params", "_ctx", "Context", "_lock", "Lock", "_downloadRequests", "ComplexMap", "key", "PublicKey", "from", "toHex", "_extensions", "Set", "open", "close", "dispose", "download", "ctx", "id", "log", "request", "executeSynchronized", "existingRequest", "get", "counter", "meta", "blobStore", "getMeta", "trigger", "Trigger", "want", "chunkSize", "bitfield", "Uint8Array", "BitField", "invert", "state", "BlobMeta", "State", "FULLY_PRESENT", "wake", "set", "_updateExtensionsWantList", "onDispose", "delete", "cancelWithContext", "wait", "createExtension", "extension", "BlobSyncExtension", "onOpen", "add", "updateWantList", "_getWantList", "onClose", "onPush", "blobChunk", "has", "setChunk", "invariant", "_reconcileUploads", "notifyBlobAdded", "_id", "blobs", "Array", "values", "map", "reconcileUploads", "trackLeaks", "import_async", "import_invariant", "import_keys", "import_protocols", "import_blob", "import_util", "DEFAULT_CHUNK_SIZE", "BlobMetaCodec", "schema", "getCodecForType", "BlobStore", "constructor", "_directory", "getMeta", "id", "_getMeta", "get", "options", "metadata", "Error", "offset", "length", "state", "BlobMeta", "State", "FULLY_PRESENT", "file", "_getDataFile", "read", "undefined", "beginChunk", "Math", "floor", "chunkSize", "endChunk", "ceil", "invariant", "bitfield", "present", "BitField", "count", "list", "files", "Set", "map", "f", "split", "res", "PublicKey", "from", "asUint8Array", "meta", "push", "set", "data", "Uint8Array", "subtleCrypto", "digest", "ones", "created", "Date", "updated", "write", "arrayToBuffer", "_writeMeta", "setChunk", "chunk", "totalLength", "PARTIALLY_PRESENT", "zeros", "chunkOffset", "payload", "encoded", "encode", "Buffer", "alloc", "writeUInt32LE", "copy", "_getMetaFile", "size", "stat", "protoSize", "readUInt32LE", "decode", "subarray", "getOrCreateFile", "path", "join", "toString", "synchronized"]
3
+ "sources": ["../../../src/blob-sync-extension.ts", "../../../src/blob-sync.ts", "../../../src/blob-store.ts"],
4
+ "sourcesContent": ["//\n\n//\n// Copyright 2023 DXOS.org\n//\n\nimport { DeferredTask, sleep, synchronized } from '@dxos/async';\nimport { Context } from '@dxos/context';\nimport { invariant } from '@dxos/invariant';\nimport { log } from '@dxos/log';\nimport { RpcClosedError, schema } from '@dxos/protocols';\nimport { type BlobChunk, type BlobSyncService, type WantList } from '@dxos/protocols/proto/dxos/mesh/teleport/blobsync';\nimport { type ExtensionContext, RpcExtension } from '@dxos/teleport';\nimport { BitField } from '@dxos/util';\n\nimport { type BlobStore } from './blob-store';\n\nexport type BlobSyncExtensionParams = {\n blobStore: BlobStore;\n onOpen: () => Promise<void>;\n onClose: () => Promise<void>;\n onAbort: () => Promise<void>;\n onPush: (data: BlobChunk) => Promise<void>;\n};\n\nconst MIN_WANT_LIST_UPDATE_INTERVAL = process.env.NODE_ENV === 'test' ? 5 : 500;\n\nconst MAX_CONCURRENT_UPLOADS = 20;\n\n/**\n * Manages replication between a set of feeds for a single teleport session.\n */\nexport class BlobSyncExtension extends RpcExtension<ServiceBundle, ServiceBundle> {\n private readonly _ctx = new Context({ onError: (err) => log.catch(err) });\n\n private _lastWantListUpdate = 0;\n private _localWantList: WantList = { blobs: [] };\n\n private readonly _updateWantList = new DeferredTask(this._ctx, async () => {\n // Throttle want list updates.\n if (this._lastWantListUpdate + MIN_WANT_LIST_UPDATE_INTERVAL > Date.now()) {\n await sleep(this._lastWantListUpdate + MIN_WANT_LIST_UPDATE_INTERVAL - Date.now());\n if (this._ctx.disposed) {\n return;\n }\n }\n\n log('want', { list: this._localWantList });\n await this.rpc.BlobSyncService.want(this._localWantList);\n this._lastWantListUpdate = Date.now();\n });\n\n private _currentUploads = 0;\n\n private readonly _upload = new DeferredTask(this._ctx, async () => {\n if (this._currentUploads >= MAX_CONCURRENT_UPLOADS) {\n return;\n }\n const blobChunks = await this._pickBlobChunks(MAX_CONCURRENT_UPLOADS - this._currentUploads);\n if (!blobChunks) {\n return;\n }\n for (const blobChunk of blobChunks) {\n if (this._ctx.disposed) {\n break;\n }\n\n this._currentUploads++;\n\n this.push(blobChunk)\n .catch((err) => {\n if (err instanceof RpcClosedError) {\n return;\n }\n log.warn('push failed', { err });\n })\n .finally(() => {\n this._currentUploads--;\n this.reconcileUploads();\n });\n }\n });\n\n /**\n * Set of id's remote peer wants.\n */\n public remoteWantList: WantList = { blobs: [] };\n\n constructor(\n private readonly _params: BlobSyncExtensionParams, // to not conflict with the base class\n ) {\n super({\n exposed: {\n BlobSyncService: schema.getService('dxos.mesh.teleport.blobsync.BlobSyncService'),\n },\n requested: {\n BlobSyncService: schema.getService('dxos.mesh.teleport.blobsync.BlobSyncService'),\n },\n timeout: 20_000,\n encodingOptions: {\n preserveAny: true,\n },\n });\n }\n\n override async onOpen(context: ExtensionContext): Promise<void> {\n log('open');\n await super.onOpen(context);\n await this._params.onOpen();\n }\n\n override async onClose(err?: Error | undefined): Promise<void> {\n log('close');\n await this._ctx.dispose();\n await this._params.onClose();\n await super.onClose(err);\n }\n\n override async onAbort(err?: Error | undefined): Promise<void> {\n log('abort');\n await this._ctx.dispose();\n await this._params.onAbort();\n await super.onAbort(err);\n }\n\n protected async getHandlers(): Promise<ServiceBundle> {\n return {\n BlobSyncService: {\n want: async (wantList) => {\n log('remote want', { remoteWantList: wantList });\n this.remoteWantList = wantList;\n this.reconcileUploads();\n },\n push: async (data) => {\n log('received', { data });\n await this._params.onPush(data);\n },\n },\n };\n }\n\n @synchronized\n async push(data: BlobChunk) {\n if (this._ctx.disposed) {\n return;\n }\n log('push', { data });\n await this.rpc.BlobSyncService.push(data);\n }\n\n updateWantList(wantList: WantList) {\n if (this._ctx.disposed) {\n return;\n }\n this._localWantList = wantList;\n this._updateWantList.schedule();\n }\n\n reconcileUploads() {\n if (this._ctx.disposed) {\n return;\n }\n this._upload.schedule();\n }\n\n private async _pickBlobChunks(amount = 1): Promise<BlobChunk[] | void> {\n if (this._ctx.disposed) {\n return;\n }\n\n if (!this.remoteWantList.blobs || this.remoteWantList.blobs?.length === 0) {\n return;\n }\n\n const shuffled = [...this.remoteWantList.blobs].sort(() => Math.random() - 0.5);\n\n const chunks: BlobChunk[] = [];\n\n for (const header of shuffled) {\n const meta = await this._params.blobStore.getMeta(header.id);\n\n if (!meta) {\n // Skip this header\n continue;\n }\n invariant(meta.bitfield);\n invariant(meta.chunkSize);\n invariant(meta.length);\n\n if (header.chunkSize && header.chunkSize !== meta.chunkSize) {\n log.warn('Invalid chunk size', { header, meta });\n continue;\n }\n\n const requestBitfield = header.bitfield ?? BitField.ones(meta.length / meta.chunkSize);\n\n const presentData = BitField.and(requestBitfield, meta.bitfield);\n const chunkIndices = BitField.findIndexes(presentData).sort(() => Math.random() - 0.5);\n\n for (const idx of chunkIndices) {\n const chunkData = await this._params.blobStore.get(header.id, {\n offset: idx * meta.chunkSize,\n length: Math.min(meta.chunkSize, meta.length - idx * meta.chunkSize),\n });\n chunks.push({\n id: header.id,\n totalLength: meta.length,\n chunkSize: meta.chunkSize,\n chunkOffset: idx * meta.chunkSize,\n payload: chunkData,\n });\n\n if (chunks.length >= amount) {\n return chunks;\n }\n }\n }\n\n return chunks;\n }\n}\n\ntype ServiceBundle = {\n BlobSyncService: BlobSyncService;\n};\n", "//\n// Copyright 2023 DXOS.org\n//\n\nimport { trackLeaks, Trigger, Lock } from '@dxos/async';\nimport { cancelWithContext, Context } from '@dxos/context';\nimport { invariant } from '@dxos/invariant';\nimport { PublicKey } from '@dxos/keys';\nimport { log } from '@dxos/log';\nimport { BlobMeta } from '@dxos/protocols/proto/dxos/echo/blob';\nimport { type WantList } from '@dxos/protocols/proto/dxos/mesh/teleport/blobsync';\nimport { BitField, ComplexMap } from '@dxos/util';\n\nimport { type BlobStore } from './blob-store';\nimport { BlobSyncExtension } from './blob-sync-extension';\n\nexport type BlobSyncParams = {\n blobStore: BlobStore;\n};\n\ntype DownloadRequest = {\n trigger: Trigger<void>;\n counter: number;\n want: WantList.Entry;\n};\n\n// TODO(dmaretskyi): Rename to blob-sync.\n@trackLeaks('open', 'close')\nexport class BlobSync {\n private readonly _ctx = new Context();\n private readonly _lock = new Lock();\n\n private readonly _downloadRequests = new ComplexMap<Uint8Array, DownloadRequest>((key) =>\n PublicKey.from(key).toHex(),\n );\n\n private readonly _extensions = new Set<BlobSyncExtension>();\n\n constructor(private readonly _params: BlobSyncParams) {}\n\n async open() {}\n\n async close() {\n await this._ctx.dispose();\n }\n\n /**\n * Resolves when the object with the given id is fully downloaded in the blob store.\n *\n * @param id hex-encoded id of the object to download.\n */\n async download(ctx: Context, id: Uint8Array): Promise<void> {\n log('download', { id });\n const request = await this._lock.executeSynchronized(async () => {\n const existingRequest = this._downloadRequests.get(id);\n\n if (existingRequest) {\n existingRequest.counter++;\n return existingRequest;\n }\n\n const meta = await this._params.blobStore.getMeta(id);\n const request: DownloadRequest = {\n trigger: new Trigger(),\n counter: 1,\n want: {\n id,\n chunkSize: meta?.chunkSize,\n bitfield: meta?.bitfield && Uint8Array.from(BitField.invert(meta.bitfield)),\n },\n };\n\n // Check if the object is already fully downloaded.\n if (meta?.state === BlobMeta.State.FULLY_PRESENT) {\n request.trigger.wake();\n } else {\n this._downloadRequests.set(id, request);\n this._updateExtensionsWantList();\n }\n\n return request;\n });\n\n ctx?.onDispose(() =>\n this._lock.executeSynchronized(async () => {\n // Remove request if context is disposed and nobody else requests it.\n const request = this._downloadRequests.get(id);\n if (!request) {\n return;\n }\n if (--request.counter === 0) {\n this._downloadRequests.delete(id);\n }\n this._updateExtensionsWantList();\n }),\n );\n\n return ctx ? cancelWithContext(ctx, request.trigger.wait()) : request.trigger.wait();\n }\n\n createExtension() {\n const extension = new BlobSyncExtension({\n blobStore: this._params.blobStore,\n onOpen: async () => {\n log('extension opened');\n this._extensions.add(extension);\n extension.updateWantList(this._getWantList());\n },\n onClose: async () => {\n log('extension closed');\n this._extensions.delete(extension);\n },\n onAbort: async () => {\n log('extension aborted');\n this._extensions.delete(extension);\n },\n onPush: async (blobChunk) => {\n if (!this._downloadRequests.has(blobChunk.id)) {\n return;\n }\n log('received', { blobChunk });\n const meta = await this._params.blobStore.setChunk(blobChunk);\n if (meta.state === BlobMeta.State.FULLY_PRESENT) {\n this._downloadRequests.get(blobChunk.id)?.trigger.wake();\n this._downloadRequests.delete(blobChunk.id);\n } else {\n invariant(meta.bitfield);\n this._downloadRequests.get(blobChunk.id)!.want.bitfield = BitField.invert(meta.bitfield);\n }\n\n this._updateExtensionsWantList();\n this._reconcileUploads();\n },\n });\n return extension;\n }\n\n /**\n * Notify extensions that a blob with the given id was added to the blob store.\n */\n async notifyBlobAdded(_id: Uint8Array) {\n this._reconcileUploads();\n }\n\n private _getWantList(): WantList {\n return {\n blobs: Array.from(this._downloadRequests.values()).map((request) => request.want),\n };\n }\n\n private _reconcileUploads() {\n for (const extension of this._extensions) {\n extension.reconcileUploads();\n }\n }\n\n private _updateExtensionsWantList() {\n for (const extension of this._extensions) {\n extension.updateWantList(this._getWantList());\n }\n }\n}\n", "//\n// Copyright 2023 DXOS.org\n//\n\nimport path from 'node:path';\n\nimport { synchronized } from '@dxos/async';\nimport { subtleCrypto } from '@dxos/crypto';\nimport { invariant } from '@dxos/invariant';\nimport { PublicKey } from '@dxos/keys';\nimport { schema } from '@dxos/protocols';\nimport { BlobMeta } from '@dxos/protocols/proto/dxos/echo/blob';\nimport { type BlobChunk } from '@dxos/protocols/proto/dxos/mesh/teleport/blobsync';\nimport { type Directory } from '@dxos/random-access-storage';\nimport { BitField, arrayToBuffer } from '@dxos/util';\n\nexport type GetOptions = {\n offset?: number;\n length?: number;\n};\n\nexport const DEFAULT_CHUNK_SIZE = 4096;\n\nconst BlobMetaCodec = schema.getCodecForType('dxos.echo.blob.BlobMeta');\n\nexport class BlobStore {\n constructor(private readonly _directory: Directory) {}\n\n @synchronized\n async getMeta(id: Uint8Array): Promise<BlobMeta | undefined> {\n return this._getMeta(id);\n }\n\n /**\n * @throws If range is not available.\n */\n @synchronized\n async get(id: Uint8Array, options: GetOptions = {}): Promise<Uint8Array> {\n const metadata = await this._getMeta(id);\n\n if (!metadata) {\n throw new Error('Blob not available');\n }\n\n const { offset = 0, length = metadata.length } = options;\n\n if (offset + length > metadata.length) {\n throw new Error('Invalid range');\n }\n\n if (metadata.state === BlobMeta.State.FULLY_PRESENT) {\n const file = this._getDataFile(id);\n return file.read(offset, length);\n } else if (options.offset === undefined && options.length === undefined) {\n throw new Error('Blob not available');\n }\n\n const beginChunk = Math.floor(offset / metadata.chunkSize);\n const endChunk = Math.ceil((offset + length) / metadata.chunkSize);\n\n invariant(metadata.bitfield, 'Bitfield not present');\n invariant(metadata.bitfield.length * 8 >= endChunk, 'Invalid bitfield length');\n\n const present = BitField.count(metadata.bitfield, beginChunk, endChunk) === endChunk - beginChunk;\n\n if (!present) {\n throw new Error('Blob not available');\n }\n\n const file = this._getDataFile(id);\n return file.read(offset, length);\n }\n\n @synchronized\n async list(): Promise<BlobMeta[]> {\n /*\n Weird path formatting:\n\n \"e9b9aa7a21c2c55a9eca333cd59975633157562ca0a0f4f243d4778f192c291e_meta\"\n \"e9b9aa7a21c2c55a9eca333cd59975633157562ca0a0f4f243d4778f192c291e_data\"\n \"5001de5a47191357c075aeee6451c4cc323f3a8ada24dd1191e83403608a38d5_meta\n */\n const files = new Set((await this._directory.list()).map((f) => f.split('_')[0]));\n\n const res: BlobMeta[] = [];\n\n for (const file of files) {\n const id = PublicKey.from(file).asUint8Array();\n const meta = await this._getMeta(id);\n if (meta) {\n res.push(meta);\n }\n }\n\n return res;\n }\n\n @synchronized\n async set(data: Uint8Array): Promise<BlobMeta> {\n const id = new Uint8Array(await subtleCrypto.digest('SHA-256', data));\n const bitfield = BitField.ones(data.length / DEFAULT_CHUNK_SIZE);\n\n const meta: BlobMeta = {\n id,\n state: BlobMeta.State.FULLY_PRESENT,\n length: data.length,\n chunkSize: DEFAULT_CHUNK_SIZE,\n bitfield,\n created: new Date(),\n updated: new Date(),\n };\n\n await this._getDataFile(id).write(0, arrayToBuffer(data));\n await this._writeMeta(id, meta);\n return meta;\n }\n\n // TODO(dmaretskyi): Optimize locking.\n @synchronized\n async setChunk(chunk: BlobChunk): Promise<BlobMeta> {\n // Init metadata.\n let meta = await this._getMeta(chunk.id);\n if (!meta) {\n invariant(chunk.totalLength, 'totalLength is not present');\n meta = {\n id: chunk.id,\n state: BlobMeta.State.PARTIALLY_PRESENT,\n length: chunk.totalLength,\n chunkSize: chunk.chunkSize ?? DEFAULT_CHUNK_SIZE,\n created: new Date(),\n };\n meta.bitfield = BitField.zeros(meta.length / meta.chunkSize);\n }\n\n if (chunk.chunkSize && chunk.chunkSize !== meta.chunkSize) {\n throw new Error('Invalid chunk size');\n }\n\n invariant(meta.bitfield, 'Bitfield not present');\n invariant(chunk.chunkOffset !== undefined, 'chunkOffset is not present');\n\n // Write chunk.\n await this._getDataFile(chunk.id).write(chunk.chunkOffset, arrayToBuffer(chunk.payload));\n\n // Update bitfield.\n BitField.set(meta.bitfield, Math.floor(chunk.chunkOffset / meta.chunkSize), true);\n\n // Update metadata.\n if (BitField.count(meta.bitfield, 0, meta.length) * meta.chunkSize >= meta.length) {\n meta.state = BlobMeta.State.FULLY_PRESENT;\n }\n meta.updated = new Date();\n\n await this._writeMeta(chunk.id, meta);\n\n return meta;\n }\n\n private async _writeMeta(id: Uint8Array, meta: BlobMeta): Promise<void> {\n const encoded = arrayToBuffer(BlobMetaCodec.encode(meta));\n const data = Buffer.alloc(encoded.length + 4);\n data.writeUInt32LE(encoded.length, 0);\n encoded.copy(data, 4);\n\n // Write metadata.\n await this._getMetaFile(id).write(0, data);\n }\n\n private async _getMeta(id: Uint8Array): Promise<BlobMeta | undefined> {\n const file = this._getMetaFile(id);\n const size = (await file.stat()).size;\n if (size === 0) {\n return;\n }\n const data = await file.read(0, size);\n const protoSize = data.readUInt32LE(0);\n return BlobMetaCodec.decode(data.subarray(4, protoSize + 4));\n }\n\n private _getMetaFile(id: Uint8Array) {\n return this._directory.getOrCreateFile(path.join(arrayToBuffer(id).toString('hex'), 'meta'));\n }\n\n private _getDataFile(id: Uint8Array) {\n return this._directory.getOrCreateFile(path.join(arrayToBuffer(id).toString('hex'), 'data'));\n }\n}\n"],
5
+ "mappings": "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",
6
+ "names": ["import_async", "import_context", "import_invariant", "import_log", "import_util", "import_keys", "import_protocols", "import_blob", "MIN_WANT_LIST_UPDATE_INTERVAL", "process", "env", "NODE_ENV", "MAX_CONCURRENT_UPLOADS", "BlobSyncExtension", "RpcExtension", "constructor", "_params", "exposed", "BlobSyncService", "schema", "getService", "requested", "timeout", "encodingOptions", "preserveAny", "_ctx", "Context", "onError", "err", "log", "catch", "_lastWantListUpdate", "_localWantList", "blobs", "_updateWantList", "DeferredTask", "Date", "now", "sleep", "disposed", "list", "rpc", "want", "_currentUploads", "_upload", "blobChunks", "_pickBlobChunks", "blobChunk", "push", "RpcClosedError", "warn", "finally", "reconcileUploads", "remoteWantList", "onOpen", "context", "onClose", "dispose", "onAbort", "getHandlers", "wantList", "data", "onPush", "updateWantList", "schedule", "amount", "length", "shuffled", "sort", "Math", "random", "chunks", "header", "meta", "blobStore", "getMeta", "id", "invariant", "bitfield", "chunkSize", "requestBitfield", "BitField", "ones", "presentData", "and", "chunkIndices", "findIndexes", "idx", "chunkData", "get", "offset", "min", "totalLength", "chunkOffset", "payload", "synchronized", "BlobSync", "_lock", "Lock", "_downloadRequests", "ComplexMap", "key", "PublicKey", "from", "toHex", "_extensions", "Set", "open", "close", "download", "ctx", "request", "executeSynchronized", "existingRequest", "counter", "trigger", "Trigger", "Uint8Array", "invert", "state", "BlobMeta", "State", "FULLY_PRESENT", "wake", "set", "_updateExtensionsWantList", "onDispose", "delete", "cancelWithContext", "wait", "createExtension", "extension", "add", "_getWantList", "has", "setChunk", "_reconcileUploads", "notifyBlobAdded", "_id", "Array", "values", "map", "trackLeaks", "DEFAULT_CHUNK_SIZE", "BlobMetaCodec", "getCodecForType", "BlobStore", "_directory", "_getMeta", "options", "metadata", "Error", "file", "_getDataFile", "read", "undefined", "beginChunk", "floor", "endChunk", "ceil", "present", "count", "files", "f", "split", "res", "asUint8Array", "subtleCrypto", "digest", "created", "updated", "write", "arrayToBuffer", "_writeMeta", "chunk", "PARTIALLY_PRESENT", "zeros", "encoded", "encode", "Buffer", "alloc", "writeUInt32LE", "copy", "_getMetaFile", "size", "stat", "protoSize", "readUInt32LE", "decode", "subarray", "getOrCreateFile", "path", "join", "toString"]
7
7
  }
@@ -1 +1 @@
1
- {"inputs":{"packages/core/mesh/teleport-extension-object-sync/src/blob-sync-extension.ts":{"bytes":24384,"imports":[{"path":"@dxos/async","kind":"import-statement","external":true},{"path":"@dxos/context","kind":"import-statement","external":true},{"path":"@dxos/invariant","kind":"import-statement","external":true},{"path":"@dxos/log","kind":"import-statement","external":true},{"path":"@dxos/protocols","kind":"import-statement","external":true},{"path":"@dxos/teleport","kind":"import-statement","external":true},{"path":"@dxos/util","kind":"import-statement","external":true}],"format":"esm"},"packages/core/mesh/teleport-extension-object-sync/src/blob-sync.ts":{"bytes":17817,"imports":[{"path":"@dxos/async","kind":"import-statement","external":true},{"path":"@dxos/context","kind":"import-statement","external":true},{"path":"@dxos/invariant","kind":"import-statement","external":true},{"path":"@dxos/keys","kind":"import-statement","external":true},{"path":"@dxos/log","kind":"import-statement","external":true},{"path":"@dxos/protocols/proto/dxos/echo/blob","kind":"import-statement","external":true},{"path":"@dxos/util","kind":"import-statement","external":true},{"path":"packages/core/mesh/teleport-extension-object-sync/src/blob-sync-extension.ts","kind":"import-statement","original":"./blob-sync-extension"}],"format":"esm"},"packages/core/mesh/teleport-extension-object-sync/src/blob-store.ts":{"bytes":22281,"imports":[{"path":"node:path","kind":"import-statement","external":true},{"path":"@dxos/async","kind":"import-statement","external":true},{"path":"@dxos/crypto","kind":"import-statement","external":true},{"path":"@dxos/invariant","kind":"import-statement","external":true},{"path":"@dxos/keys","kind":"import-statement","external":true},{"path":"@dxos/protocols","kind":"import-statement","external":true},{"path":"@dxos/protocols/proto/dxos/echo/blob","kind":"import-statement","external":true},{"path":"@dxos/util","kind":"import-statement","external":true}],"format":"esm"},"packages/core/mesh/teleport-extension-object-sync/src/index.ts":{"bytes":703,"imports":[{"path":"packages/core/mesh/teleport-extension-object-sync/src/blob-sync-extension.ts","kind":"import-statement","original":"./blob-sync-extension"},{"path":"packages/core/mesh/teleport-extension-object-sync/src/blob-sync.ts","kind":"import-statement","original":"./blob-sync"},{"path":"packages/core/mesh/teleport-extension-object-sync/src/blob-store.ts","kind":"import-statement","original":"./blob-store"}],"format":"esm"}},"outputs":{"packages/core/mesh/teleport-extension-object-sync/dist/lib/node/index.cjs.map":{"imports":[],"exports":[],"inputs":{},"bytes":30003},"packages/core/mesh/teleport-extension-object-sync/dist/lib/node/index.cjs":{"imports":[{"path":"@dxos/async","kind":"require-call","external":true},{"path":"@dxos/context","kind":"require-call","external":true},{"path":"@dxos/invariant","kind":"require-call","external":true},{"path":"@dxos/log","kind":"require-call","external":true},{"path":"@dxos/protocols","kind":"require-call","external":true},{"path":"@dxos/teleport","kind":"require-call","external":true},{"path":"@dxos/util","kind":"require-call","external":true},{"path":"@dxos/async","kind":"require-call","external":true},{"path":"@dxos/context","kind":"require-call","external":true},{"path":"@dxos/invariant","kind":"require-call","external":true},{"path":"@dxos/keys","kind":"require-call","external":true},{"path":"@dxos/log","kind":"require-call","external":true},{"path":"@dxos/protocols/proto/dxos/echo/blob","kind":"require-call","external":true},{"path":"@dxos/util","kind":"require-call","external":true},{"path":"node:path","kind":"require-call","external":true},{"path":"@dxos/async","kind":"require-call","external":true},{"path":"@dxos/crypto","kind":"require-call","external":true},{"path":"@dxos/invariant","kind":"require-call","external":true},{"path":"@dxos/keys","kind":"require-call","external":true},{"path":"@dxos/protocols","kind":"require-call","external":true},{"path":"@dxos/protocols/proto/dxos/echo/blob","kind":"require-call","external":true},{"path":"@dxos/util","kind":"require-call","external":true}],"exports":[],"entryPoint":"packages/core/mesh/teleport-extension-object-sync/src/index.ts","inputs":{"packages/core/mesh/teleport-extension-object-sync/src/index.ts":{"bytesInOutput":245},"packages/core/mesh/teleport-extension-object-sync/src/blob-sync-extension.ts":{"bytesInOutput":7510},"packages/core/mesh/teleport-extension-object-sync/src/blob-sync.ts":{"bytesInOutput":5354},"packages/core/mesh/teleport-extension-object-sync/src/blob-store.ts":{"bytesInOutput":6945}},"bytes":21934}}}
1
+ {"inputs":{"packages/core/mesh/teleport-extension-object-sync/src/blob-sync-extension.ts":{"bytes":25193,"imports":[{"path":"@dxos/async","kind":"import-statement","external":true},{"path":"@dxos/context","kind":"import-statement","external":true},{"path":"@dxos/invariant","kind":"import-statement","external":true},{"path":"@dxos/log","kind":"import-statement","external":true},{"path":"@dxos/protocols","kind":"import-statement","external":true},{"path":"@dxos/teleport","kind":"import-statement","external":true},{"path":"@dxos/util","kind":"import-statement","external":true}],"format":"esm"},"packages/core/mesh/teleport-extension-object-sync/src/blob-sync.ts":{"bytes":18388,"imports":[{"path":"@dxos/async","kind":"import-statement","external":true},{"path":"@dxos/context","kind":"import-statement","external":true},{"path":"@dxos/invariant","kind":"import-statement","external":true},{"path":"@dxos/keys","kind":"import-statement","external":true},{"path":"@dxos/log","kind":"import-statement","external":true},{"path":"@dxos/protocols/proto/dxos/echo/blob","kind":"import-statement","external":true},{"path":"@dxos/util","kind":"import-statement","external":true},{"path":"packages/core/mesh/teleport-extension-object-sync/src/blob-sync-extension.ts","kind":"import-statement","original":"./blob-sync-extension"}],"format":"esm"},"packages/core/mesh/teleport-extension-object-sync/src/blob-store.ts":{"bytes":22276,"imports":[{"path":"node:path","kind":"import-statement","external":true},{"path":"@dxos/async","kind":"import-statement","external":true},{"path":"@dxos/crypto","kind":"import-statement","external":true},{"path":"@dxos/invariant","kind":"import-statement","external":true},{"path":"@dxos/keys","kind":"import-statement","external":true},{"path":"@dxos/protocols","kind":"import-statement","external":true},{"path":"@dxos/protocols/proto/dxos/echo/blob","kind":"import-statement","external":true},{"path":"@dxos/util","kind":"import-statement","external":true}],"format":"esm"},"packages/core/mesh/teleport-extension-object-sync/src/index.ts":{"bytes":698,"imports":[{"path":"packages/core/mesh/teleport-extension-object-sync/src/blob-sync-extension.ts","kind":"import-statement","original":"./blob-sync-extension"},{"path":"packages/core/mesh/teleport-extension-object-sync/src/blob-sync.ts","kind":"import-statement","original":"./blob-sync"},{"path":"packages/core/mesh/teleport-extension-object-sync/src/blob-store.ts","kind":"import-statement","original":"./blob-store"}],"format":"esm"}},"outputs":{"packages/core/mesh/teleport-extension-object-sync/dist/lib/node/index.cjs.map":{"imports":[],"exports":[],"inputs":{},"bytes":30539},"packages/core/mesh/teleport-extension-object-sync/dist/lib/node/index.cjs":{"imports":[{"path":"@dxos/async","kind":"import-statement","external":true},{"path":"@dxos/context","kind":"import-statement","external":true},{"path":"@dxos/invariant","kind":"import-statement","external":true},{"path":"@dxos/log","kind":"import-statement","external":true},{"path":"@dxos/protocols","kind":"import-statement","external":true},{"path":"@dxos/teleport","kind":"import-statement","external":true},{"path":"@dxos/util","kind":"import-statement","external":true},{"path":"@dxos/async","kind":"import-statement","external":true},{"path":"@dxos/context","kind":"import-statement","external":true},{"path":"@dxos/invariant","kind":"import-statement","external":true},{"path":"@dxos/keys","kind":"import-statement","external":true},{"path":"@dxos/log","kind":"import-statement","external":true},{"path":"@dxos/protocols/proto/dxos/echo/blob","kind":"import-statement","external":true},{"path":"@dxos/util","kind":"import-statement","external":true},{"path":"node:path","kind":"import-statement","external":true},{"path":"@dxos/async","kind":"import-statement","external":true},{"path":"@dxos/crypto","kind":"import-statement","external":true},{"path":"@dxos/invariant","kind":"import-statement","external":true},{"path":"@dxos/keys","kind":"import-statement","external":true},{"path":"@dxos/protocols","kind":"import-statement","external":true},{"path":"@dxos/protocols/proto/dxos/echo/blob","kind":"import-statement","external":true},{"path":"@dxos/util","kind":"import-statement","external":true}],"exports":["BlobStore","BlobSync","BlobSyncExtension","DEFAULT_CHUNK_SIZE"],"entryPoint":"packages/core/mesh/teleport-extension-object-sync/src/index.ts","inputs":{"packages/core/mesh/teleport-extension-object-sync/src/blob-sync-extension.ts":{"bytesInOutput":7378},"packages/core/mesh/teleport-extension-object-sync/src/index.ts":{"bytesInOutput":0},"packages/core/mesh/teleport-extension-object-sync/src/blob-sync.ts":{"bytesInOutput":5405},"packages/core/mesh/teleport-extension-object-sync/src/blob-store.ts":{"bytesInOutput":6532}},"bytes":19652}}}
@@ -5,6 +5,7 @@ export type BlobSyncExtensionParams = {
5
5
  blobStore: BlobStore;
6
6
  onOpen: () => Promise<void>;
7
7
  onClose: () => Promise<void>;
8
+ onAbort: () => Promise<void>;
8
9
  onPush: (data: BlobChunk) => Promise<void>;
9
10
  };
10
11
  /**
@@ -25,6 +26,7 @@ export declare class BlobSyncExtension extends RpcExtension<ServiceBundle, Servi
25
26
  constructor(_params: BlobSyncExtensionParams);
26
27
  onOpen(context: ExtensionContext): Promise<void>;
27
28
  onClose(err?: Error | undefined): Promise<void>;
29
+ onAbort(err?: Error | undefined): Promise<void>;
28
30
  protected getHandlers(): Promise<ServiceBundle>;
29
31
  push(data: BlobChunk): Promise<void>;
30
32
  updateWantList(wantList: WantList): void;
@@ -1 +1 @@
1
- {"version":3,"file":"blob-sync-extension.d.ts","sourceRoot":"","sources":["../../../src/blob-sync-extension.ts"],"names":[],"mappings":"AAWA,OAAO,EAAE,KAAK,SAAS,EAAE,KAAK,eAAe,EAAE,KAAK,QAAQ,EAAE,MAAM,mDAAmD,CAAC;AACxH,OAAO,EAAE,KAAK,gBAAgB,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAGrE,OAAO,EAAE,KAAK,SAAS,EAAE,MAAM,cAAc,CAAC;AAE9C,MAAM,MAAM,uBAAuB,GAAG;IACpC,SAAS,EAAE,SAAS,CAAC;IACrB,MAAM,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IAC5B,OAAO,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IAC7B,MAAM,EAAE,CAAC,IAAI,EAAE,SAAS,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;CAC5C,CAAC;AAMF;;GAEG;AACH,qBAAa,iBAAkB,SAAQ,YAAY,CAAC,aAAa,EAAE,aAAa,CAAC;IAyD7E,OAAO,CAAC,QAAQ,CAAC,OAAO;IAxD1B,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAqD;IAE1E,OAAO,CAAC,mBAAmB,CAAK;IAChC,OAAO,CAAC,cAAc,CAA2B;IAEjD,OAAO,CAAC,QAAQ,CAAC,eAAe,CAY7B;IAEH,OAAO,CAAC,eAAe,CAAK;IAE5B,OAAO,CAAC,QAAQ,CAAC,OAAO,CA2BrB;IAEH;;OAEG;IACI,cAAc,EAAE,QAAQ,CAAiB;gBAG7B,OAAO,EAAE,uBAAuB;IAgBpC,MAAM,CAAC,OAAO,EAAE,gBAAgB,GAAG,OAAO,CAAC,IAAI,CAAC;IAMhD,OAAO,CAAC,GAAG,CAAC,EAAE,KAAK,GAAG,SAAS,GAAG,OAAO,CAAC,IAAI,CAAC;cAO9C,WAAW,IAAI,OAAO,CAAC,aAAa,CAAC;IAiB/C,IAAI,CAAC,IAAI,EAAE,SAAS;IAQ1B,cAAc,CAAC,QAAQ,EAAE,QAAQ;IAQjC,gBAAgB;YAOF,eAAe;CAuD9B;AAED,KAAK,aAAa,GAAG;IACnB,eAAe,EAAE,eAAe,CAAC;CAClC,CAAC"}
1
+ {"version":3,"file":"blob-sync-extension.d.ts","sourceRoot":"","sources":["../../../src/blob-sync-extension.ts"],"names":[],"mappings":"AAWA,OAAO,EAAE,KAAK,SAAS,EAAE,KAAK,eAAe,EAAE,KAAK,QAAQ,EAAE,MAAM,mDAAmD,CAAC;AACxH,OAAO,EAAE,KAAK,gBAAgB,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAGrE,OAAO,EAAE,KAAK,SAAS,EAAE,MAAM,cAAc,CAAC;AAE9C,MAAM,MAAM,uBAAuB,GAAG;IACpC,SAAS,EAAE,SAAS,CAAC;IACrB,MAAM,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IAC5B,OAAO,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IAC7B,OAAO,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IAC7B,MAAM,EAAE,CAAC,IAAI,EAAE,SAAS,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;CAC5C,CAAC;AAMF;;GAEG;AACH,qBAAa,iBAAkB,SAAQ,YAAY,CAAC,aAAa,EAAE,aAAa,CAAC;IAyD7E,OAAO,CAAC,QAAQ,CAAC,OAAO;IAxD1B,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAqD;IAE1E,OAAO,CAAC,mBAAmB,CAAK;IAChC,OAAO,CAAC,cAAc,CAA2B;IAEjD,OAAO,CAAC,QAAQ,CAAC,eAAe,CAY7B;IAEH,OAAO,CAAC,eAAe,CAAK;IAE5B,OAAO,CAAC,QAAQ,CAAC,OAAO,CA2BrB;IAEH;;OAEG;IACI,cAAc,EAAE,QAAQ,CAAiB;gBAG7B,OAAO,EAAE,uBAAuB;IAgBpC,MAAM,CAAC,OAAO,EAAE,gBAAgB,GAAG,OAAO,CAAC,IAAI,CAAC;IAMhD,OAAO,CAAC,GAAG,CAAC,EAAE,KAAK,GAAG,SAAS,GAAG,OAAO,CAAC,IAAI,CAAC;IAO/C,OAAO,CAAC,GAAG,CAAC,EAAE,KAAK,GAAG,SAAS,GAAG,OAAO,CAAC,IAAI,CAAC;cAO9C,WAAW,IAAI,OAAO,CAAC,aAAa,CAAC;IAiB/C,IAAI,CAAC,IAAI,EAAE,SAAS;IAQ1B,cAAc,CAAC,QAAQ,EAAE,QAAQ;IAQjC,gBAAgB;YAOF,eAAe;CAuD9B;AAED,KAAK,aAAa,GAAG;IACnB,eAAe,EAAE,eAAe,CAAC;CAClC,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"blob-sync.d.ts","sourceRoot":"","sources":["../../../src/blob-sync.ts"],"names":[],"mappings":"AAKA,OAAO,EAAqB,OAAO,EAAE,MAAM,eAAe,CAAC;AAQ3D,OAAO,EAAE,KAAK,SAAS,EAAE,MAAM,cAAc,CAAC;AAC9C,OAAO,EAAE,iBAAiB,EAAE,MAAM,uBAAuB,CAAC;AAE1D,MAAM,MAAM,cAAc,GAAG;IAC3B,SAAS,EAAE,SAAS,CAAC;CACtB,CAAC;AASF,qBACa,QAAQ;IAUP,OAAO,CAAC,QAAQ,CAAC,OAAO;IATpC,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAiB;IACtC,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAc;IAEpC,OAAO,CAAC,QAAQ,CAAC,iBAAiB,CAEhC;IAEF,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAgC;gBAE/B,OAAO,EAAE,cAAc;IAE9C,IAAI;IAEJ,KAAK;IAIX;;;;OAIG;IACG,QAAQ,CAAC,GAAG,EAAE,OAAO,EAAE,EAAE,EAAE,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC;IAiD3D,eAAe;IAiCf;;OAEG;IACG,eAAe,CAAC,GAAG,EAAE,UAAU;IAIrC,OAAO,CAAC,YAAY;IAMpB,OAAO,CAAC,iBAAiB;IAMzB,OAAO,CAAC,yBAAyB;CAKlC"}
1
+ {"version":3,"file":"blob-sync.d.ts","sourceRoot":"","sources":["../../../src/blob-sync.ts"],"names":[],"mappings":"AAKA,OAAO,EAAqB,OAAO,EAAE,MAAM,eAAe,CAAC;AAQ3D,OAAO,EAAE,KAAK,SAAS,EAAE,MAAM,cAAc,CAAC;AAC9C,OAAO,EAAE,iBAAiB,EAAE,MAAM,uBAAuB,CAAC;AAE1D,MAAM,MAAM,cAAc,GAAG;IAC3B,SAAS,EAAE,SAAS,CAAC;CACtB,CAAC;AASF,qBACa,QAAQ;IAUP,OAAO,CAAC,QAAQ,CAAC,OAAO;IATpC,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAiB;IACtC,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAc;IAEpC,OAAO,CAAC,QAAQ,CAAC,iBAAiB,CAEhC;IAEF,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAgC;gBAE/B,OAAO,EAAE,cAAc;IAE9C,IAAI;IAEJ,KAAK;IAIX;;;;OAIG;IACG,QAAQ,CAAC,GAAG,EAAE,OAAO,EAAE,EAAE,EAAE,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC;IAiD3D,eAAe;IAqCf;;OAEG;IACG,eAAe,CAAC,GAAG,EAAE,UAAU;IAIrC,OAAO,CAAC,YAAY;IAMpB,OAAO,CAAC,iBAAiB;IAMzB,OAAO,CAAC,yBAAyB;CAKlC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dxos/teleport-extension-object-sync",
3
- "version": "0.3.8-next.f4e0086",
3
+ "version": "0.3.8",
4
4
  "description": "Teleport extension to synchronize opaque data objects.",
5
5
  "homepage": "https://dxos.org",
6
6
  "bugs": "https://github.com/dxos/dxos/issues",
@@ -16,19 +16,19 @@
16
16
  "src"
17
17
  ],
18
18
  "dependencies": {
19
- "@dxos/async": "0.3.8-next.f4e0086",
20
- "@dxos/context": "0.3.8-next.f4e0086",
21
- "@dxos/debug": "0.3.8-next.f4e0086",
22
- "@dxos/keys": "0.3.8-next.f4e0086",
23
- "@dxos/crypto": "0.3.8-next.f4e0086",
24
- "@dxos/invariant": "0.3.8-next.f4e0086",
25
- "@dxos/log": "0.3.8-next.f4e0086",
26
- "@dxos/protocols": "0.3.8-next.f4e0086",
27
- "@dxos/rpc": "0.3.8-next.f4e0086",
28
- "@dxos/random-access-storage": "0.3.8-next.f4e0086",
29
- "@dxos/node-std": "0.3.8-next.f4e0086",
30
- "@dxos/teleport": "0.3.8-next.f4e0086",
31
- "@dxos/util": "0.3.8-next.f4e0086"
19
+ "@dxos/async": "0.3.8",
20
+ "@dxos/crypto": "0.3.8",
21
+ "@dxos/context": "0.3.8",
22
+ "@dxos/keys": "0.3.8",
23
+ "@dxos/debug": "0.3.8",
24
+ "@dxos/log": "0.3.8",
25
+ "@dxos/invariant": "0.3.8",
26
+ "@dxos/node-std": "0.3.8",
27
+ "@dxos/protocols": "0.3.8",
28
+ "@dxos/rpc": "0.3.8",
29
+ "@dxos/random-access-storage": "0.3.8",
30
+ "@dxos/teleport": "0.3.8",
31
+ "@dxos/util": "0.3.8"
32
32
  },
33
33
  "devDependencies": {
34
34
  "typescript": "^5.2.2"
@@ -19,6 +19,7 @@ export type BlobSyncExtensionParams = {
19
19
  blobStore: BlobStore;
20
20
  onOpen: () => Promise<void>;
21
21
  onClose: () => Promise<void>;
22
+ onAbort: () => Promise<void>;
22
23
  onPush: (data: BlobChunk) => Promise<void>;
23
24
  };
24
25
 
@@ -115,6 +116,13 @@ export class BlobSyncExtension extends RpcExtension<ServiceBundle, ServiceBundle
115
116
  await super.onClose(err);
116
117
  }
117
118
 
119
+ override async onAbort(err?: Error | undefined): Promise<void> {
120
+ log('abort');
121
+ await this._ctx.dispose();
122
+ await this._params.onAbort();
123
+ await super.onAbort(err);
124
+ }
125
+
118
126
  protected async getHandlers(): Promise<ServiceBundle> {
119
127
  return {
120
128
  BlobSyncService: {
package/src/blob-sync.ts CHANGED
@@ -110,6 +110,10 @@ export class BlobSync {
110
110
  log('extension closed');
111
111
  this._extensions.delete(extension);
112
112
  },
113
+ onAbort: async () => {
114
+ log('extension aborted');
115
+ this._extensions.delete(extension);
116
+ },
113
117
  onPush: async (blobChunk) => {
114
118
  if (!this._downloadRequests.has(blobChunk.id)) {
115
119
  return;