@decentnetwork/peer 0.1.150 → 0.1.151

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.
Files changed (2) hide show
  1. package/dist/peer.js +59 -0
  2. package/package.json +1 -1
package/dist/peer.js CHANGED
@@ -395,6 +395,7 @@ export class Peer {
395
395
  #textHandlers = new Set();
396
396
  #pendingTextAcks = new Map();
397
397
  #deliveredTextIds = new Set();
398
+ #deliveredPersistTimer;
398
399
  #deliveredTextOrder = [];
399
400
  #friendStoreFile;
400
401
  #persistSeq = 0; // makes atomic friend-store temp filenames unique per write
@@ -598,6 +599,7 @@ export class Peer {
598
599
  }
599
600
  this.#cookieSymmetricKey = randomBytes(32);
600
601
  await this.#loadPersistedFriends();
602
+ await this.#loadDeliveredTextIds();
601
603
  if (this.#opts.expressNodes && this.#opts.expressNodes.length > 0) {
602
604
  this.#express = new LegacyExpressClient({
603
605
  nodes: this.#opts.expressNodes,
@@ -1623,6 +1625,63 @@ export class Peer {
1623
1625
  if (old)
1624
1626
  this.#deliveredTextIds.delete(old);
1625
1627
  }
1628
+ this.#persistDeliveredTextIds();
1629
+ }
1630
+ /** Where the delivered-id set lives between runs. Next to the friend store,
1631
+ * because it is the same kind of state: what this node already knows. */
1632
+ get #deliveredStoreFile() {
1633
+ return this.#friendStoreFile ? `${this.#friendStoreFile}.delivered.json` : undefined;
1634
+ }
1635
+ /** Persist the seen delivery ids.
1636
+ *
1637
+ * In memory only, this set died with the process — and the moment it did,
1638
+ * every message the sender had retransmitted while we were down was
1639
+ * accepted as new. Restart the daemon during a conversation and the last
1640
+ * messages arrive TWICE, which is exactly what a restart-heavy evening
1641
+ * looked like. The sender is behaving correctly: it never got an ACK, so
1642
+ * it resent. Remembering is the receiver's job.
1643
+ *
1644
+ * Debounced: a busy chat would otherwise write the file per message. */
1645
+ #persistDeliveredTextIds() {
1646
+ const file = this.#deliveredStoreFile;
1647
+ if (!file || this.#deliveredPersistTimer)
1648
+ return;
1649
+ this.#deliveredPersistTimer = setTimeout(() => {
1650
+ this.#deliveredPersistTimer = undefined;
1651
+ const payload = JSON.stringify(this.#deliveredTextOrder);
1652
+ const tmp = `${file}.tmp.${process.pid}.${this.#persistSeq++}`;
1653
+ void mkdir(dirname(file), { recursive: true })
1654
+ .then(() => writeFile(tmp, payload, "utf8"))
1655
+ .then(() => rename(tmp, file))
1656
+ .catch((error) => {
1657
+ this.#debugLog(`persist delivered ids failed: ${error.message}`);
1658
+ });
1659
+ }, 1000);
1660
+ this.#deliveredPersistTimer.unref?.();
1661
+ }
1662
+ async #loadDeliveredTextIds() {
1663
+ const file = this.#deliveredStoreFile;
1664
+ if (!file)
1665
+ return;
1666
+ try {
1667
+ const raw = await readFile(file, "utf8");
1668
+ const ids = JSON.parse(raw);
1669
+ if (!Array.isArray(ids))
1670
+ return;
1671
+ for (const id of ids) {
1672
+ if (typeof id !== "string")
1673
+ continue;
1674
+ if (this.#deliveredTextIds.has(id))
1675
+ continue;
1676
+ this.#deliveredTextIds.add(id);
1677
+ this.#deliveredTextOrder.push(id);
1678
+ }
1679
+ this.#debugLog(`loaded ${this.#deliveredTextIds.size} delivered text id(s)`);
1680
+ }
1681
+ catch {
1682
+ // Absent or unreadable: start empty. Worst case is the duplicate this
1683
+ // was written to prevent, not a failure to start.
1684
+ }
1626
1685
  }
1627
1686
  /** Files received inline over (bulk)messages — the iOS/C Carrier apps'
1628
1687
  * native way of sending images/audio online (FileModel JSON envelope). */
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@decentnetwork/peer",
3
- "version": "0.1.150",
3
+ "version": "0.1.151",
4
4
  "description": "Pure TypeScript port of Elastos Carrier (toxcore-derived) P2P messaging. DHT, onion routing, TCP relay, FlatBuffers app payloads, Express offline relay. Wire-compatible with iOS Beagle and the Carrier C SDK.",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",