@mtcute/core 0.23.2 → 0.24.0

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 (131) hide show
  1. package/client.cjs +21 -2
  2. package/client.js +21 -2
  3. package/highlevel/base.cjs +15 -3
  4. package/highlevel/base.d.cts +4 -1
  5. package/highlevel/base.d.ts +4 -1
  6. package/highlevel/base.js +15 -3
  7. package/highlevel/client.d.cts +56 -7
  8. package/highlevel/client.d.ts +56 -7
  9. package/highlevel/client.types.d.cts +2 -1
  10. package/highlevel/client.types.d.ts +2 -1
  11. package/highlevel/methods/chats/get-chat-event-log.cjs +5 -3
  12. package/highlevel/methods/chats/get-chat-event-log.js +3 -1
  13. package/highlevel/methods/files/download-iterable.cjs +1 -1
  14. package/highlevel/methods/files/download-iterable.js +1 -1
  15. package/highlevel/methods/premium/_normalize-input-star-gift.cjs +6 -0
  16. package/highlevel/methods/premium/_normalize-input-star-gift.js +6 -0
  17. package/highlevel/methods/premium/buy-resale-gift.cjs +30 -0
  18. package/highlevel/methods/premium/buy-resale-gift.d.cts +13 -0
  19. package/highlevel/methods/premium/buy-resale-gift.d.ts +13 -0
  20. package/highlevel/methods/premium/buy-resale-gift.js +25 -0
  21. package/highlevel/methods/premium/get-resale-star-gifts.cjs +107 -0
  22. package/highlevel/methods/premium/get-resale-star-gifts.d.cts +45 -0
  23. package/highlevel/methods/premium/get-resale-star-gifts.d.ts +45 -0
  24. package/highlevel/methods/premium/get-resale-star-gifts.js +102 -0
  25. package/highlevel/methods/premium/get-unique-star-gift.cjs +1 -1
  26. package/highlevel/methods/premium/get-unique-star-gift.js +1 -1
  27. package/highlevel/methods/premium/set-gift-resale-price.cjs +19 -0
  28. package/highlevel/methods/premium/set-gift-resale-price.d.cts +9 -0
  29. package/highlevel/methods/premium/set-gift-resale-price.d.ts +9 -0
  30. package/highlevel/methods/premium/set-gift-resale-price.js +14 -0
  31. package/highlevel/methods/premium/transfer-star-gift.cjs +28 -13
  32. package/highlevel/methods/premium/transfer-star-gift.d.cts +1 -1
  33. package/highlevel/methods/premium/transfer-star-gift.d.ts +1 -1
  34. package/highlevel/methods/premium/transfer-star-gift.js +28 -13
  35. package/highlevel/methods/premium/upgrade-star-gift.cjs +26 -11
  36. package/highlevel/methods/premium/upgrade-star-gift.js +26 -11
  37. package/highlevel/methods/users/resolve-peer.cjs +63 -70
  38. package/highlevel/methods/users/resolve-peer.d.cts +2 -1
  39. package/highlevel/methods/users/resolve-peer.d.ts +2 -1
  40. package/highlevel/methods/users/resolve-peer.js +61 -68
  41. package/highlevel/methods/users/resolve-phone-number.cjs +36 -0
  42. package/highlevel/methods/users/resolve-phone-number.d.cts +10 -0
  43. package/highlevel/methods/users/resolve-phone-number.d.ts +10 -0
  44. package/highlevel/methods/users/resolve-phone-number.js +31 -0
  45. package/highlevel/methods.d.cts +10 -4
  46. package/highlevel/methods.d.ts +10 -4
  47. package/highlevel/types/messages/message-action.cjs +8 -2
  48. package/highlevel/types/messages/message-action.d.cts +6 -0
  49. package/highlevel/types/messages/message-action.d.ts +6 -0
  50. package/highlevel/types/messages/message-action.js +8 -2
  51. package/highlevel/types/peers/chat-event/actions.cjs +49 -1
  52. package/highlevel/types/peers/chat-event/actions.d.cts +60 -2
  53. package/highlevel/types/peers/chat-event/actions.d.ts +60 -2
  54. package/highlevel/types/peers/chat-event/actions.js +49 -1
  55. package/highlevel/types/peers/chat-event/filters.cjs +9 -0
  56. package/highlevel/types/peers/chat-event/filters.js +9 -0
  57. package/highlevel/types/peers/chat-event/index.cjs +3 -2
  58. package/highlevel/types/peers/chat-event/index.d.cts +2 -1
  59. package/highlevel/types/peers/chat-event/index.d.ts +2 -1
  60. package/highlevel/types/peers/chat-event/index.js +3 -2
  61. package/highlevel/types/peers/chat.cjs +5 -4
  62. package/highlevel/types/peers/chat.d.cts +2 -0
  63. package/highlevel/types/peers/chat.d.ts +2 -0
  64. package/highlevel/types/peers/chat.js +5 -4
  65. package/highlevel/types/peers/peer.d.cts +2 -3
  66. package/highlevel/types/peers/peer.d.ts +2 -3
  67. package/highlevel/types/peers/user.cjs +1 -4
  68. package/highlevel/types/peers/user.js +1 -4
  69. package/highlevel/types/premium/saved-star-gift.cjs +8 -0
  70. package/highlevel/types/premium/saved-star-gift.d.cts +4 -0
  71. package/highlevel/types/premium/saved-star-gift.d.ts +4 -0
  72. package/highlevel/types/premium/saved-star-gift.js +8 -0
  73. package/highlevel/types/premium/stars-gift-unique.cjs +13 -2
  74. package/highlevel/types/premium/stars-gift-unique.d.cts +6 -2
  75. package/highlevel/types/premium/stars-gift-unique.d.ts +6 -2
  76. package/highlevel/types/premium/stars-gift-unique.js +13 -2
  77. package/highlevel/types/premium/stars-gift.cjs +11 -1
  78. package/highlevel/types/premium/stars-gift.d.cts +8 -1
  79. package/highlevel/types/premium/stars-gift.d.ts +8 -1
  80. package/highlevel/types/premium/stars-gift.js +11 -1
  81. package/highlevel/types/premium/stars-transaction.cjs +7 -1
  82. package/highlevel/types/premium/stars-transaction.d.cts +9 -2
  83. package/highlevel/types/premium/stars-transaction.d.ts +9 -2
  84. package/highlevel/types/premium/stars-transaction.js +7 -1
  85. package/highlevel/types/reactions/emoji-status.cjs +6 -0
  86. package/highlevel/types/reactions/emoji-status.d.cts +1 -0
  87. package/highlevel/types/reactions/emoji-status.d.ts +1 -0
  88. package/highlevel/types/reactions/emoji-status.js +6 -0
  89. package/highlevel/types/utils.d.cts +4 -0
  90. package/highlevel/types/utils.d.ts +4 -0
  91. package/highlevel/updates/manager.cjs +35 -26
  92. package/highlevel/updates/manager.d.cts +6 -6
  93. package/highlevel/updates/manager.d.ts +6 -6
  94. package/highlevel/updates/manager.js +35 -26
  95. package/highlevel/updates/types.d.cts +6 -6
  96. package/highlevel/updates/types.d.ts +6 -6
  97. package/highlevel/utils/misc-utils.cjs +8 -0
  98. package/highlevel/utils/misc-utils.d.cts +2 -1
  99. package/highlevel/utils/misc-utils.d.ts +2 -1
  100. package/highlevel/utils/misc-utils.js +8 -0
  101. package/highlevel/worker/port.cjs +7 -5
  102. package/highlevel/worker/port.d.cts +3 -2
  103. package/highlevel/worker/port.d.ts +3 -2
  104. package/highlevel/worker/port.js +7 -5
  105. package/methods.cjs +8 -0
  106. package/methods.js +8 -0
  107. package/network/client.cjs +12 -8
  108. package/network/client.d.cts +4 -1
  109. package/network/client.d.ts +4 -1
  110. package/network/client.js +12 -8
  111. package/network/network-manager.cjs +1 -1
  112. package/network/network-manager.js +1 -1
  113. package/network/session-connection.cjs +1 -0
  114. package/network/session-connection.js +1 -0
  115. package/package.json +2 -2
  116. package/utils/binary/compat.cjs +9 -0
  117. package/utils/binary/compat.js +9 -0
  118. package/utils/index.d.cts +0 -1
  119. package/utils/index.d.ts +0 -1
  120. package/utils/sorted-array.cjs +6 -0
  121. package/utils/sorted-array.d.cts +2 -0
  122. package/utils/sorted-array.d.ts +2 -0
  123. package/utils/sorted-array.js +6 -0
  124. package/utils.cjs +1 -2
  125. package/utils.js +2 -3
  126. package/utils/linked-list.cjs +0 -65
  127. package/utils/linked-list.d.cts +0 -21
  128. package/utils/linked-list.d.ts +0 -21
  129. package/utils/linked-list.js +0 -60
  130. package/utils/linked-list.test.d.cts +0 -1
  131. package/utils/linked-list.test.d.ts +0 -1
