@dxos/teleport-extension-replicator 0.8.3 → 0.8.4-main.03d5cd7b56

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.
@@ -1,7 +1,7 @@
1
1
  import "@dxos/node-std/globals";
2
2
 
3
- // packages/core/mesh/teleport-extension-replicator/src/replicator-extension.ts
4
- import { asyncTimeout, DeferredTask, synchronized } from "@dxos/async";
3
+ // src/replicator-extension.ts
4
+ import { DeferredTask, asyncTimeout, synchronized } from "@dxos/async";
5
5
  import { Context } from "@dxos/context";
6
6
  import { failUndefined } from "@dxos/debug";
7
7
  import { invariant } from "@dxos/invariant";
@@ -11,49 +11,46 @@ import { RpcClosedError, TimeoutError } from "@dxos/protocols";
11
11
  import { schema } from "@dxos/protocols/proto";
12
12
  import { createProtoRpcPeer } from "@dxos/rpc";
13
13
  import { ComplexMap } from "@dxos/util";
14
+ var __dxlog_file = "/__w/dxos/dxos/packages/core/mesh/teleport-extension-replicator/src/replicator-extension.ts";
14
15
  function _ts_decorate(decorators, target, key, desc) {
15
16
  var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
16
17
  if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
17
18
  else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
18
19
  return c > 3 && r && Object.defineProperty(target, key, r), r;
19
20
  }
