@enbox/agent 0.7.4 → 0.7.5

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.
@@ -1396,6 +1396,39 @@ export class SyncEngineLevel implements SyncEngine {
1396
1396
  }
1397
1397
  }
1398
1398
 
1399
+ /**
1400
+ * Wrapper around {@link initializeLinkTarget} that retries on DID
1401
+ * resolution failures. Newly published `did:dht` DIDs take a few
1402
+ * seconds to propagate through the DHT network. During this window,
1403
+ * the remote DWN can't resolve the DID to verify request signatures,
1404
+ * causing a 401. Retrying with exponential backoff lets the
1405
+ * propagation settle before giving up.
1406
+ */
1407
+ private async initializeLinkTargetWithRetry(target: {
1408
+ did: string; dwnUrl: string; delegateDid?: string; protocol?: string;
1409
+ }): Promise<void> {
1410
+ try {
1411
+ await this.initializeLinkTarget(target);
1412
+ } catch (error: any) {
1413
+ const msg = error.message ?? '';
1414
+ const isDidResolutionFailure = msg.includes('GetPublicKeyNotFound') || msg.includes('notFound');
1415
+ if (!isDidResolutionFailure) { throw error; }
1416
+
1417
+ const delays = [2000, 4000, 8000];
1418
+ for (const delay of delays) {
1419
+ await sleep(delay);
1420
+ try {
1421
+ await this.initializeLinkTarget(target);
1422
+ return;
1423
+ } catch {
1424
+ // Continue to next attempt.
1425
+ }
1426
+ }
1427
+ // All retries exhausted — the original error was already logged
1428
+ // by initializeLinkTarget's catch block.
1429
+ }
1430
+ }
1431
+
1399
1432
  // ---------------------------------------------------------------------------
1400
1433
  // Hot-add / hot-remove: per-identity live sync management
1401
1434
  // ---------------------------------------------------------------------------
@@ -1430,7 +1463,7 @@ export class SyncEngineLevel implements SyncEngine {
1430
1463
  }
1431
1464
  }
1432
1465
 
1433
- await Promise.allSettled(targets.map(t => this.initializeLinkTarget(t)));
1466
+ await Promise.allSettled(targets.map(t => this.initializeLinkTargetWithRetry(t)));
1434
1467
  }
1435
1468
 
1436
1469
  /** Hot-remove a single identity from the active live sync session. */
@@ -393,9 +393,10 @@ export async function pushMessages({ did, dwnUrl, delegateDid, protocol, message
393
393
  for (const entry of sorted) {
394
394
  const cid = await getMessageCid(entry.message);
395
395
 
396
- // Create a fresh stream from the buffer for each send attempt.
396
+ // Use a Blob for buffered data unlike ReadableStream, Blob is
397
+ // replayable so fetchWithRetry can retry the HTTP request on failure.
397
398
  const data = entry.bufferedData
398
- ? new ReadableStream<Uint8Array>({ start(c): void { c.enqueue(entry.bufferedData!); c.close(); } })
399
+ ? new Blob([entry.bufferedData] as BlobPart[], { type: 'application/octet-stream' })
399
400
  : entry.dataStream;
400
401
 
401
402
  try {