@@ -11,14 +11,15 @@ const Long = require("long");
11
11
  const errors = require("../../types/errors.cjs");
12
12
  const utils$1 = require("../../types/utils.cjs");
13
13
  const earlyTimer = require("../../utils/early-timer.cjs");
14
- const linkedList = require("../../utils/linked-list.cjs");
15
14
  const peerUtils = require("../../utils/peer-utils.cjs");
15
+ const sortedArray = require("../../utils/sorted-array.cjs");
16
16
  require("@mtcute/tl-runtime");
17
17
  const batchedQueries = require("../methods/chats/batched-queries.cjs");
18
18
  const peersIndex = require("../types/peers/peers-index.cjs");
19
19
  const types = require("./types.cjs");
20
20
  const utils$2 = require("./utils.cjs");
21
21
  const peerUtils$1 = require("../utils/peer-utils.cjs");
22
+ const WARN_EVERY = 100;
22
23
  const KEEP_ALIVE_INTERVAL = 15 * 60 * 1e3;
23
24
  const UPDATES_TOO_LONG = { _: "updatesTooLong" };
24
25
  class UpdatesManager {
@@ -51,11 +52,11 @@ class UpdatesManager {
51
52
  updatesLoopCv = new utils.ConditionVariable();
52
53
  postponedTimer = new earlyTimer.EarlyTimer();
53
54
  hasTimedoutPostponed = false;
54
- pendingUpdateContainers = new linkedList.SortedLinkedList((a, b) => a.seqStart - b.seqStart);
55
- pendingPtsUpdates = new linkedList.SortedLinkedList((a, b) => a.ptsBefore - b.ptsBefore);
56
- pendingPtsUpdatesPostponed = new linkedList.SortedLinkedList((a, b) => a.ptsBefore - b.ptsBefore);
57
- pendingQtsUpdates = new linkedList.SortedLinkedList((a, b) => a.qtsBefore - b.qtsBefore);
58
- pendingQtsUpdatesPostponed = new linkedList.SortedLinkedList((a, b) => a.qtsBefore - b.qtsBefore);
55
+ pendingUpdateContainers = new sortedArray.SortedArray([], (a, b) => a.seqStart - b.seqStart);
56
+ pendingPtsUpdates = new sortedArray.SortedArray([], (a, b) => a.ptsBefore - b.ptsBefore);
57
+ pendingPtsUpdatesPostponed = new sortedArray.SortedArray([], (a, b) => a.ptsBefore - b.ptsBefore);
58
+ pendingQtsUpdates = new sortedArray.SortedArray([], (a, b) => a.qtsBefore - b.qtsBefore);
59
+ pendingQtsUpdatesPostponed = new sortedArray.SortedArray([], (a, b) => a.qtsBefore - b.qtsBefore);
59
60
  pendingUnorderedUpdates = new utils.Deque();
60
61
  noDispatchEnabled;
61
62
  // channel id or 0 => msg id
@@ -197,7 +198,7 @@ class UpdatesManager {
197
198
  case "updateShortChatMessage":
198
199
  case "updateShort":
199
200
  case "updateShortSentMessage":
200
- this.pendingUpdateContainers.add({
201
+ this.pendingUpdateContainers.insert({
201
202
  upd: update,
202
203
  seqStart: 0,
203
204
  seqEnd: 0
@@ -205,7 +206,7 @@ class UpdatesManager {
205
206
  break;
206
207
  case "updates":
207
208
  case "updatesCombined":
208
- this.pendingUpdateContainers.add({
209
+ this.pendingUpdateContainers.insert({
209
210
  upd: update,
210
211
  seqStart: update._ === "updatesCombined" ? update.seqStart : update.seq,
211
212
  seqEnd: update.seq
@@ -214,6 +215,9 @@ class UpdatesManager {
214
215
  default:
215
216
  utils$1.assertNever();
216
217
  }
218
+ if (this.pendingUpdateContainers.length % WARN_EVERY === 0) {
219
+ this.log.warn("%d pending update containers, updatesLoopActive = %b. possible memory leak", this.pendingUpdateContainers.length, this.updatesLoopActive);
220
+ }
217
221
  this.updatesLoopCv.notify();
218
222
  }
219
223
  /**
@@ -776,7 +780,7 @@ class UpdatesManager {
776
780
  if (utils$2.isMessageEmpty(upd)) return;
777
781
  const parsed = utils$2.toPendingUpdate(upd, peers, true);
778
782
  if (parsed.channelId && parsed.ptsBefore) {
779
- pendingPtsUpdates.add(parsed);
783
+ pendingPtsUpdates.insert(parsed);
780
784
  } else {
781
785
  pendingUnorderedUpdates.pushBack(parsed);
782
786
  }
@@ -1068,9 +1072,9 @@ class UpdatesManager {
1068
1072
  }
1069
1073
  const parsed = utils$2.toPendingUpdate(update, peers);
1070
1074
  if (parsed.ptsBefore !== void 0) {
1071
- pendingPtsUpdates.add(parsed);
1075
+ pendingPtsUpdates.insert(parsed);
1072
1076
  } else if (parsed.qtsBefore !== void 0) {
1073
- pendingQtsUpdates.add(parsed);
1077
+ pendingQtsUpdates.insert(parsed);
1074
1078
  } else {
1075
1079
  pendingUnorderedUpdates.pushBack(parsed);
1076
1080
  }
@@ -1085,9 +1089,9 @@ class UpdatesManager {
1085
1089
  log.debug("received short %s", upd._);
1086
1090
  const parsed = utils$2.toPendingUpdate(upd.update, new peersIndex.PeersIndex());
1087
1091
  if (parsed.ptsBefore !== void 0) {
1088
- pendingPtsUpdates.add(parsed);
1092
+ pendingPtsUpdates.insert(parsed);
1089
1093
  } else if (parsed.qtsBefore !== void 0) {
1090
- pendingQtsUpdates.add(parsed);
1094
+ pendingQtsUpdates.insert(parsed);
1091
1095
  } else {
1092
1096
  pendingUnorderedUpdates.pushBack(parsed);
1093
1097
  }
@@ -1129,7 +1133,7 @@ class UpdatesManager {
1129
1133
  pts: upd.pts,
1130
1134
  ptsCount: upd.ptsCount
1131
1135
  };
1132
- pendingPtsUpdates.add({
1136
+ pendingPtsUpdates.insert({
1133
1137
  update,
1134
1138
  ptsBefore: upd.pts - upd.ptsCount,
1135
1139
  pts: upd.pts,
@@ -1169,7 +1173,7 @@ class UpdatesManager {
1169
1173
  pts: upd.pts,
1170
1174
  ptsCount: upd.ptsCount
1171
1175
  };
1172
- pendingPtsUpdates.add({
1176
+ pendingPtsUpdates.insert({
1173
1177
  update,
1174
1178
  ptsBefore: upd.pts - upd.ptsCount,
1175
1179
  pts: upd.pts,
@@ -1226,7 +1230,7 @@ class UpdatesManager {
1226
1230
  diff
1227
1231
  );
1228
1232
  pending.timeout = performance.now() + 500;
1229
- pendingPtsUpdatesPostponed.add(pending);
1233
+ pendingPtsUpdatesPostponed.insert(pending);
1230
1234
  postponedTimer.emitBefore(pending.timeout);
1231
1235
  } else if (diff > -1e6) {
1232
1236
  log.debug(
@@ -1265,8 +1269,8 @@ class UpdatesManager {
1265
1269
  await this._onUpdate(pending, requestedDiff);
1266
1270
  }
1267
1271
  this.log.debug("processing postponed pts-ordered updates");
1268
- for (let item = pendingPtsUpdatesPostponed._first; item; item = item.n) {
1269
- const pending = item.v;
1272
+ for (let i = 0; i < pendingPtsUpdatesPostponed.raw.length; i++) {
1273
+ const pending = pendingPtsUpdatesPostponed.raw[i];
1270
1274
  const upd = pending.update;
1271
1275
  let localPts;
1272
1276
  if (!pending.channelId) {
@@ -1290,7 +1294,8 @@ class UpdatesManager {
1290
1294
  localPts,
1291
1295
  pending.ptsBefore
1292
1296
  );
1293
- pendingPtsUpdatesPostponed._remove(item);
1297
+ pendingPtsUpdatesPostponed.removeIndex(i);
1298
+ i--;
1294
1299
  continue;
1295
1300
  }
1296
1301
  if (localPts < pending.ptsBefore) {
@@ -1312,7 +1317,8 @@ class UpdatesManager {
1312
1317
  localPts,
1313
1318
  pending.ptsBefore
1314
1319
  );
1315
- pendingPtsUpdatesPostponed._remove(item);
1320
+ pendingPtsUpdatesPostponed.removeIndex(i);
1321
+ i--;
1316
1322
  if (pending.channelId) {
1317
1323
  this._fetchChannelDifferenceLater(requestedDiff, pending.channelId);
1318
1324
  } else {
@@ -1322,7 +1328,8 @@ class UpdatesManager {
1322
1328
  continue;
1323
1329
  }
1324
1330
  await this._onUpdate(pending, requestedDiff, true);
1325
- pendingPtsUpdatesPostponed._remove(item);
1331
+ pendingPtsUpdatesPostponed.removeIndex(i);
1332
+ i--;
1326
1333
  }
1327
1334
  this.log.debug("processing pending qts-ordered updates");
1328
1335
  while (pendingQtsUpdates.length) {
@@ -1349,7 +1356,7 @@ class UpdatesManager {
1349
1356
  diff
1350
1357
  );
1351
1358
  pending.timeout = performance.now() + 500;
1352
- pendingQtsUpdatesPostponed.add(pending);
1359
+ pendingQtsUpdatesPostponed.insert(pending);
1353
1360
  postponedTimer.emitBefore(pending.timeout);
1354
1361
  } else {
1355
1362
  log.debug(
@@ -1369,8 +1376,8 @@ class UpdatesManager {
1369
1376
  await this._onUpdate(pending, requestedDiff);
1370
1377
  }
1371
1378
  this.log.debug("processing postponed qts-ordered updates");
1372
- for (let item = pendingQtsUpdatesPostponed._first; item; item = item.n) {
1373
- const pending = item.v;
1379
+ for (let i = 0; i < pendingQtsUpdatesPostponed.raw.length; i++) {
1380
+ const pending = pendingQtsUpdatesPostponed.raw[i];
1374
1381
  const upd = pending.update;
1375
1382
  if (this.qts > pending.qtsBefore) {
1376
1383
  log.debug(
@@ -1398,13 +1405,15 @@ class UpdatesManager {
1398
1405
  this.qts,
1399
1406
  pending.qtsBefore
1400
1407
  );
1401
- pendingQtsUpdatesPostponed._remove(item);
1408
+ pendingQtsUpdatesPostponed.removeIndex(i);
1409
+ i--;
1402
1410
  this._fetchDifferenceLater(requestedDiff);
1403
1411
  }
1404
1412
  continue;
1405
1413
  }
1406
1414
  await this._onUpdate(pending, requestedDiff, true);
1407
- pendingQtsUpdatesPostponed._remove(item);
1415
+ pendingQtsUpdatesPostponed.removeIndex(i);
1416
+ i--;
1408
1417
  }
1409
1418
  this.hasTimedoutPostponed = false;
1410
1419
  while (requestedDiff.size) {
@@ -1,4 +1,4 @@
1
- import { Logger, EarlyTimer, SortedLinkedList } from '../../utils/index.js';
1
+ import { Logger, EarlyTimer, SortedArray } from '../../utils/index.js';
2
2
  import { BaseTelegramClient } from '../base.js';
3
3
  import { AsyncLock, ConditionVariable, Deque, timers } from '@fuman/utils';
4
4
  import { tl } from '@mtcute/tl';
@@ -11,11 +11,11 @@ export declare class UpdatesManager {
11
11
  updatesLoopCv: ConditionVariable;
12
12
  postponedTimer: EarlyTimer;
13
13
  hasTimedoutPostponed: boolean;
14
- pendingUpdateContainers: SortedLinkedList<PendingUpdateContainer>;
15
- pendingPtsUpdates: SortedLinkedList<PendingUpdate>;
16
- pendingPtsUpdatesPostponed: SortedLinkedList<PendingUpdate>;
17
- pendingQtsUpdates: SortedLinkedList<PendingUpdate>;
18
- pendingQtsUpdatesPostponed: SortedLinkedList<PendingUpdate>;
14
+ pendingUpdateContainers: SortedArray<PendingUpdateContainer>;
15
+ pendingPtsUpdates: SortedArray<PendingUpdate>;
16
+ pendingPtsUpdatesPostponed: SortedArray<PendingUpdate>;
17
+ pendingQtsUpdates: SortedArray<PendingUpdate>;
18
+ pendingQtsUpdatesPostponed: SortedArray<PendingUpdate>;
19
19
  pendingUnorderedUpdates: Deque<PendingUpdate>;
20
20
  noDispatchEnabled: boolean;
21
21
  noDispatchMsg: Map<number, Set<number>>;
@@ -1,4 +1,4 @@
1
- import { Logger, EarlyTimer, SortedLinkedList } from '../../utils/index.js';
1
+ import { Logger, EarlyTimer, SortedArray } from '../../utils/index.js';
2
2
  import { BaseTelegramClient } from '../base.js';
3
3
  import { AsyncLock, ConditionVariable, Deque, timers } from '@fuman/utils';
4
4
  import { tl } from '@mtcute/tl';
@@ -11,11 +11,11 @@ export declare class UpdatesManager {
11
11
  updatesLoopCv: ConditionVariable;
12
12
  postponedTimer: EarlyTimer;
13
13
  hasTimedoutPostponed: boolean;
14
- pendingUpdateContainers: SortedLinkedList<PendingUpdateContainer>;
15
- pendingPtsUpdates: SortedLinkedList<PendingUpdate>;
16
- pendingPtsUpdatesPostponed: SortedLinkedList<PendingUpdate>;
17
- pendingQtsUpdates: SortedLinkedList<PendingUpdate>;
18
- pendingQtsUpdatesPostponed: SortedLinkedList<PendingUpdate>;
14
+ pendingUpdateContainers: SortedArray<PendingUpdateContainer>;
15
+ pendingPtsUpdates: SortedArray<PendingUpdate>;
16
+ pendingPtsUpdatesPostponed: SortedArray<PendingUpdate>;
17
+ pendingQtsUpdates: SortedArray<PendingUpdate>;
18
+ pendingQtsUpdatesPostponed: SortedArray<PendingUpdate>;
19
19
  pendingUnorderedUpdates: Deque<PendingUpdate>;
20
20
  noDispatchEnabled: boolean;
21
21
  noDispatchMsg: Map<number, Set<number>>;
@@ -4,14 +4,15 @@ import Long from "long";
4
4
  import { MtArgumentError } from "../../types/errors.js";
5
5
  import { assertNever } from "../../types/utils.js";
6
6
  import { EarlyTimer } from "../../utils/early-timer.js";
7
- import { SortedLinkedList } from "../../utils/linked-list.js";
8
7
  import { toggleChannelIdMark, parseMarkedPeerId, getBarePeerId, getMarkedPeerId } from "../../utils/peer-utils.js";
8
+ import { SortedArray } from "../../utils/sorted-array.js";
9
9
  import "@mtcute/tl-runtime";
10
10
  import { _getChannelsBatched } from "../methods/chats/batched-queries.js";
11
11
  import { PeersIndex } from "../types/peers/peers-index.js";
12
12
  import { RawUpdateInfo } from "./types.js";
13
13
  import { toPendingUpdate, messageToUpdate, isMessageEmpty, createDummyUpdatesContainer, extractChannelIdFromUpdate } from "./utils.js";
14
14
  import { toInputChannel } from "../utils/peer-utils.js";
15
+ const WARN_EVERY = 100;
15
16
  const KEEP_ALIVE_INTERVAL = 15 * 60 * 1e3;
16
17
  const UPDATES_TOO_LONG = { _: "updatesTooLong" };
17
18
  class UpdatesManager {
@@ -44,11 +45,11 @@ class UpdatesManager {
44
45
  updatesLoopCv = new ConditionVariable();
45
46
  postponedTimer = new EarlyTimer();
46
47
  hasTimedoutPostponed = false;
47
- pendingUpdateContainers = new SortedLinkedList((a, b) => a.seqStart - b.seqStart);
48
- pendingPtsUpdates = new SortedLinkedList((a, b) => a.ptsBefore - b.ptsBefore);
49
- pendingPtsUpdatesPostponed = new SortedLinkedList((a, b) => a.ptsBefore - b.ptsBefore);
50
- pendingQtsUpdates = new SortedLinkedList((a, b) => a.qtsBefore - b.qtsBefore);
51
- pendingQtsUpdatesPostponed = new SortedLinkedList((a, b) => a.qtsBefore - b.qtsBefore);
48
+ pendingUpdateContainers = new SortedArray([], (a, b) => a.seqStart - b.seqStart);
49
+ pendingPtsUpdates = new SortedArray([], (a, b) => a.ptsBefore - b.ptsBefore);
50
+ pendingPtsUpdatesPostponed = new SortedArray([], (a, b) => a.ptsBefore - b.ptsBefore);
51
+ pendingQtsUpdates = new SortedArray([], (a, b) => a.qtsBefore - b.qtsBefore);
52
+ pendingQtsUpdatesPostponed = new SortedArray([], (a, b) => a.qtsBefore - b.qtsBefore);
52
53
  pendingUnorderedUpdates = new Deque();
53
54
  noDispatchEnabled;
54
55
  // channel id or 0 => msg id
@@ -190,7 +191,7 @@ class UpdatesManager {
190
191
  case "updateShortChatMessage":
191
192
  case "updateShort":
192
193
  case "updateShortSentMessage":
193
- this.pendingUpdateContainers.add({
194
+ this.pendingUpdateContainers.insert({
194
195
  upd: update,
195
196
  seqStart: 0,
196
197
  seqEnd: 0
@@ -198,7 +199,7 @@ class UpdatesManager {
198
199
  break;
199
200
  case "updates":
200
201
  case "updatesCombined":
201
- this.pendingUpdateContainers.add({
202
+ this.pendingUpdateContainers.insert({
202
203
  upd: update,
203
204
  seqStart: update._ === "updatesCombined" ? update.seqStart : update.seq,
204
205
  seqEnd: update.seq
@@ -207,6 +208,9 @@ class UpdatesManager {
207
208
  default:
208
209
  assertNever();
209
210
  }
211
+ if (this.pendingUpdateContainers.length % WARN_EVERY === 0) {
212
+ this.log.warn("%d pending update containers, updatesLoopActive = %b. possible memory leak", this.pendingUpdateContainers.length, this.updatesLoopActive);
213
+ }
210
214
  this.updatesLoopCv.notify();
211
215
  }
212
216
  /**
@@ -769,7 +773,7 @@ class UpdatesManager {
769
773
  if (isMessageEmpty(upd)) return;
770
774
  const parsed = toPendingUpdate(upd, peers, true);
771
775
  if (parsed.channelId && parsed.ptsBefore) {
772
- pendingPtsUpdates.add(parsed);
776
+ pendingPtsUpdates.insert(parsed);
773
777
  } else {
774
778
  pendingUnorderedUpdates.pushBack(parsed);
775
779
  }
@@ -1061,9 +1065,9 @@ class UpdatesManager {
1061
1065
  }
1062
1066
  const parsed = toPendingUpdate(update, peers);
1063
1067
  if (parsed.ptsBefore !== void 0) {
1064
- pendingPtsUpdates.add(parsed);
1068
+ pendingPtsUpdates.insert(parsed);
1065
1069
  } else if (parsed.qtsBefore !== void 0) {
1066
- pendingQtsUpdates.add(parsed);
1070
+ pendingQtsUpdates.insert(parsed);
1067
1071
  } else {
1068
1072
  pendingUnorderedUpdates.pushBack(parsed);
1069
1073
  }
@@ -1078,9 +1082,9 @@ class UpdatesManager {
1078
1082
  log.debug("received short %s", upd._);
1079
1083
  const parsed = toPendingUpdate(upd.update, new PeersIndex());
1080
1084
  if (parsed.ptsBefore !== void 0) {
1081
- pendingPtsUpdates.add(parsed);
1085
+ pendingPtsUpdates.insert(parsed);
1082
1086
  } else if (parsed.qtsBefore !== void 0) {
1083
- pendingQtsUpdates.add(parsed);
1087
+ pendingQtsUpdates.insert(parsed);
1084
1088
  } else {
1085
1089
  pendingUnorderedUpdates.pushBack(parsed);
1086
1090
  }
@@ -1122,7 +1126,7 @@ class UpdatesManager {
1122
1126
  pts: upd.pts,
1123
1127
  ptsCount: upd.ptsCount
1124
1128
  };
1125
- pendingPtsUpdates.add({
1129
+ pendingPtsUpdates.insert({
1126
1130
  update,
1127
1131
  ptsBefore: upd.pts - upd.ptsCount,
1128
1132
  pts: upd.pts,
@@ -1162,7 +1166,7 @@ class UpdatesManager {
1162
1166
  pts: upd.pts,
1163
1167
  ptsCount: upd.ptsCount
1164
1168
  };
1165
- pendingPtsUpdates.add({
1169
+ pendingPtsUpdates.insert({
1166
1170
  update,
1167
1171
  ptsBefore: upd.pts - upd.ptsCount,
1168
1172
  pts: upd.pts,
@@ -1219,7 +1223,7 @@ class UpdatesManager {
1219
1223
  diff
1220
1224
  );
1221
1225
  pending.timeout = performance.now() + 500;
1222
- pendingPtsUpdatesPostponed.add(pending);
1226
+ pendingPtsUpdatesPostponed.insert(pending);
1223
1227
  postponedTimer.emitBefore(pending.timeout);
1224
1228
  } else if (diff > -1e6) {
1225
1229
  log.debug(
@@ -1258,8 +1262,8 @@ class UpdatesManager {
1258
1262
  await this._onUpdate(pending, requestedDiff);
1259
1263
  }
1260
1264
  this.log.debug("processing postponed pts-ordered updates");
1261
- for (let item = pendingPtsUpdatesPostponed._first; item; item = item.n) {
1262
- const pending = item.v;
1265
+ for (let i = 0; i < pendingPtsUpdatesPostponed.raw.length; i++) {
1266
+ const pending = pendingPtsUpdatesPostponed.raw[i];
1263
1267
  const upd = pending.update;
1264
1268
  let localPts;
1265
1269
  if (!pending.channelId) {
@@ -1283,7 +1287,8 @@ class UpdatesManager {
1283
1287
  localPts,
1284
1288
  pending.ptsBefore
1285
1289
  );
1286
- pendingPtsUpdatesPostponed._remove(item);
1290
+ pendingPtsUpdatesPostponed.removeIndex(i);
1291
+ i--;
1287
1292
  continue;
1288
1293
  }
1289
1294
  if (localPts < pending.ptsBefore) {
@@ -1305,7 +1310,8 @@ class UpdatesManager {
1305
1310
  localPts,
1306
1311
  pending.ptsBefore
1307
1312
  );
1308
- pendingPtsUpdatesPostponed._remove(item);
1313
+ pendingPtsUpdatesPostponed.removeIndex(i);
1314
+ i--;
1309
1315
  if (pending.channelId) {
1310
1316
  this._fetchChannelDifferenceLater(requestedDiff, pending.channelId);
1311
1317
  } else {
@@ -1315,7 +1321,8 @@ class UpdatesManager {
1315
1321
  continue;
1316
1322
  }
1317
1323
  await this._onUpdate(pending, requestedDiff, true);
1318
- pendingPtsUpdatesPostponed._remove(item);
1324
+ pendingPtsUpdatesPostponed.removeIndex(i);
1325
+ i--;
1319
1326
  }
1320
1327
  this.log.debug("processing pending qts-ordered updates");
1321
1328
  while (pendingQtsUpdates.length) {
@@ -1342,7 +1349,7 @@ class UpdatesManager {
1342
1349
  diff
1343
1350
  );
1344
1351
  pending.timeout = performance.now() + 500;
1345
- pendingQtsUpdatesPostponed.add(pending);
1352
+ pendingQtsUpdatesPostponed.insert(pending);
1346
1353
  postponedTimer.emitBefore(pending.timeout);
1347
1354
  } else {
1348
1355
  log.debug(
@@ -1362,8 +1369,8 @@ class UpdatesManager {
1362
1369
  await this._onUpdate(pending, requestedDiff);
1363
1370
  }
1364
1371
  this.log.debug("processing postponed qts-ordered updates");
1365
- for (let item = pendingQtsUpdatesPostponed._first; item; item = item.n) {
1366
- const pending = item.v;
1372
+ for (let i = 0; i < pendingQtsUpdatesPostponed.raw.length; i++) {
1373
+ const pending = pendingQtsUpdatesPostponed.raw[i];
1367
1374
  const upd = pending.update;
1368
1375
  if (this.qts > pending.qtsBefore) {
1369
1376
  log.debug(
@@ -1391,13 +1398,15 @@ class UpdatesManager {
1391
1398
  this.qts,
1392
1399
  pending.qtsBefore
1393
1400
  );
1394
- pendingQtsUpdatesPostponed._remove(item);
1401
+ pendingQtsUpdatesPostponed.removeIndex(i);
1402
+ i--;
1395
1403
  this._fetchDifferenceLater(requestedDiff);
1396
1404
  }
1397
1405
  continue;
1398
1406
  }
1399
1407
  await this._onUpdate(pending, requestedDiff, true);
1400
- pendingQtsUpdatesPostponed._remove(item);
1408
+ pendingQtsUpdatesPostponed.removeIndex(i);
1409
+ i--;
1401
1410
  }
1402
1411
  this.hasTimedoutPostponed = false;
1403
1412
  while (requestedDiff.size) {
@@ -1,6 +1,6 @@
1
1
  import { AsyncLock, ConditionVariable, Deque, timers } from '@fuman/utils';
2
2
  import { tl } from '@mtcute/tl';
3
- import { EarlyTimer, Logger, SortedLinkedList } from '../../utils/index.js';
3
+ import { EarlyTimer, Logger, SortedArray } from '../../utils/index.js';
4
4
  import { CurrentUserInfo } from '../storage/service/current-user.js';
5
5
  import { PeersIndex } from '../types/peers/peers-index.js';
6
6
  /** Information about a raw update. */
@@ -115,11 +115,11 @@ export interface UpdatesState {
115
115
  updatesLoopCv: ConditionVariable;
116
116
  postponedTimer: EarlyTimer;
117
117
  hasTimedoutPostponed: boolean;
118
- pendingUpdateContainers: SortedLinkedList<PendingUpdateContainer>;
119
- pendingPtsUpdates: SortedLinkedList<PendingUpdate>;
120
- pendingPtsUpdatesPostponed: SortedLinkedList<PendingUpdate>;
121
- pendingQtsUpdates: SortedLinkedList<PendingUpdate>;
122
- pendingQtsUpdatesPostponed: SortedLinkedList<PendingUpdate>;
118
+ pendingUpdateContainers: SortedArray<PendingUpdateContainer>;
119
+ pendingPtsUpdates: SortedArray<PendingUpdate>;
120
+ pendingPtsUpdatesPostponed: SortedArray<PendingUpdate>;
121
+ pendingQtsUpdates: SortedArray<PendingUpdate>;
122
+ pendingQtsUpdatesPostponed: SortedArray<PendingUpdate>;
123
123
  pendingUnorderedUpdates: Deque<PendingUpdate>;
124
124
  noDispatchEnabled: boolean;
125
125
  noDispatchMsg: Map<number, Set<number>>;
@@ -1,6 +1,6 @@
1
1
  import { AsyncLock, ConditionVariable, Deque, timers } from '@fuman/utils';
2
2
  import { tl } from '@mtcute/tl';
3
- import { EarlyTimer, Logger, SortedLinkedList } from '../../utils/index.js';
3
+ import { EarlyTimer, Logger, SortedArray } from '../../utils/index.js';
4
4
  import { CurrentUserInfo } from '../storage/service/current-user.js';
5
5
  import { PeersIndex } from '../types/peers/peers-index.js';
6
6
  /** Information about a raw update. */
@@ -115,11 +115,11 @@ export interface UpdatesState {
115
115
  updatesLoopCv: ConditionVariable;
116
116
  postponedTimer: EarlyTimer;
117
117
  hasTimedoutPostponed: boolean;
118
- pendingUpdateContainers: SortedLinkedList<PendingUpdateContainer>;
119
- pendingPtsUpdates: SortedLinkedList<PendingUpdate>;
120
- pendingPtsUpdatesPostponed: SortedLinkedList<PendingUpdate>;
121
- pendingQtsUpdates: SortedLinkedList<PendingUpdate>;
122
- pendingQtsUpdatesPostponed: SortedLinkedList<PendingUpdate>;
118
+ pendingUpdateContainers: SortedArray<PendingUpdateContainer>;
119
+ pendingPtsUpdates: SortedArray<PendingUpdate>;
120
+ pendingPtsUpdatesPostponed: SortedArray<PendingUpdate>;
121
+ pendingQtsUpdates: SortedArray<PendingUpdate>;
122
+ pendingQtsUpdatesPostponed: SortedArray<PendingUpdate>;
123
123
  pendingUnorderedUpdates: Deque<PendingUpdate>;
124
124
  noDispatchEnabled: boolean;
125
125
  noDispatchMsg: Map<number, Set<number>>;
@@ -25,6 +25,13 @@ function makeArrayPaginated(arr, total, next) {
25
25
  a.next = next;
26
26
  return a;
27
27
  }
28
+ function makeArrayPaginatedWithMeta(arr, total, meta, next) {
29
+ const a = arr;
30
+ a.total = total;
31
+ a.next = next;
32
+ Object.assign(a, meta);
33
+ return a;
34
+ }
28
35
  function normalizeDate(date) {
29
36
  return date ? ~~((typeof date === "number" ? date : date.getTime()) / 1e3) : void 0;
30
37
  }
@@ -33,6 +40,7 @@ function normalizeMessageId(msg) {
33
40
  return typeof msg === "number" ? msg : msg.id;
34
41
  }
35
42
  exports.makeArrayPaginated = makeArrayPaginated;
43
+ exports.makeArrayPaginatedWithMeta = makeArrayPaginatedWithMeta;
36
44
  exports.makeArrayWithTotal = makeArrayWithTotal;
37
45
  exports.normalizeDate = normalizeDate;
38
46
  exports.normalizeMessageId = normalizeMessageId;
@@ -1,4 +1,4 @@
1
- import { ArrayPaginated, ArrayWithTotal, MaybeDynamic, Message } from '../types/index.js';
1
+ import { ArrayPaginated, ArrayPaginatedWithMeta, ArrayWithTotal, MaybeDynamic, Message } from '../types/index.js';
2
2
  /**
3
3
  * Normalize phone number by stripping formatting
4
4
  * @param phone Phone number
@@ -7,6 +7,7 @@ export declare function normalizePhoneNumber(phone: string): string;
7
7
  export declare function resolveMaybeDynamic<T>(val: MaybeDynamic<T>): Promise<T>;
8
8
  export declare function makeArrayWithTotal<T>(arr: T[], total: number): ArrayWithTotal<T>;
9
9
  export declare function makeArrayPaginated<T, Offset>(arr: T[], total: number, next?: Offset): ArrayPaginated<T, Offset>;
10
+ export declare function makeArrayPaginatedWithMeta<T, Offset, Meta>(arr: T[], total: number, meta: Meta, next?: Offset): ArrayPaginatedWithMeta<T, Offset, Meta>;
10
11
  export declare function normalizeDate(date: Date | number): number;
11
12
  export declare function normalizeDate(date: Date | number | undefined): number | undefined;
12
13
  export declare function normalizeMessageId(msg: Message | number | undefined): number | undefined;
@@ -1,4 +1,4 @@
1
- import { ArrayPaginated, ArrayWithTotal, MaybeDynamic, Message } from '../types/index.js';
1
+ import { ArrayPaginated, ArrayPaginatedWithMeta, ArrayWithTotal, MaybeDynamic, Message } from '../types/index.js';
2
2
  /**
3
3
  * Normalize phone number by stripping formatting
4
4
  * @param phone Phone number
@@ -7,6 +7,7 @@ export declare function normalizePhoneNumber(phone: string): string;
7
7
  export declare function resolveMaybeDynamic<T>(val: MaybeDynamic<T>): Promise<T>;
8
8
  export declare function makeArrayWithTotal<T>(arr: T[], total: number): ArrayWithTotal<T>;
9
9
  export declare function makeArrayPaginated<T, Offset>(arr: T[], total: number, next?: Offset): ArrayPaginated<T, Offset>;
10
+ export declare function makeArrayPaginatedWithMeta<T, Offset, Meta>(arr: T[], total: number, meta: Meta, next?: Offset): ArrayPaginatedWithMeta<T, Offset, Meta>;
10
11
  export declare function normalizeDate(date: Date | number): number;
11
12
  export declare function normalizeDate(date: Date | number | undefined): number | undefined;
12
13
  export declare function normalizeMessageId(msg: Message | number | undefined): number | undefined;
@@ -18,6 +18,13 @@ function makeArrayPaginated(arr, total, next) {
18
18
  a.next = next;
19
19
  return a;
20
20
  }
21
+ function makeArrayPaginatedWithMeta(arr, total, meta, next) {
22
+ const a = arr;
23
+ a.total = total;
24
+ a.next = next;
25
+ Object.assign(a, meta);
26
+ return a;
27
+ }
21
28
  function normalizeDate(date) {
22
29
  return date ? ~~((typeof date === "number" ? date : date.getTime()) / 1e3) : void 0;
23
30
  }
@@ -27,6 +34,7 @@ function normalizeMessageId(msg) {
27
34
  }
28
35
  export {
29
36
  makeArrayPaginated,
37
+ makeArrayPaginatedWithMeta,
30
38
  makeArrayWithTotal,
31
39
  normalizeDate,
32
40
  normalizeMessageId,
@@ -26,7 +26,8 @@ class TelegramWorkerPort {
26
26
  const bind = this._invoker.makeBinder("client");
27
27
  this.prepare = bind("prepare");
28
28
  this._connect = bind("connect");
29
- this.close = bind("close");
29
+ this.disconnect = bind("disconnect");
30
+ this.destroy_ = bind("destroy");
30
31
  this.notifyLoggedIn = bind("notifyLoggedIn");
31
32
  this.notifyLoggedOut = bind("notifyLoggedOut");
32
33
  this.notifyChannelOpened = bind("notifyChannelOpened");
@@ -60,7 +61,8 @@ class TelegramWorkerPort {
60
61
  // bound methods
61
62
  prepare;
62
63
  _connect;
63
- close;
64
+ disconnect;
65
+ destroy_;
64
66
  notifyLoggedIn;
65
67
  notifyLoggedOut;
66
68
  notifyChannelOpened;
@@ -120,14 +122,14 @@ class TelegramWorkerPort {
120
122
  }
121
123
  };
122
124
  _destroyed = false;
123
- destroy(terminate = false) {
125
+ async destroy(terminate = false) {
124
126
  if (this._destroyed) return;
127
+ await this.destroy_();
125
128
  this.timers.destroy();
126
129
  this._connection[1]();
127
130
  this._destroyed = true;
128
131
  if (terminate && "terminate" in this.options.worker) {
129
- Promise.resolve(this.options.worker.terminate()).catch(() => {
130
- });
132
+ await Promise.resolve(this.options.worker.terminate());
131
133
  }
132
134
  }
133
135
  invokeCustom(method, ...args) {
@@ -25,7 +25,8 @@ export declare abstract class TelegramWorkerPort<Custom extends WorkerCustomMeth
25
25
  readonly timers: TimersManager;
26
26
  readonly prepare: ITelegramClient['prepare'];
27
27
  private _connect;
28
- readonly close: ITelegramClient['close'];
28
+ readonly disconnect: ITelegramClient['disconnect'];
29
+ readonly destroy_: ITelegramClient['destroy'];
29
30
  readonly notifyLoggedIn: ITelegramClient['notifyLoggedIn'];
30
31
  readonly notifyLoggedOut: ITelegramClient['notifyLoggedOut'];
31
32
  readonly notifyChannelOpened: ITelegramClient['notifyChannelOpened'];
@@ -54,7 +55,7 @@ export declare abstract class TelegramWorkerPort<Custom extends WorkerCustomMeth
54
55
  onError: Emitter<Error>;
55
56
  private _onMessage;
56
57
  private _destroyed;
57
- destroy(terminate?: boolean): void;
58
+ destroy(terminate?: boolean): Promise<void>;
58
59
  invokeCustom<T extends keyof Custom>(method: T, ...args: Parameters<Custom[T]>): Promise<ReturnType<Custom[T]>>;
59
60
  connect(): Promise<void>;
60
61
  }
@@ -25,7 +25,8 @@ export declare abstract class TelegramWorkerPort<Custom extends WorkerCustomMeth
25
25
  readonly timers: TimersManager;
26
26
  readonly prepare: ITelegramClient['prepare'];
27
27
  private _connect;
28
- readonly close: ITelegramClient['close'];
28
+ readonly disconnect: ITelegramClient['disconnect'];
29
+ readonly destroy_: ITelegramClient['destroy'];
29
30
  readonly notifyLoggedIn: ITelegramClient['notifyLoggedIn'];
30
31
  readonly notifyLoggedOut: ITelegramClient['notifyLoggedOut'];
31
32
  readonly notifyChannelOpened: ITelegramClient['notifyChannelOpened'];
@@ -54,7 +55,7 @@ export declare abstract class TelegramWorkerPort<Custom extends WorkerCustomMeth
54
55
  onError: Emitter<Error>;
55
56
  private _onMessage;
56
57
  private _destroyed;
57
- destroy(terminate?: boolean): void;
58
+ destroy(terminate?: boolean): Promise<void>;
58
59
  invokeCustom<T extends keyof Custom>(method: T, ...args: Parameters<Custom[T]>): Promise<ReturnType<Custom[T]>>;
59
60
  connect(): Promise<void>;
60
61
  }