20
- var __dxlog_file = "/home/runner/work/dxos/dxos/packages/core/mesh/teleport-extension-replicator/src/replicator-extension.ts";
21
21
  var ReplicatorExtension = class {
22
- constructor() {
23
- this._ctx = new Context({
24
- onError: (err) => {
25
- this._extensionContext?.close(err);
22
+ _ctx = new Context({
23
+ onError: (err) => {
24
+ this._extensionContext?.close(err);
25
+ }
26
+ }, { "~LogMeta": "~LogMeta", F: __dxlog_file, L: 23 });
27
+ _feeds = new ComplexMap(PublicKey.hash);
28
+ _streams = new ComplexMap(PublicKey.hash);
29
+ _rpc;
30
+ _extensionContext;
31
+ _options = {
32
+ upload: false
33
+ };
34
+ _updateTask = new DeferredTask(this._ctx, async () => {
35
+ try {
36
+ if (this._extensionContext.initiator === false) {
37
+ await this._rpc.rpc.ReplicatorService.updateFeeds({
38
+ feeds: Array.from(this._feeds.values()).map((feed) => ({
39
+ feedKey: feed.key,
40
+ download: true,
41
+ upload: this._options.upload
42
+ }))
43
+ });
44
+ } else if (this._extensionContext.initiator === true) {
45
+ await this._reevaluateFeeds();
26
46
  }
27
- }, {
28
- F: __dxlog_file,
29
- L: 30
30
- });
31
- this._feeds = new ComplexMap(PublicKey.hash);
32
- this._streams = new ComplexMap(PublicKey.hash);
33
- this._options = {
34
- upload: false
35
- };
36
- this._updateTask = new DeferredTask(this._ctx, async () => {
37
- try {
38
- if (this._extensionContext.initiator === false) {
39
- await this._rpc.rpc.ReplicatorService.updateFeeds({
40
- feeds: Array.from(this._feeds.values()).map((feed) => ({
41
- feedKey: feed.key,
42
- download: true,
43
- upload: this._options.upload
44
- }))
45
- });
46
- } else if (this._extensionContext.initiator === true) {
47
- await this._reevaluateFeeds();
48
- }
49
- } catch (err) {
50
- if (err instanceof RpcClosedError) {
51
- return;
52
- }
53
- throw err;
47
+ } catch (err) {
48
+ if (err instanceof RpcClosedError) {
49
+ return;
54
50
  }
55
- });
56
- }
51
+ throw err;
52
+ }
53
+ });
57
54
  get extensionInfo() {
58
55
  return {
59
56
  initiator: this._extensionContext?.initiator,
@@ -66,12 +63,7 @@ var ReplicatorExtension = class {
66
63
  this._options = options;
67
64
  log("setOptions", {
68
65
  options
69
- }, {
70
- F: __dxlog_file,
71
- L: 79,
72
- S: this,
73
- C: (f, a) => f(...a)
74
- });
66
+ }, { "~LogMeta": "~LogMeta", F: __dxlog_file, L: 65, S: this });
75
67
  if (this._extensionContext) {
76
68
  this._updateTask.schedule();
77
69
  }
@@ -81,24 +73,14 @@ var ReplicatorExtension = class {
81
73
  this._feeds.set(feed.key, feed);
82
74
  log("addFeed", {
83
75
  feedKey: feed.key
84
- }, {
85
- F: __dxlog_file,
86
- L: 88,
87
- S: this,
88
- C: (f, a) => f(...a)
89
- });
76
+ }, { "~LogMeta": "~LogMeta", F: __dxlog_file, L: 75, S: this });
90
77
  if (this._extensionContext) {
91
78
  this._updateTask.schedule();
92
79
  }
93
80
  }
94
81
  async onOpen(context) {
95
82
  this._extensionContext = context;
96
- log("open", void 0, {
97
- F: __dxlog_file,
98
- L: 96,
99
- S: this,
100
- C: (f, a) => f(...a)
101
- });
83
+ log("open", void 0, { "~LogMeta": "~LogMeta", F: __dxlog_file, L: 84, S: this });
102
84
  this._rpc = createProtoRpcPeer({
103
85
  requested: {
104
86
  ReplicatorService: schema.getService("dxos.mesh.teleport.replicator.ReplicatorService")
@@ -111,41 +93,15 @@ var ReplicatorExtension = class {
111
93
  updateFeeds: async ({ feeds }) => {
112
94
  log("received feed info", {
113
95
  feeds
114
- }, {
115
- F: __dxlog_file,
116
- L: 108,
117
- S: this,
118
- C: (f, a) => f(...a)
119
- });
120
- invariant(this._extensionContext.initiator === true, "Invalid call", {
121
- F: __dxlog_file,
122
- L: 109,
123
- S: this,
124
- A: [
125
- "this._extensionContext!.initiator === true",
126
- "'Invalid call'"
127
- ]
128
- });
96
+ }, { "~LogMeta": "~LogMeta", F: __dxlog_file, L: 95, S: this });
97
+ invariant(this._extensionContext.initiator === true, "Invalid call", { "~LogMeta": "~LogMeta", F: __dxlog_file, L: 98, S: this, A: ["this._extensionContext.initiator === true", "'Invalid call'"] });
129
98
  this._updateTask.schedule();
130
99
  },
131
100
  startReplication: async ({ info }) => {
132
101
  log("starting replication...", {
133
102
  info
134
- }, {
135
- F: __dxlog_file,
136
- L: 113,
137
- S: this,
138
- C: (f, a) => f(...a)
139
- });
140
- invariant(this._extensionContext.initiator === false, "Invalid call", {
141
- F: __dxlog_file,
142
- L: 114,
143
- S: this,
144
- A: [
145
- "this._extensionContext!.initiator === false",
146
- "'Invalid call'"
147
- ]
148
- });
103
+ }, { "~LogMeta": "~LogMeta", F: __dxlog_file, L: 102, S: this });
104
+ invariant(this._extensionContext.initiator === false, "Invalid call", { "~LogMeta": "~LogMeta", F: __dxlog_file, L: 105, S: this, A: ["this._extensionContext.initiator === false", "'Invalid call'"] });
149
105
  const streamTag = await this._acceptReplication(info);
150
106
  return {
151
107
  streamTag
@@ -154,21 +110,8 @@ var ReplicatorExtension = class {
154
110
  stopReplication: async ({ info }) => {
155
111
  log("stopping replication...", {
156
112
  info
157
- }, {
158
- F: __dxlog_file,
159
- L: 122,
160
- S: this,
161
- C: (f, a) => f(...a)
162
- });
163
- invariant(this._extensionContext.initiator === false, "Invalid call", {
164
- F: __dxlog_file,
165
- L: 124,
166
- S: this,
167
- A: [
168
- "this._extensionContext!.initiator === false",
169
- "'Invalid call'"
170
- ]
171
- });
113
+ }, { "~LogMeta": "~LogMeta", F: __dxlog_file, L: 112, S: this });
114
+ invariant(this._extensionContext.initiator === false, "Invalid call", { "~LogMeta": "~LogMeta", F: __dxlog_file, L: 116, S: this, A: ["this._extensionContext.initiator === false", "'Invalid call'"] });
172
115
  await this._stopReplication(info.feedKey);
173
116
  }
174
117
  }
@@ -184,12 +127,7 @@ var ReplicatorExtension = class {
184
127
  async onClose(err) {
185
128
  log("close", {
186
129
  err
187
- }, {
188
- F: __dxlog_file,
189
- L: 141,
190
- S: this,
191
- C: (f, a) => f(...a)
192
- });
130
+ }, { "~LogMeta": "~LogMeta", F: __dxlog_file, L: 130, S: this });
193
131
  await this._ctx.dispose();
194
132
  await this._rpc?.close();
195
133
  for (const feedKey of this._streams.keys()) {
@@ -199,12 +137,7 @@ var ReplicatorExtension = class {
199
137
  async onAbort(err) {
200
138
  log("abort", {
201
139
  err
202
- }, {
203
- F: __dxlog_file,
204
- L: 150,
205
- S: this,
206
- C: (f, a) => f(...a)
207
- });
140
+ }, { "~LogMeta": "~LogMeta", F: __dxlog_file, L: 140, S: this });
208
141
  await this._ctx.dispose();
209
142
  await this._rpc?.abort();
210
143
  for (const feedKey of this._streams.keys()) {
@@ -212,12 +145,7 @@ var ReplicatorExtension = class {
212
145
  }
213
146
  }
214
147
  async _reevaluateFeeds() {
215
- log("_reevaluateFeeds", void 0, {
216
- F: __dxlog_file,
217
- L: 161,
218
- S: this,
219
- C: (f, a) => f(...a)
220
- });
148
+ log("_reevaluateFeeds", void 0, { "~LogMeta": "~LogMeta", F: __dxlog_file, L: 150, S: this });
221
149
  for (const feedKey of this._feeds.keys()) {
222
150
  if (this._ctx.disposed) {
223
151
  return;
@@ -226,12 +154,7 @@ var ReplicatorExtension = class {
226
154
  try {
227
155
  await asyncTimeout(this._stopReplication(feedKey), 1e3);
228
156
  } catch (err) {
229
- log.catch(err, void 0, {
230
- F: __dxlog_file,
231
- L: 170,
232
- S: this,
233
- C: (f, a) => f(...a)
234
- });
157
+ log.catch(err, void 0, { "~LogMeta": "~LogMeta", F: __dxlog_file, L: 159, S: this });
235
158
  }
236
159
  }
237
160
  if (this._ctx.disposed) {
@@ -252,30 +175,9 @@ var ReplicatorExtension = class {
252
175
  async _initiateReplication(feedInfo) {
253
176
  log("initiating replication", {
254
177
  feedInfo
255
- }, {
256
- F: __dxlog_file,
257
- L: 191,
258
- S: this,
259
- C: (f, a) => f(...a)
260
- });
261
- invariant(this._extensionContext.initiator === true, "Invalid call", {
262
- F: __dxlog_file,
263
- L: 192,
264
- S: this,
265
- A: [
266
- "this._extensionContext!.initiator === true",
267
- "'Invalid call'"
268
- ]
269
- });
270
- invariant(!this._streams.has(feedInfo.feedKey), `Replication already in progress for feed: ${feedInfo.feedKey}`, {
271
- F: __dxlog_file,
272
- L: 193,
273
- S: this,
274
- A: [
275
- "!this._streams.has(feedInfo.feedKey)",
276
- "`Replication already in progress for feed: ${feedInfo.feedKey}`"
277
- ]
278
- });
178
+ }, { "~LogMeta": "~LogMeta", F: __dxlog_file, L: 177, S: this });
179
+ invariant(this._extensionContext.initiator === true, "Invalid call", { "~LogMeta": "~LogMeta", F: __dxlog_file, L: 180, S: this, A: ["this._extensionContext.initiator === true", "'Invalid call'"] });
180
+ invariant(!this._streams.has(feedInfo.feedKey), `Replication already in progress for feed: ${feedInfo.feedKey}`, { "~LogMeta": "~LogMeta", F: __dxlog_file, L: 181, S: this, A: ["!this._streams.has(feedInfo.feedKey)", "`Replication already in progress for feed: ${feedInfo.feedKey}`"] });
279
181
  const { streamTag } = await this._rpc.rpc.ReplicatorService.startReplication({
280
182
  info: feedInfo
281
183
  });
@@ -289,15 +191,7 @@ var ReplicatorExtension = class {
289
191
  * @returns A stream tag for the replication stream or `undefined` if we don't want to replicate.
290
192
  */
291
193
  async _acceptReplication(feedInfo) {
292
- invariant(this._extensionContext.initiator === false, "Invalid call", {
293
- F: __dxlog_file,
294
- L: 208,
295
- S: this,
296
- A: [
297
- "this._extensionContext!.initiator === false",
298
- "'Invalid call'"
299
- ]
300
- });
194
+ invariant(this._extensionContext.initiator === false, "Invalid call", { "~LogMeta": "~LogMeta", F: __dxlog_file, L: 194, S: this, A: ["this._extensionContext.initiator === false", "'Invalid call'"] });
301
195
  if (!this._feeds.has(feedInfo.feedKey) || this._streams.has(feedInfo.feedKey)) {
302
196
  return void 0;
303
197
  }
@@ -309,21 +203,8 @@ var ReplicatorExtension = class {
309
203
  log("replicate", {
310
204
  info,
311
205
  streamTag
312
- }, {
313
- F: __dxlog_file,
314
- L: 220,
315
- S: this,
316
- C: (f, a) => f(...a)
317
- });
318
- invariant(!this._streams.has(info.feedKey), `Replication already in progress for feed: ${info.feedKey}`, {
319
- F: __dxlog_file,
320
- L: 221,
321
- S: this,
322
- A: [
323
- "!this._streams.has(info.feedKey)",
324
- "`Replication already in progress for feed: ${info.feedKey}`"
325
- ]
326
- });
206
+ }, { "~LogMeta": "~LogMeta", F: __dxlog_file, L: 203, S: this });
207
+ invariant(!this._streams.has(info.feedKey), `Replication already in progress for feed: ${info.feedKey}`, { "~LogMeta": "~LogMeta", F: __dxlog_file, L: 207, S: this, A: ["!this._streams.has(info.feedKey)", "`Replication already in progress for feed: ${info.feedKey}`"] });
327
208
  const feed = this._feeds.get(info.feedKey) ?? failUndefined();
328
209
  const networkStream = await this._extensionContext.createStream(streamTag, {
329
210
  contentType: "application/x-hypercore"
@@ -342,47 +223,27 @@ var ReplicatorExtension = class {
342
223
  log.info("replication stream timeout", {
343
224
  err,
344
225
  info
345
- }, {
346
- F: __dxlog_file,
347
- L: 257,
348
- S: this,
349
- C: (f, a) => f(...a)
350
- });
226
+ }, { "~LogMeta": "~LogMeta", F: __dxlog_file, L: 239, S: this });
351
227
  return;
352
228
  }
353
229
  if (err?.message === "Writable stream closed prematurely" || err?.message === "Cannot call write after a stream was destroyed") {
354
230
  log("replication stream closed", {
355
231
  err,
356
232
  info
357
- }, {
358
- F: __dxlog_file,
359
- L: 265,
360
- S: this,
361
- C: (f, a) => f(...a)
362
- });
233
+ }, { "~LogMeta": "~LogMeta", F: __dxlog_file, L: 247, S: this });
363
234
  return;
364
235
  }
365
236
  if (replicationStreamErrors === 0) {
366
237
  log.info("replication stream error", {
367
238
  err,
368
239
  info
369
- }, {
370
- F: __dxlog_file,
371
- L: 271,
372
- S: this,
373
- C: (f, a) => f(...a)
374
- });
240
+ }, { "~LogMeta": "~LogMeta", F: __dxlog_file, L: 255, S: this });
375
241
  } else {
376
242
  log.info("replication stream error", {
377
243
  err,
378
244
  feedKey: info.feedKey,
379
245
  count: replicationStreamErrors
380
- }, {
381
- F: __dxlog_file,
382
- L: 273,
383
- S: this,
384
- C: (f, a) => f(...a)
385
- });
246
+ }, { "~LogMeta": "~LogMeta", F: __dxlog_file, L: 260, S: this });
386
247
  }
387
248
  replicationStreamErrors++;
388
249
  });
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../src/replicator-extension.ts"],
4
- "sourcesContent": ["//\n// Copyright 2022 DXOS.org\n//\n\nimport type { ProtocolStream } from 'hypercore-protocol';\nimport { type Duplex } from 'node:stream';\n\nimport { asyncTimeout, DeferredTask, synchronized } from '@dxos/async';\nimport { Context } from '@dxos/context';\nimport { failUndefined } from '@dxos/debug';\nimport { type FeedWrapper } from '@dxos/feed-store';\nimport { invariant } from '@dxos/invariant';\nimport { PublicKey } from '@dxos/keys';\nimport { log, logInfo } from '@dxos/log';\nimport { RpcClosedError, TimeoutError } from '@dxos/protocols';\nimport { schema } from '@dxos/protocols/proto';\nimport { type FeedInfo, type ReplicatorService } from '@dxos/protocols/proto/dxos/mesh/teleport/replicator';\nimport { createProtoRpcPeer, type ProtoRpcPeer } from '@dxos/rpc';\nimport { type ExtensionContext, type TeleportExtension } from '@dxos/teleport';\nimport { ComplexMap } from '@dxos/util';\n\nexport type ReplicationOptions = {\n upload: boolean;\n};\n\n/**\n * Manages replication between a set of feeds for a single teleport session.\n */\nexport class ReplicatorExtension implements TeleportExtension {\n private readonly _ctx = new Context({\n onError: (err) => {\n this._extensionContext?.close(err);\n },\n });\n\n private readonly _feeds = new ComplexMap<PublicKey, FeedWrapper<any>>(PublicKey.hash);\n private readonly _streams = new ComplexMap<PublicKey, ActiveStream>(PublicKey.hash);\n\n private _rpc?: ProtoRpcPeer<ServiceBundle>;\n private _extensionContext?: ExtensionContext;\n\n private _options: ReplicationOptions = {\n upload: false,\n };\n\n private readonly _updateTask = new DeferredTask(this._ctx, async () => {\n try {\n if (this._extensionContext!.initiator === false) {\n await this._rpc!.rpc.ReplicatorService.updateFeeds({\n feeds: Array.from(this._feeds.values()).map((feed) => ({\n feedKey: feed.key,\n download: true,\n upload: this._options.upload,\n })),\n });\n } else if (this._extensionContext!.initiator === true) {\n await this._reevaluateFeeds();\n }\n } catch (err) {\n if (err instanceof RpcClosedError) {\n return; // Some RPC requests might be pending while closing.\n }\n throw err;\n }\n });\n\n @logInfo\n private get extensionInfo() {\n return {\n initiator: this._extensionContext?.initiator,\n localPeerId: this._extensionContext?.localPeerId,\n remotePeerId: this._extensionContext?.remotePeerId,\n feeds: Array.from(this._feeds.keys()),\n };\n }\n\n setOptions(options: ReplicationOptions): this {\n this._options = options;\n log('setOptions', { options });\n if (this._extensionContext) {\n this._updateTask.schedule();\n }\n return this;\n }\n\n addFeed(feed: FeedWrapper<any>): void {\n this._feeds.set(feed.key, feed);\n log('addFeed', { feedKey: feed.key });\n if (this._extensionContext) {\n this._updateTask.schedule();\n }\n }\n\n async onOpen(context: ExtensionContext): Promise<void> {\n this._extensionContext = context;\n log('open');\n\n this._rpc = createProtoRpcPeer<ServiceBundle, ServiceBundle>({\n requested: {\n ReplicatorService: schema.getService('dxos.mesh.teleport.replicator.ReplicatorService'),\n },\n exposed: {\n ReplicatorService: schema.getService('dxos.mesh.teleport.replicator.ReplicatorService'),\n },\n handlers: {\n ReplicatorService: {\n updateFeeds: async ({ feeds }) => {\n log('received feed info', { feeds });\n invariant(this._extensionContext!.initiator === true, 'Invalid call');\n this._updateTask.schedule();\n },\n startReplication: async ({ info }) => {\n log('starting replication...', { info });\n invariant(this._extensionContext!.initiator === false, 'Invalid call');\n\n const streamTag = await this._acceptReplication(info);\n return {\n streamTag,\n };\n },\n stopReplication: async ({ info }) => {\n log('stopping replication...', { info });\n // TODO(dmaretskyi): Make sure any peer can stop replication.\n invariant(this._extensionContext!.initiator === false, 'Invalid call');\n\n await this._stopReplication(info.feedKey);\n },\n },\n },\n port: await context.createPort('rpc', {\n contentType: 'application/x-protobuf; messageType=\"dxos.rpc.Message\"',\n }),\n timeout: 10_000,\n });\n await this._rpc.open();\n\n this._updateTask.schedule();\n }\n\n async onClose(err?: Error | undefined): Promise<void> {\n log('close', { err });\n await this._ctx.dispose();\n await this._rpc?.close();\n for (const feedKey of this._streams.keys()) {\n await this._stopReplication(feedKey);\n }\n }\n\n async onAbort(err?: Error | undefined): Promise<void> {\n log('abort', { err });\n\n await this._ctx.dispose();\n await this._rpc?.abort();\n for (const feedKey of this._streams.keys()) {\n await this._stopReplication(feedKey);\n }\n }\n\n @synchronized\n private async _reevaluateFeeds(): Promise<void> {\n log('_reevaluateFeeds');\n for (const feedKey of this._feeds.keys()) {\n if (this._ctx.disposed) {\n return;\n }\n if (this._streams.has(feedKey) && this._options.upload !== this._streams.get(feedKey)?.info.upload) {\n try {\n await asyncTimeout(this._stopReplication(feedKey), 1000);\n } catch (err) {\n log.catch(err);\n }\n }\n\n if (this._ctx.disposed) {\n return;\n }\n if (!this._streams.has(feedKey)) {\n await this._initiateReplication({\n feedKey,\n download: true,\n upload: this._options.upload,\n });\n }\n }\n }\n\n /**\n * Try to initiate feed replication.\n */\n private async _initiateReplication(feedInfo: FeedInfo): Promise<void> {\n log('initiating replication', { feedInfo });\n invariant(this._extensionContext!.initiator === true, 'Invalid call');\n invariant(!this._streams.has(feedInfo.feedKey), `Replication already in progress for feed: ${feedInfo.feedKey}`);\n const { streamTag } = await this._rpc!.rpc.ReplicatorService.startReplication({ info: feedInfo });\n if (!streamTag) {\n return;\n }\n\n await this._replicateFeed(feedInfo, streamTag);\n }\n\n /**\n * Respond to a remote request to replicate a feed.\n * @returns A stream tag for the replication stream or `undefined` if we don't want to replicate.\n */\n @synchronized\n private async _acceptReplication(feedInfo: FeedInfo): Promise<string | undefined> {\n invariant(this._extensionContext!.initiator === false, 'Invalid call');\n\n if (!this._feeds.has(feedInfo.feedKey) || this._streams.has(feedInfo.feedKey)) {\n return undefined; // We don't have the feed or we are already replicating it.\n }\n\n const tag = `feed-${feedInfo.feedKey.toHex()}-${PublicKey.random().toHex().slice(0, 8)}`; // Generate a unique tag for the stream.\n await this._replicateFeed(feedInfo, tag);\n return tag;\n }\n\n private async _replicateFeed(info: FeedInfo, streamTag: string): Promise<void> {\n log('replicate', { info, streamTag });\n invariant(!this._streams.has(info.feedKey), `Replication already in progress for feed: ${info.feedKey}`);\n\n const feed = this._feeds.get(info.feedKey) ?? failUndefined();\n const networkStream = await this._extensionContext!.createStream(streamTag, {\n contentType: 'application/x-hypercore',\n });\n let replicationStreamErrors = 0;\n\n // https://github.com/holepunchto/hypercore/tree/v9.12.0#var-stream--feedreplicateisinitiator-options\n const replicationStream = feed.replicate(true, {\n live: true,\n upload: info.upload,\n download: info.download,\n noise: false,\n encrypted: false,\n maxRequests: 1024,\n });\n\n // Left for testing.\n // const debug = true;\n // if (debug) {\n // feed.on('sync', () => {\n // log.info('sync', { key: feed.key, length: feed.length });\n // });\n // feed.on('download', (index: number, data: any) => {\n // log.info('download', {\n // key: feed.key,\n // index,\n // length: feed.length,\n // data: data.length,\n // });\n // });\n // }\n\n replicationStream.on('error', (err) => {\n if (err instanceof TimeoutError) {\n log.info('replication stream timeout', { err, info });\n return;\n }\n // TODO(nf): use sentinel errors\n if (\n err?.message === 'Writable stream closed prematurely' ||\n err?.message === 'Cannot call write after a stream was destroyed'\n ) {\n log('replication stream closed', { err, info });\n return;\n }\n\n // TODO(nf): WARN on first error? log full info on some subsequent errors?\n if (replicationStreamErrors === 0) {\n log.info('replication stream error', { err, info });\n } else {\n log.info('replication stream error', { err, feedKey: info.feedKey, count: replicationStreamErrors });\n }\n replicationStreamErrors++;\n });\n\n this._streams.set(info.feedKey, {\n streamTag,\n networkStream,\n replicationStream,\n info,\n });\n\n networkStream.pipe(replicationStream as any).pipe(networkStream);\n }\n\n private async _stopReplication(feedKey: PublicKey): Promise<void> {\n const stream = this._streams.get(feedKey);\n if (!stream) {\n return;\n }\n\n stream.networkStream.destroy();\n this._streams.delete(feedKey);\n }\n}\n\ntype ServiceBundle = {\n ReplicatorService: ReplicatorService;\n};\n\ntype ActiveStream = {\n streamTag: string;\n networkStream: Duplex;\n replicationStream: ProtocolStream;\n info: FeedInfo;\n};\n"],
5
- "mappings": "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",
6
- "names": ["asyncTimeout", "DeferredTask", "synchronized", "Context", "failUndefined", "invariant", "PublicKey", "log", "logInfo", "RpcClosedError", "TimeoutError", "schema", "createProtoRpcPeer", "ComplexMap", "ReplicatorExtension", "_ctx", "onError", "err", "_extensionContext", "close", "_feeds", "hash", "_streams", "_options", "upload", "_updateTask", "initiator", "_rpc", "rpc", "ReplicatorService", "updateFeeds", "feeds", "Array", "from", "values", "map", "feed", "feedKey", "key", "download", "_reevaluateFeeds", "extensionInfo", "localPeerId", "remotePeerId", "keys", "setOptions", "options", "schedule", "addFeed", "set", "onOpen", "context", "requested", "getService", "exposed", "handlers", "startReplication", "info", "streamTag", "_acceptReplication", "stopReplication", "_stopReplication", "port", "createPort", "contentType", "timeout", "open", "onClose", "dispose", "onAbort", "abort", "disposed", "has", "get", "catch", "_initiateReplication", "feedInfo", "_replicateFeed", "undefined", "tag", "toHex", "random", "slice", "networkStream", "createStream", "replicationStreamErrors", "replicationStream", "replicate", "live", "noise", "encrypted", "maxRequests", "on", "message", "count", "pipe", "stream", "destroy", "delete"]
4
+ "sourcesContent": ["//\n// Copyright 2022 DXOS.org\n//\n\nimport type { ProtocolStream } from 'hypercore-protocol';\nimport { type Duplex } from 'node:stream';\n\nimport { DeferredTask, asyncTimeout, synchronized } from '@dxos/async';\nimport { Context } from '@dxos/context';\nimport { failUndefined } from '@dxos/debug';\nimport { type FeedWrapper } from '@dxos/feed-store';\nimport { invariant } from '@dxos/invariant';\nimport { PublicKey } from '@dxos/keys';\nimport { log, logInfo } from '@dxos/log';\nimport { RpcClosedError, TimeoutError } from '@dxos/protocols';\nimport { schema } from '@dxos/protocols/proto';\nimport { type FeedInfo, type ReplicatorService } from '@dxos/protocols/proto/dxos/mesh/teleport/replicator';\nimport { type ProtoRpcPeer, createProtoRpcPeer } from '@dxos/rpc';\nimport { type ExtensionContext, type TeleportExtension } from '@dxos/teleport';\nimport { ComplexMap } from '@dxos/util';\n\nexport type ReplicationOptions = {\n upload: boolean;\n};\n\n/**\n * Manages replication between a set of feeds for a single teleport session.\n */\nexport class ReplicatorExtension implements TeleportExtension {\n private readonly _ctx = new Context({\n onError: (err) => {\n this._extensionContext?.close(err);\n },\n });\n\n private readonly _feeds = new ComplexMap<PublicKey, FeedWrapper<any>>(PublicKey.hash);\n private readonly _streams = new ComplexMap<PublicKey, ActiveStream>(PublicKey.hash);\n\n private _rpc?: ProtoRpcPeer<ServiceBundle>;\n private _extensionContext?: ExtensionContext;\n\n private _options: ReplicationOptions = {\n upload: false,\n };\n\n private readonly _updateTask = new DeferredTask(this._ctx, async () => {\n try {\n if (this._extensionContext!.initiator === false) {\n await this._rpc!.rpc.ReplicatorService.updateFeeds({\n feeds: Array.from(this._feeds.values()).map((feed) => ({\n feedKey: feed.key,\n download: true,\n upload: this._options.upload,\n })),\n });\n } else if (this._extensionContext!.initiator === true) {\n await this._reevaluateFeeds();\n }\n } catch (err) {\n if (err instanceof RpcClosedError) {\n return; // Some RPC requests might be pending while closing.\n }\n throw err;\n }\n });\n\n @logInfo\n private get extensionInfo() {\n return {\n initiator: this._extensionContext?.initiator,\n localPeerId: this._extensionContext?.localPeerId,\n remotePeerId: this._extensionContext?.remotePeerId,\n feeds: Array.from(this._feeds.keys()),\n };\n }\n\n setOptions(options: ReplicationOptions): this {\n this._options = options;\n log('setOptions', { options });\n if (this._extensionContext) {\n this._updateTask.schedule();\n }\n return this;\n }\n\n addFeed(feed: FeedWrapper<any>): void {\n this._feeds.set(feed.key, feed);\n log('addFeed', { feedKey: feed.key });\n if (this._extensionContext) {\n this._updateTask.schedule();\n }\n }\n\n async onOpen(context: ExtensionContext): Promise<void> {\n this._extensionContext = context;\n log('open');\n\n this._rpc = createProtoRpcPeer<ServiceBundle, ServiceBundle>({\n requested: {\n ReplicatorService: schema.getService('dxos.mesh.teleport.replicator.ReplicatorService'),\n },\n exposed: {\n ReplicatorService: schema.getService('dxos.mesh.teleport.replicator.ReplicatorService'),\n },\n handlers: {\n ReplicatorService: {\n updateFeeds: async ({ feeds }) => {\n log('received feed info', { feeds });\n invariant(this._extensionContext!.initiator === true, 'Invalid call');\n this._updateTask.schedule();\n },\n startReplication: async ({ info }) => {\n log('starting replication...', { info });\n invariant(this._extensionContext!.initiator === false, 'Invalid call');\n\n const streamTag = await this._acceptReplication(info);\n return {\n streamTag,\n };\n },\n stopReplication: async ({ info }) => {\n log('stopping replication...', { info });\n // TODO(dmaretskyi): Make sure any peer can stop replication.\n invariant(this._extensionContext!.initiator === false, 'Invalid call');\n\n await this._stopReplication(info.feedKey);\n },\n },\n },\n port: await context.createPort('rpc', {\n contentType: 'application/x-protobuf; messageType=\"dxos.rpc.Message\"',\n }),\n timeout: 10_000,\n });\n await this._rpc.open();\n\n this._updateTask.schedule();\n }\n\n async onClose(err?: Error | undefined): Promise<void> {\n log('close', { err });\n await this._ctx.dispose();\n await this._rpc?.close();\n for (const feedKey of this._streams.keys()) {\n await this._stopReplication(feedKey);\n }\n }\n\n async onAbort(err?: Error | undefined): Promise<void> {\n log('abort', { err });\n\n await this._ctx.dispose();\n await this._rpc?.abort();\n for (const feedKey of this._streams.keys()) {\n await this._stopReplication(feedKey);\n }\n }\n\n @synchronized\n private async _reevaluateFeeds(): Promise<void> {\n log('_reevaluateFeeds');\n for (const feedKey of this._feeds.keys()) {\n if (this._ctx.disposed) {\n return;\n }\n if (this._streams.has(feedKey) && this._options.upload !== this._streams.get(feedKey)?.info.upload) {\n try {\n await asyncTimeout(this._stopReplication(feedKey), 1000);\n } catch (err) {\n log.catch(err);\n }\n }\n\n if (this._ctx.disposed) {\n return;\n }\n if (!this._streams.has(feedKey)) {\n await this._initiateReplication({\n feedKey,\n download: true,\n upload: this._options.upload,\n });\n }\n }\n }\n\n /**\n * Try to initiate feed replication.\n */\n private async _initiateReplication(feedInfo: FeedInfo): Promise<void> {\n log('initiating replication', { feedInfo });\n invariant(this._extensionContext!.initiator === true, 'Invalid call');\n invariant(!this._streams.has(feedInfo.feedKey), `Replication already in progress for feed: ${feedInfo.feedKey}`);\n const { streamTag } = await this._rpc!.rpc.ReplicatorService.startReplication({ info: feedInfo });\n if (!streamTag) {\n return;\n }\n\n await this._replicateFeed(feedInfo, streamTag);\n }\n\n /**\n * Respond to a remote request to replicate a feed.\n * @returns A stream tag for the replication stream or `undefined` if we don't want to replicate.\n */\n @synchronized\n private async _acceptReplication(feedInfo: FeedInfo): Promise<string | undefined> {\n invariant(this._extensionContext!.initiator === false, 'Invalid call');\n\n if (!this._feeds.has(feedInfo.feedKey) || this._streams.has(feedInfo.feedKey)) {\n return undefined; // We don't have the feed or we are already replicating it.\n }\n\n const tag = `feed-${feedInfo.feedKey.toHex()}-${PublicKey.random().toHex().slice(0, 8)}`; // Generate a unique tag for the stream.\n await this._replicateFeed(feedInfo, tag);\n return tag;\n }\n\n private async _replicateFeed(info: FeedInfo, streamTag: string): Promise<void> {\n log('replicate', { info, streamTag });\n invariant(!this._streams.has(info.feedKey), `Replication already in progress for feed: ${info.feedKey}`);\n\n const feed = this._feeds.get(info.feedKey) ?? failUndefined();\n const networkStream = await this._extensionContext!.createStream(streamTag, {\n contentType: 'application/x-hypercore',\n });\n let replicationStreamErrors = 0;\n\n // https://github.com/holepunchto/hypercore/tree/v9.12.0#var-stream--feedreplicateisinitiator-options\n const replicationStream = feed.replicate(true, {\n live: true,\n upload: info.upload,\n download: info.download,\n noise: false,\n encrypted: false,\n maxRequests: 1024,\n });\n\n // Left for testing.\n // const debug = true;\n // if (debug) {\n // feed.on('sync', () => {\n // log.info('sync', { key: feed.key, length: feed.length });\n // });\n // feed.on('download', (index: number, data: any) => {\n // log.info('download', {\n // key: feed.key,\n // index,\n // length: feed.length,\n // data: data.length,\n // });\n // });\n // }\n\n replicationStream.on('error', (err) => {\n if (err instanceof TimeoutError) {\n log.info('replication stream timeout', { err, info });\n return;\n }\n // TODO(nf): use sentinel errors\n if (\n err?.message === 'Writable stream closed prematurely' ||\n err?.message === 'Cannot call write after a stream was destroyed'\n ) {\n log('replication stream closed', { err, info });\n return;\n }\n\n // TODO(nf): WARN on first error? log full info on some subsequent errors?\n if (replicationStreamErrors === 0) {\n log.info('replication stream error', { err, info });\n } else {\n log.info('replication stream error', { err, feedKey: info.feedKey, count: replicationStreamErrors });\n }\n replicationStreamErrors++;\n });\n\n this._streams.set(info.feedKey, {\n streamTag,\n networkStream,\n replicationStream,\n info,\n });\n\n networkStream.pipe(replicationStream as any).pipe(networkStream);\n }\n\n private async _stopReplication(feedKey: PublicKey): Promise<void> {\n const stream = this._streams.get(feedKey);\n if (!stream) {\n return;\n }\n\n stream.networkStream.destroy();\n this._streams.delete(feedKey);\n }\n}\n\ntype ServiceBundle = {\n ReplicatorService: ReplicatorService;\n};\n\ntype ActiveStream = {\n streamTag: string;\n networkStream: Duplex;\n replicationStream: ProtocolStream;\n info: FeedInfo;\n};\n"],
5
+ "mappings": "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",
6
+ "names": ["Context", "failUndefined", "invariant", "PublicKey", "log", "RpcClosedError", "TimeoutError", "schema", "createProtoRpcPeer", "ComplexMap", "onError", "err", "_extensionContext", "_feeds", "_streams", "hash", "_rpc", "_options", "upload", "_updateTask", "ReplicatorService", "updateFeeds", "feeds", "Array", "from", "values", "feed", "feedKey", "key", "download", "_reevaluateFeeds", "initiator", "localPeerId", "remotePeerId", "setOptions", "options", "schedule", "addFeed", "requested", "exposed", "handlers", "startReplication", "info", "streamTag", "_acceptReplication", "stopReplication", "_stopReplication", "port", "contentType", "timeout", "_ctx", "close", "abort", "disposed", "catch", "_initiateReplication", "feedInfo", "rpc", "undefined", "_replicateFeed", "tag", "has", "get", "networkStream", "createStream", "live", "noise", "encrypted", "maxRequests", "count", "replicationStreamErrors", "replicationStream", "stream"]
7
7
  }
@@ -0,0 +1 @@
1
+ {"inputs":{"src/replicator-extension.ts":{"bytes":36158,"imports":[{"path":"@dxos/async","kind":"import-statement","external":true},{"path":"@dxos/context","kind":"import-statement","external":true},{"path":"@dxos/debug","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","kind":"import-statement","external":true},{"path":"@dxos/protocols/proto","kind":"import-statement","external":true},{"path":"@dxos/rpc","kind":"import-statement","external":true},{"path":"@dxos/util","kind":"import-statement","external":true}],"format":"esm"},"src/index.ts":{"bytes":408,"imports":[{"path":"src/replicator-extension.ts","kind":"import-statement","original":"./replicator-extension"}],"format":"esm"}},"outputs":{"dist/lib/neutral/index.mjs.map":{"imports":[],"exports":[],"inputs":{},"bytes":16928},"dist/lib/neutral/index.mjs":{"imports":[{"path":"@dxos/async","kind":"import-statement","external":true},{"path":"@dxos/context","kind":"import-statement","external":true},{"path":"@dxos/debug","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","kind":"import-statement","external":true},{"path":"@dxos/protocols/proto","kind":"import-statement","external":true},{"path":"@dxos/rpc","kind":"import-statement","external":true},{"path":"@dxos/util","kind":"import-statement","external":true}],"exports":["ReplicatorExtension"],"entryPoint":"src/index.ts","inputs":{"src/replicator-extension.ts":{"bytesInOutput":10583},"src/index.ts":{"bytesInOutput":0}},"bytes":10717}}}
@@ -21,14 +21,7 @@ export declare class ReplicatorExtension implements TeleportExtension {
21
21
  onClose(err?: Error | undefined): Promise<void>;
22
22
  onAbort(err?: Error | undefined): Promise<void>;
23
23
  private _reevaluateFeeds;
24
- /**
25
- * Try to initiate feed replication.
26
- */
27
24
  private _initiateReplication;
28
- /**
29
- * Respond to a remote request to replicate a feed.
30
- * @returns A stream tag for the replication stream or `undefined` if we don't want to replicate.
31
- */
32
25
  private _acceptReplication;
33
26
  private _replicateFeed;
34
27
  private _stopReplication;
@@ -1 +1 @@
1
- {"version":3,"file":"replicator-extension.d.ts","sourceRoot":"","sources":["../../../src/replicator-extension.ts"],"names":[],"mappings":"AAUA,OAAO,EAAE,KAAK,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAQpD,OAAO,EAAE,KAAK,gBAAgB,EAAE,KAAK,iBAAiB,EAAE,MAAM,gBAAgB,CAAC;AAG/E,MAAM,MAAM,kBAAkB,GAAG;IAC/B,MAAM,EAAE,OAAO,CAAC;CACjB,CAAC;AAEF;;GAEG;AACH,qBAAa,mBAAoB,YAAW,iBAAiB;IAC3D,OAAO,CAAC,QAAQ,CAAC,IAAI,CAIlB;IAEH,OAAO,CAAC,QAAQ,CAAC,MAAM,CAA+D;IACtF,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAA2D;IAEpF,OAAO,CAAC,IAAI,CAAC,CAA8B;IAC3C,OAAO,CAAC,iBAAiB,CAAC,CAAmB;IAE7C,OAAO,CAAC,QAAQ,CAEd;IAEF,OAAO,CAAC,QAAQ,CAAC,WAAW,CAmBzB;IAGH,OAAO,KAAK,aAAa,GAOxB;IAED,UAAU,CAAC,OAAO,EAAE,kBAAkB,GAAG,IAAI;IAS7C,OAAO,CAAC,IAAI,EAAE,WAAW,CAAC,GAAG,CAAC,GAAG,IAAI;IAQ/B,MAAM,CAAC,OAAO,EAAE,gBAAgB,GAAG,OAAO,CAAC,IAAI,CAAC;IA8ChD,OAAO,CAAC,GAAG,CAAC,EAAE,KAAK,GAAG,SAAS,GAAG,OAAO,CAAC,IAAI,CAAC;IAS/C,OAAO,CAAC,GAAG,CAAC,EAAE,KAAK,GAAG,SAAS,GAAG,OAAO,CAAC,IAAI,CAAC;YAWvC,gBAAgB;IA2B9B;;OAEG;YACW,oBAAoB;IAYlC;;;OAGG;YAEW,kBAAkB;YAYlB,cAAc;YAqEd,gBAAgB;CAS/B"}
1
+ {"version":3,"file":"replicator-extension.d.ts","sourceRoot":"","sources":["../../../src/replicator-extension.ts"],"names":[],"mappings":"AAUA,OAAO,EAAE,KAAK,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAQpD,OAAO,EAAE,KAAK,gBAAgB,EAAE,KAAK,iBAAiB,EAAE,MAAM,gBAAgB,CAAC;AAG/E,MAAM,MAAM,kBAAkB,GAAG;IAC/B,MAAM,EAAE,OAAO,CAAC;CACjB,CAAC;AAEF;;GAEG;AACH,qBAAa,mBAAoB,YAAW,iBAAiB;IAC3D,OAAO,CAAC,QAAQ,CAAC,IAAI,CAIlB;IAEH,OAAO,CAAC,QAAQ,CAAC,MAAM,CAA+D;IACtF,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAA2D;IAEpF,OAAO,CAAC,IAAI,CAAC,CAA8B;IAC3C,OAAO,CAAC,iBAAiB,CAAC,CAAmB;IAE7C,OAAO,CAAC,QAAQ,CAEd;IAEF,OAAO,CAAC,QAAQ,CAAC,WAAW,CAmBzB;IAGH,OAAO,KAAK,aAAa,GAOxB;IAED,UAAU,CAAC,OAAO,EAAE,kBAAkB,GAAG,IAAI,CAO5C;IAED,OAAO,CAAC,IAAI,EAAE,WAAW,CAAC,GAAG,CAAC,GAAG,IAAI,CAMpC;IAEK,MAAM,CAAC,OAAO,EAAE,gBAAgB,GAAG,OAAO,CAAC,IAAI,CAAC,CA4CrD;IAEK,OAAO,CAAC,GAAG,CAAC,EAAE,KAAK,GAAG,SAAS,GAAG,OAAO,CAAC,IAAI,CAAC,CAOpD;IAEK,OAAO,CAAC,GAAG,CAAC,EAAE,KAAK,GAAG,SAAS,GAAG,OAAO,CAAC,IAAI,CAAC,CAQpD;YAGa,gBAAgB;YA8BhB,oBAAoB;YAiBpB,kBAAkB;YAYlB,cAAc;YAqEd,gBAAgB;CAS/B"}
@@ -1 +1 @@
1
- {"version":3,"file":"testing.d.ts","sourceRoot":"","sources":["../../../src/testing.ts"],"names":[],"mappings":"AAOA,OAAO,EAAe,KAAK,WAAW,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAC5E,OAAO,EAAE,OAAO,EAAE,MAAM,eAAe,CAAC;AACxC,OAAO,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAGvC,OAAO,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAG1C,OAAO,EAAE,mBAAmB,EAAE,MAAM,wBAAwB,CAAC;AAE7D,qBAAa,WAAW;IACtB,WAAW,IAAI,SAAS;CAGzB;AAGD,qBAAa,SAAS;IACb,OAAO,gDAA4C;IACnD,OAAO,UAAwD;IAC/D,SAAS,gBAEb;IAEG,eAAe,CAAC,SAAS,SAAI;IAUnC,cAAc,CAAC,GAAG,EAAE,SAAS,EAAE,IAAI,CAAC,EAAE,WAAW;CAGlD;AAED;;GAEG;AACH,eAAO,MAAM,gBAAgB;;;EAuB5B,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,oBAAoB;;;EAUhC,CAAC"}
1
+ {"version":3,"file":"testing.d.ts","sourceRoot":"","sources":["../../../src/testing.ts"],"names":[],"mappings":"AAOA,OAAO,EAAe,KAAK,WAAW,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAC5E,OAAO,EAAE,OAAO,EAAE,MAAM,eAAe,CAAC;AACxC,OAAO,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAGvC,OAAO,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAG1C,OAAO,EAAE,mBAAmB,EAAE,MAAM,wBAAwB,CAAC;AAE7D,qBAAa,WAAW;IACtB,WAAW,IAAI,SAAS,CAEvB;CACF;AAGD,qBAAa,SAAS;IACb,OAAO,gDAA4C;IACnD,OAAO,UAAwD;IAC/D,SAAS,gBAEb;IAEG,eAAe,CAAC,SAAS,SAAI,uDAQlC;IAED,cAAc,CAAC,GAAG,EAAE,SAAS,EAAE,IAAI,CAAC,EAAE,WAAW,uDAEhD;CACF;AAED;;GAEG;AACH,eAAO,MAAM,gBAAgB;;;EAuB5B,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,oBAAoB;;;EAUhC,CAAC"}