@agentunion/fastaun-browser 0.5.11 → 0.5.12
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.
- package/CHANGELOG.md +30 -0
- package/_packed_docs/CHANGELOG.md +30 -0
- package/_packed_docs/INDEX.md +2 -2
- package/_packed_docs/KITE_DOCS_GUIDE.md +1 -1
- package/_packed_docs/protocol/10-Group-/345/255/220/345/215/217/350/256/256.md +21 -3
- package/_packed_docs/sdk/09-group-rpc-manual.md +29 -2
- package/dist/bundle.js +559 -295
- package/dist/client/delivery.d.ts +1 -0
- package/dist/client/delivery.d.ts.map +1 -1
- package/dist/client/delivery.js +161 -242
- package/dist/client/delivery.js.map +1 -1
- package/dist/client/group-state.d.ts.map +1 -1
- package/dist/client/group-state.js +1 -0
- package/dist/client/group-state.js.map +1 -1
- package/dist/client/rpc-pipeline.d.ts.map +1 -1
- package/dist/client/rpc-pipeline.js +24 -11
- package/dist/client/rpc-pipeline.js.map +1 -1
- package/dist/client/v2-e2ee.d.ts +0 -1
- package/dist/client/v2-e2ee.d.ts.map +1 -1
- package/dist/client/v2-e2ee.js +65 -44
- package/dist/client/v2-e2ee.js.map +1 -1
- package/dist/client.d.ts +14 -0
- package/dist/client.d.ts.map +1 -1
- package/dist/client.js +341 -18
- package/dist/client.js.map +1 -1
- package/dist/facades.d.ts +7 -0
- package/dist/facades.d.ts.map +1 -1
- package/dist/facades.js +44 -0
- package/dist/facades.js.map +1 -1
- package/dist/seq-tracker.d.ts +2 -2
- package/dist/seq-tracker.d.ts.map +1 -1
- package/dist/seq-tracker.js +11 -7
- package/dist/seq-tracker.js.map +1 -1
- package/dist/tools/cross-sdk-agent.js +50 -12
- package/dist/tools/cross-sdk-agent.js.map +1 -1
- package/dist/transport.d.ts.map +1 -1
- package/dist/transport.js +3 -0
- package/dist/transport.js.map +1 -1
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/package.json +1 -1
package/dist/client/delivery.js
CHANGED
|
@@ -58,6 +58,10 @@ function positiveSafeSequenceHint(value) {
|
|
|
58
58
|
const parsed = Number(value);
|
|
59
59
|
return Number.isSafeInteger(parsed) && parsed > 0 ? parsed : 0;
|
|
60
60
|
}
|
|
61
|
+
function hasNonEmptyInlineMessage(value) {
|
|
62
|
+
return isJsonObject(value)
|
|
63
|
+
&& Object.keys(value).length > 0;
|
|
64
|
+
}
|
|
61
65
|
function nonNegativeSafeSequenceHint(value) {
|
|
62
66
|
if (typeof value !== 'number' || !Number.isSafeInteger(value) || value < 0)
|
|
63
67
|
return null;
|
|
@@ -981,14 +985,22 @@ export class MessageDeliveryEngine {
|
|
|
981
985
|
publishedCount += 1;
|
|
982
986
|
}
|
|
983
987
|
}
|
|
988
|
+
else if (this.isSelfSentGroupMessage(message)) {
|
|
989
|
+
this.markPublishedSeq(ns, seq);
|
|
990
|
+
}
|
|
984
991
|
else if (await this.publishPulledMessage('group.message_created', ns, seq, message, false)) {
|
|
985
992
|
this.ensurePullOperationCurrent();
|
|
986
993
|
publishedCount += 1;
|
|
987
994
|
}
|
|
988
995
|
}
|
|
989
996
|
this.ensurePullOperationCurrent();
|
|
990
|
-
|
|
997
|
+
const contiguousSeq = Number.isSafeInteger(result.contiguous_seq)
|
|
998
|
+
? result.contiguous_seq
|
|
999
|
+
: undefined;
|
|
1000
|
+
if (contiguousSeq === undefined)
|
|
991
1001
|
client._seqTracker.onPullResult(ns, messages, afterSeq);
|
|
1002
|
+
else
|
|
1003
|
+
client._seqTracker.onPullResult(ns, messages, afterSeq, contiguousSeq);
|
|
992
1004
|
const commitTarget = Math.max(client._seqTracker.getContiguousSeq(ns), retentionFloor, visibilityFloor, deferredServerCursor);
|
|
993
1005
|
if (commitTarget > client._seqTracker.getContiguousSeq(ns)) {
|
|
994
1006
|
client._seqTracker.forceContiguousSeq(ns, commitTarget);
|
|
@@ -1536,11 +1548,7 @@ export class MessageDeliveryEngine {
|
|
|
1536
1548
|
return true;
|
|
1537
1549
|
}
|
|
1538
1550
|
async onRawGroupMessageRecalled(data) {
|
|
1539
|
-
//
|
|
1540
|
-
// tombstone 的 notice_seq;必须像普通群消息 push 一样推进 seqTracker + markPublished +
|
|
1541
|
-
// auto-ack,否则该 seq 在本地 contiguous 序列留洞,后续 pull/reconnect 会重复拉到并
|
|
1542
|
-
// 重复处理。publishGroupRecallTombstone 内部再按 (group_id, message_ids) 去重,
|
|
1543
|
-
// 确保应用层只回调一次。
|
|
1551
|
+
// 非 inline push 仅作为实时通知,不推进 seqTracker/cursor/ACK。
|
|
1544
1552
|
const client = this.runtime.client;
|
|
1545
1553
|
if (!isJsonObject(data))
|
|
1546
1554
|
return;
|
|
@@ -1571,39 +1579,11 @@ export class MessageDeliveryEngine {
|
|
|
1571
1579
|
return;
|
|
1572
1580
|
}
|
|
1573
1581
|
const ns = `group:${groupId}`;
|
|
1574
|
-
|
|
1575
|
-
|
|
1576
|
-
|
|
1577
|
-
|
|
1578
|
-
await this.publishGroupRecallTombstone(groupId, seq, wrapped);
|
|
1579
|
-
return;
|
|
1580
|
-
}
|
|
1581
|
-
client._repairPushContiguousBound(ns, seqNum, true, '_raw.group.message_recalled');
|
|
1582
|
-
}
|
|
1583
|
-
// 该 notice_seq 已由 pull 路径处理过(已发布或挂起待发布)时,去重发布兜底后返回。
|
|
1584
|
-
const pushed = client._pushedSeqs.get(ns);
|
|
1585
|
-
const pending = client._pendingOrderedMsgs.get(ns);
|
|
1586
|
-
if (pushed?.has(seqNum) || pending?.has(seqNum)) {
|
|
1587
|
-
await this.publishGroupRecallTombstone(groupId, seq, wrapped);
|
|
1588
|
-
return;
|
|
1589
|
-
}
|
|
1590
|
-
const contigBefore = client._seqTracker.getContiguousSeq(ns);
|
|
1591
|
-
client._seqTracker.onMessageSeq(ns, seqNum);
|
|
1582
|
+
client._seqTracker.updateMaxSeen(ns, seqNum);
|
|
1583
|
+
if (seqNum > client._seqTracker.getContiguousSeq(ns)
|
|
1584
|
+
&& client._sessionOptions?.background_sync !== false)
|
|
1585
|
+
client._safeAsync(this.fillGroupGap(groupId));
|
|
1592
1586
|
await this.publishGroupRecallTombstone(groupId, seq, wrapped);
|
|
1593
|
-
this.markPublishedSeq(ns, seqNum);
|
|
1594
|
-
const contig = client._seqTracker.getContiguousSeq(ns);
|
|
1595
|
-
if (contig > 0) {
|
|
1596
|
-
const ackSeq = this.clampAckSeq('group.ack_messages', 'msg_seq', ns, contig);
|
|
1597
|
-
client._transport.call('group.ack_messages', {
|
|
1598
|
-
group_id: groupId,
|
|
1599
|
-
msg_seq: ackSeq,
|
|
1600
|
-
device_id: client._deviceId,
|
|
1601
|
-
slot_id: client._slotId,
|
|
1602
|
-
_rpc_background: true,
|
|
1603
|
-
}).catch((e) => { client._clientLog.warn('group recall auto-ack failed: group=' + groupId, e); });
|
|
1604
|
-
}
|
|
1605
|
-
if (contig !== contigBefore)
|
|
1606
|
-
this.persistSeq(ns);
|
|
1607
1587
|
}
|
|
1608
1588
|
async publishAppEvent(event, payload, source = 'direct', ns = '', batch) {
|
|
1609
1589
|
const client = this.runtime.client;
|
|
@@ -1684,6 +1664,21 @@ export class MessageDeliveryEngine {
|
|
|
1684
1664
|
}
|
|
1685
1665
|
return true;
|
|
1686
1666
|
}
|
|
1667
|
+
isSelfSentGroupMessage(message) {
|
|
1668
|
+
if (!isJsonObject(message))
|
|
1669
|
+
return false;
|
|
1670
|
+
const client = this.runtime.client;
|
|
1671
|
+
const selfAid = String(client._aid ?? '').trim().toLowerCase();
|
|
1672
|
+
const senderAid = String(message.sender_aid ?? message.from_aid ?? message.from ?? '').trim().toLowerCase();
|
|
1673
|
+
if (!selfAid || senderAid !== selfAid)
|
|
1674
|
+
return false;
|
|
1675
|
+
const senderDevice = Object.prototype.hasOwnProperty.call(message, 'sender_device_id')
|
|
1676
|
+
? message.sender_device_id
|
|
1677
|
+
: message.from_device_id;
|
|
1678
|
+
if (typeof senderDevice !== 'string' || !senderDevice.trim() || !String(client._deviceId ?? '').trim())
|
|
1679
|
+
return false;
|
|
1680
|
+
return senderDevice.trim() === String(client._deviceId).trim();
|
|
1681
|
+
}
|
|
1687
1682
|
strictTargetString(source, key) {
|
|
1688
1683
|
if (!Object.prototype.hasOwnProperty.call(source, key)) {
|
|
1689
1684
|
return { present: false, valid: false, value: '' };
|
|
@@ -1753,13 +1748,12 @@ export class MessageDeliveryEngine {
|
|
|
1753
1748
|
const ns = isJsonObject(data) && client._aid && data.seq !== undefined
|
|
1754
1749
|
? `p2p:${client._aid}`
|
|
1755
1750
|
: '';
|
|
1756
|
-
const seq = isJsonObject(data)
|
|
1757
|
-
if (client._v2Session && ns &&
|
|
1758
|
-
&& this.messageTargetsCurrentInstance(data)) {
|
|
1751
|
+
const seq = isJsonObject(data) ? positiveSafeSequenceHint(data.seq) : 0;
|
|
1752
|
+
if (client._v2Session && ns && seq > 0 && this.messageTargetsCurrentInstance(data)) {
|
|
1759
1753
|
client._seqTracker.updateMaxSeen(ns, seq);
|
|
1760
1754
|
}
|
|
1761
1755
|
const hasInlineObject = isJsonObject(data)
|
|
1762
|
-
&&
|
|
1756
|
+
&& hasNonEmptyInlineMessage(data.inline_message);
|
|
1763
1757
|
const inlineGeneration = hasInlineObject ? this.captureInlineGeneration() : undefined;
|
|
1764
1758
|
const operation = () => this.processAndPublishMessage(data, inlineGeneration);
|
|
1765
1759
|
client._safeAsync(client._v2Session && ns && !hasInlineObject
|
|
@@ -1776,33 +1770,15 @@ export class MessageDeliveryEngine {
|
|
|
1776
1770
|
msg.type = 'message.recalled';
|
|
1777
1771
|
if (!this.messageTargetsCurrentInstance(msg))
|
|
1778
1772
|
return;
|
|
1779
|
-
const seq = msg.seq;
|
|
1780
|
-
if (
|
|
1773
|
+
const seq = positiveSafeSequenceHint(msg.seq);
|
|
1774
|
+
if (client._aid && seq > 0) {
|
|
1781
1775
|
const ns = `p2p:${client._aid}`;
|
|
1782
|
-
|
|
1783
|
-
|
|
1784
|
-
|
|
1785
|
-
const seqNeedsPull = client._seqTracker.onMessageSeq(ns, seq);
|
|
1786
|
-
const published = await this.publishOrderedMessage('message.recalled', ns, seq, msg);
|
|
1787
|
-
const contigAfter = client._seqTracker.getContiguousSeq(ns);
|
|
1788
|
-
if (seqNeedsPull && !published && client._sessionOptions?.background_sync !== false) {
|
|
1776
|
+
client._seqTracker.updateMaxSeen(ns, seq);
|
|
1777
|
+
if (seq > client._seqTracker.getContiguousSeq(ns)
|
|
1778
|
+
&& client._sessionOptions?.background_sync !== false)
|
|
1789
1779
|
client._safeAsync(this.fillP2pGap());
|
|
1790
|
-
}
|
|
1791
|
-
const contig = client._seqTracker.getContiguousSeq(ns);
|
|
1792
|
-
if (contig > 0) {
|
|
1793
|
-
const ackSeq = this.clampAckSeq('message.ack', 'seq', ns, contig);
|
|
1794
|
-
client._transport.call('message.ack', {
|
|
1795
|
-
seq: ackSeq,
|
|
1796
|
-
device_id: client._deviceId,
|
|
1797
|
-
slot_id: client._slotId,
|
|
1798
|
-
_rpc_background: true,
|
|
1799
|
-
}).catch((e) => { client._clientLog.warn(`P2P recall auto-ack failed:${String(e)}`); });
|
|
1800
|
-
}
|
|
1801
|
-
if (contigAfter !== contigBefore)
|
|
1802
|
-
this.persistSeq(ns);
|
|
1803
|
-
return;
|
|
1804
1780
|
}
|
|
1805
|
-
await this.publishMessageRecallTombstone(seq, msg);
|
|
1781
|
+
await this.publishMessageRecallTombstone(msg.seq, msg);
|
|
1806
1782
|
}
|
|
1807
1783
|
async processAndPublishMessage(data, inlineGeneration) {
|
|
1808
1784
|
const client = this.runtime.client;
|
|
@@ -1819,47 +1795,36 @@ export class MessageDeliveryEngine {
|
|
|
1819
1795
|
// 新服务端为兼容旧 SDK 仍可能发送 message.received;V2 会话下必须
|
|
1820
1796
|
// 在旧 seq tracking / ordered publish 之前转入前台 Tail 协调器。
|
|
1821
1797
|
const legacyPushSeq = positiveSafeSequenceHint(msg.seq);
|
|
1822
|
-
const hasInlineField =
|
|
1798
|
+
const hasInlineField = hasNonEmptyInlineMessage(msg.inline_message);
|
|
1823
1799
|
if (client._v2Session && client._aid && (legacyPushSeq > 0 || hasInlineField)) {
|
|
1824
1800
|
await this.processV2P2PNotification(msg, 'v1', inlineGeneration);
|
|
1825
1801
|
return;
|
|
1826
1802
|
}
|
|
1803
|
+
if (client._aid && legacyPushSeq > 0) {
|
|
1804
|
+
const ns = `p2p:${client._aid}`;
|
|
1805
|
+
client._seqTracker.updateMaxSeen(ns, legacyPushSeq);
|
|
1806
|
+
if (client._sessionOptions?.background_sync !== false)
|
|
1807
|
+
client._safeAsync(this.fillP2pGap());
|
|
1808
|
+
return;
|
|
1809
|
+
}
|
|
1827
1810
|
const seq = msg.seq;
|
|
1828
1811
|
const encryptedPush = client._isEncryptedPushMessage(msg);
|
|
1829
|
-
|
|
1830
|
-
|
|
1831
|
-
|
|
1832
|
-
|
|
1833
|
-
|
|
1834
|
-
|
|
1835
|
-
const published = encryptedPush
|
|
1836
|
-
? await client._publishEncryptedPushMessage('message.received', 'message.undecryptable', ns, seq, msg, false)
|
|
1837
|
-
: await this.publishOrderedMessage('message.received', ns, seq, msg);
|
|
1838
|
-
const contigAfter = client._seqTracker.getContiguousSeq(ns);
|
|
1839
|
-
const needPull = seqNeedsPull && !published;
|
|
1840
|
-
if (needPull && client._sessionOptions?.background_sync !== false) {
|
|
1812
|
+
const ns = client._aid ? `p2p:${client._aid}` : '';
|
|
1813
|
+
const seqNum = positiveSafeSequenceHint(seq);
|
|
1814
|
+
if (ns && seqNum > 0) {
|
|
1815
|
+
client._seqTracker.updateMaxSeen(ns, seqNum);
|
|
1816
|
+
if (seqNum > client._seqTracker.getContiguousSeq(ns)
|
|
1817
|
+
&& client._sessionOptions?.background_sync !== false)
|
|
1841
1818
|
client._safeAsync(this.fillP2pGap());
|
|
1842
|
-
|
|
1843
|
-
|
|
1844
|
-
|
|
1845
|
-
|
|
1846
|
-
|
|
1847
|
-
|
|
1848
|
-
|
|
1849
|
-
slot_id: client._slotId,
|
|
1850
|
-
_rpc_background: true,
|
|
1851
|
-
}).catch((e) => { client._clientLog.warn(`P2P auto-ack failed:${String(e)}`); });
|
|
1852
|
-
}
|
|
1853
|
-
if (contigAfter !== contigBefore)
|
|
1854
|
-
this.persistSeq(ns);
|
|
1855
|
-
if (encryptedPush)
|
|
1856
|
-
return;
|
|
1819
|
+
}
|
|
1820
|
+
if (encryptedPush) {
|
|
1821
|
+
await client._publishEncryptedPushMessage('message.received', 'message.undecryptable', ns, seq ?? 0, msg, false);
|
|
1822
|
+
return;
|
|
1823
|
+
}
|
|
1824
|
+
if (ns && seq !== undefined && seq !== null) {
|
|
1825
|
+
await this.publishOrderedMessage('message.received', ns, seq, msg);
|
|
1857
1826
|
}
|
|
1858
1827
|
else {
|
|
1859
|
-
if (encryptedPush) {
|
|
1860
|
-
await client._publishEncryptedPushMessage('message.received', 'message.undecryptable', '', seq ?? 0, msg, false);
|
|
1861
|
-
return;
|
|
1862
|
-
}
|
|
1863
1828
|
await client._publishAppEvent('message.received', msg, 'push');
|
|
1864
1829
|
}
|
|
1865
1830
|
}
|
|
@@ -1884,15 +1849,14 @@ export class MessageDeliveryEngine {
|
|
|
1884
1849
|
const client = this.runtime.client;
|
|
1885
1850
|
client._clientLog.debug(`_onRawGroupMessageCreated enter: group_id=${data?.group_id ?? '-'} from=${data?.from ?? '-'} seq=${data?.seq ?? '-'}`);
|
|
1886
1851
|
const groupId = isJsonObject(data) && typeof data.group_id === 'string' ? data.group_id.trim() : '';
|
|
1887
|
-
const seq = isJsonObject(data) && typeof data.seq === 'number' ? data.seq : 0;
|
|
1888
1852
|
const kind = isJsonObject(data) ? String(data.kind ?? '').trim() : '';
|
|
1889
|
-
if (client._v2Session && groupId && kind !== 'group.online_unread_hint'
|
|
1890
|
-
&& Number.isSafeInteger(seq) && seq > 0) {
|
|
1891
|
-
client._seqTracker.updateMaxSeen(`group:${groupId}`, seq);
|
|
1892
|
-
}
|
|
1893
1853
|
const ns = groupId ? `group:${groupId}` : '';
|
|
1854
|
+
const seq = isJsonObject(data) ? positiveSafeSequenceHint(data.seq) : 0;
|
|
1855
|
+
if (client._v2Session && ns && kind !== 'group.online_unread_hint' && seq > 0) {
|
|
1856
|
+
client._seqTracker.updateMaxSeen(ns, seq);
|
|
1857
|
+
}
|
|
1894
1858
|
const hasInlineObject = isJsonObject(data)
|
|
1895
|
-
&&
|
|
1859
|
+
&& hasNonEmptyInlineMessage(data.inline_message);
|
|
1896
1860
|
const inlineGeneration = hasInlineObject ? this.captureInlineGeneration() : undefined;
|
|
1897
1861
|
const operation = () => this.processAndPublishGroupMessage(data, inlineGeneration);
|
|
1898
1862
|
client._safeAsync(client._v2Session && ns && !hasInlineObject
|
|
@@ -1917,74 +1881,61 @@ export class MessageDeliveryEngine {
|
|
|
1917
1881
|
// V2 会话中旧 group.message_created 也只是 Head 通知;必须先 Tail,
|
|
1918
1882
|
// 不能让 payload 路径直接推进旧 ordered publish 状态。
|
|
1919
1883
|
const legacyPushSeq = positiveSafeSequenceHint(seq);
|
|
1920
|
-
const hasInlineField =
|
|
1884
|
+
const hasInlineField = hasNonEmptyInlineMessage(msg.inline_message);
|
|
1921
1885
|
if (client._v2Session && groupId && (legacyPushSeq > 0 || hasInlineField)) {
|
|
1922
1886
|
await this.processGroupV2MessageCreated(msg, 'v1', inlineGeneration);
|
|
1923
1887
|
return;
|
|
1924
1888
|
}
|
|
1889
|
+
if (groupId && legacyPushSeq > 0) {
|
|
1890
|
+
const ns = `group:${groupId}`;
|
|
1891
|
+
client._seqTracker.updateMaxSeen(ns, legacyPushSeq);
|
|
1892
|
+
if (client._sessionOptions?.background_sync !== false)
|
|
1893
|
+
client._safeAsync(this.fillGroupGap(groupId));
|
|
1894
|
+
return;
|
|
1895
|
+
}
|
|
1925
1896
|
if (payload === undefined || payload === null
|
|
1926
1897
|
|| (typeof payload === 'object' && Object.keys(payload).length === 0)) {
|
|
1927
|
-
|
|
1898
|
+
if (client._v2Session)
|
|
1899
|
+
await this.autoPullGroupMessages(msg);
|
|
1900
|
+
else if (groupId && seq !== undefined && seq !== null) {
|
|
1901
|
+
const ns = `group:${groupId}`;
|
|
1902
|
+
const seqNum = positiveSafeSequenceHint(seq);
|
|
1903
|
+
if (seqNum > 0) {
|
|
1904
|
+
client._seqTracker.updateMaxSeen(ns, seqNum);
|
|
1905
|
+
if (seqNum > client._seqTracker.getContiguousSeq(ns)
|
|
1906
|
+
&& client._sessionOptions?.background_sync !== false)
|
|
1907
|
+
client._safeAsync(this.fillGroupGap(groupId));
|
|
1908
|
+
}
|
|
1909
|
+
await this.publishOrderedMessage('group.message_created', ns, seq, msg);
|
|
1910
|
+
}
|
|
1911
|
+
else
|
|
1912
|
+
await client._publishAppEvent('group.message_created', msg, 'push');
|
|
1928
1913
|
return;
|
|
1929
1914
|
}
|
|
1930
1915
|
const encryptedPush = client._isEncryptedPushMessage(msg);
|
|
1931
|
-
|
|
1932
|
-
|
|
1933
|
-
|
|
1934
|
-
|
|
1935
|
-
|
|
1936
|
-
|
|
1937
|
-
// 群撤回 tombstone(占位 / 通知):归一化为 group.message_recalled,仍占 seq。
|
|
1938
|
-
if (!encryptedPush && this.recallEventFromGroupMessage(msg)) {
|
|
1939
|
-
await this.publishGroupRecallTombstone(groupId, seq, msg);
|
|
1940
|
-
this.markPublishedSeq(ns, Number(seq));
|
|
1941
|
-
const contigAfter = client._seqTracker.getContiguousSeq(ns);
|
|
1942
|
-
const contig = client._seqTracker.getContiguousSeq(ns);
|
|
1943
|
-
if (contig > 0) {
|
|
1944
|
-
const ackSeq = this.clampAckSeq('group.ack_messages', 'msg_seq', ns, contig);
|
|
1945
|
-
client._transport.call('group.ack_messages', {
|
|
1946
|
-
group_id: groupId,
|
|
1947
|
-
msg_seq: ackSeq,
|
|
1948
|
-
device_id: client._deviceId,
|
|
1949
|
-
slot_id: client._slotId,
|
|
1950
|
-
_rpc_background: true,
|
|
1951
|
-
}).catch((e) => { client._clientLog.warn('group recall auto-ack failed: group=' + groupId, e); });
|
|
1952
|
-
}
|
|
1953
|
-
if (contigAfter !== contigBefore)
|
|
1954
|
-
this.persistSeq(ns);
|
|
1955
|
-
return;
|
|
1956
|
-
}
|
|
1957
|
-
const published = encryptedPush
|
|
1958
|
-
? await client._publishEncryptedPushMessage('group.message_created', 'group.message_undecryptable', ns, seq, msg, true)
|
|
1959
|
-
: await this.publishOrderedMessage('group.message_created', ns, seq, msg);
|
|
1960
|
-
const contigAfter = client._seqTracker.getContiguousSeq(ns);
|
|
1961
|
-
const needPull = seqNeedsPull && !published;
|
|
1962
|
-
if (needPull && client._sessionOptions?.background_sync !== false) {
|
|
1916
|
+
const ns = groupId ? `group:${groupId}` : '';
|
|
1917
|
+
const seqNum = positiveSafeSequenceHint(seq);
|
|
1918
|
+
if (ns && seqNum > 0) {
|
|
1919
|
+
client._seqTracker.updateMaxSeen(ns, seqNum);
|
|
1920
|
+
if (seqNum > client._seqTracker.getContiguousSeq(ns)
|
|
1921
|
+
&& client._sessionOptions?.background_sync !== false)
|
|
1963
1922
|
client._safeAsync(this.fillGroupGap(groupId));
|
|
1964
|
-
}
|
|
1965
|
-
const contig = client._seqTracker.getContiguousSeq(ns);
|
|
1966
|
-
if (contig > 0) {
|
|
1967
|
-
const ackSeq = this.clampAckSeq('group.ack_messages', 'msg_seq', ns, contig);
|
|
1968
|
-
client._transport.call('group.ack_messages', {
|
|
1969
|
-
group_id: groupId,
|
|
1970
|
-
msg_seq: ackSeq,
|
|
1971
|
-
device_id: client._deviceId,
|
|
1972
|
-
slot_id: client._slotId,
|
|
1973
|
-
_rpc_background: true,
|
|
1974
|
-
}).catch((e) => { client._clientLog.warn('group message auto-ack failed: group=' + groupId, e); });
|
|
1975
|
-
}
|
|
1976
|
-
if (contigAfter !== contigBefore)
|
|
1977
|
-
this.persistSeq(ns);
|
|
1978
|
-
if (encryptedPush)
|
|
1979
|
-
return;
|
|
1980
1923
|
}
|
|
1981
|
-
|
|
1982
|
-
|
|
1983
|
-
|
|
1984
|
-
|
|
1985
|
-
|
|
1986
|
-
|
|
1924
|
+
if (this.isSelfSentGroupMessage(msg))
|
|
1925
|
+
return;
|
|
1926
|
+
if (!encryptedPush && this.recallEventFromGroupMessage(msg)) {
|
|
1927
|
+
await this.publishGroupRecallTombstone(groupId, seq, msg);
|
|
1928
|
+
return;
|
|
1929
|
+
}
|
|
1930
|
+
if (encryptedPush) {
|
|
1931
|
+
await client._publishEncryptedPushMessage('group.message_created', 'group.message_undecryptable', ns, seq ?? 0, msg, true);
|
|
1932
|
+
return;
|
|
1933
|
+
}
|
|
1934
|
+
if (ns && seq !== undefined && seq !== null) {
|
|
1935
|
+
await this.publishOrderedMessage('group.message_created', ns, seq, msg);
|
|
1987
1936
|
}
|
|
1937
|
+
else
|
|
1938
|
+
await client._publishAppEvent('group.message_created', msg, 'push');
|
|
1988
1939
|
}
|
|
1989
1940
|
catch (exc) {
|
|
1990
1941
|
client._clientLog.warn(`group push processing failed:${String(exc)}`);
|
|
@@ -2192,6 +2143,7 @@ export class MessageDeliveryEngine {
|
|
|
2192
2143
|
client._gapFillDone.add(dedupKey);
|
|
2193
2144
|
this.runtime.delivery.setGapFillActive(true);
|
|
2194
2145
|
let continuationAfterSeq = 0;
|
|
2146
|
+
let pendingAckSeq = 0;
|
|
2195
2147
|
let failed = false;
|
|
2196
2148
|
try {
|
|
2197
2149
|
let nextAfterSeq = afterSeq;
|
|
@@ -2214,9 +2166,11 @@ export class MessageDeliveryEngine {
|
|
|
2214
2166
|
return;
|
|
2215
2167
|
const pageContigBefore = client._seqTracker.getContiguousSeq(ns);
|
|
2216
2168
|
const eventObjects = events.filter((evt) => isJsonObject(evt));
|
|
2217
|
-
|
|
2169
|
+
const contiguousSeq = Number.isSafeInteger(result.contiguous_seq) ? result.contiguous_seq : undefined;
|
|
2170
|
+
if (contiguousSeq === undefined)
|
|
2218
2171
|
client._seqTracker.onPullResult(ns, eventObjects, nextAfterSeq);
|
|
2219
|
-
|
|
2172
|
+
else
|
|
2173
|
+
client._seqTracker.onPullResult(ns, eventObjects, nextAfterSeq, contiguousSeq);
|
|
2220
2174
|
const cursor = isJsonObject(result.cursor) ? result.cursor : null;
|
|
2221
2175
|
const retentionFloor = Math.max(0, Number(result.retention_floor_event_seq ?? 0), Number(cursor?.retention_floor_seq ?? 0));
|
|
2222
2176
|
const serverAckFloor = Math.max(0, Number(cursor?.current_seq ?? 0));
|
|
@@ -2264,35 +2218,35 @@ export class MessageDeliveryEngine {
|
|
|
2264
2218
|
this.persistSeq(ns);
|
|
2265
2219
|
}
|
|
2266
2220
|
if (eventObjects.length > 0 && ackContig > 0 && ackContig !== pageContigBefore) {
|
|
2267
|
-
|
|
2268
|
-
const ackPromise = client._transport.call('group.ack_events', {
|
|
2269
|
-
group_id: groupId,
|
|
2270
|
-
event_seq: ackContig,
|
|
2271
|
-
device_id: client._deviceId,
|
|
2272
|
-
slot_id: client._slotId,
|
|
2273
|
-
_rpc_background: true,
|
|
2274
|
-
});
|
|
2275
|
-
if (singlePage)
|
|
2276
|
-
await ackPromise;
|
|
2277
|
-
else
|
|
2278
|
-
ackPromise.catch((e) => { client._clientLog.warn('group event auto-ack failed: group=' + groupId, e); });
|
|
2279
|
-
}
|
|
2280
|
-
catch (e) {
|
|
2281
|
-
client._clientLog.warn('group event auto-ack failed: group=' + groupId, e);
|
|
2282
|
-
}
|
|
2221
|
+
pendingAckSeq = Math.max(pendingAckSeq, ackContig);
|
|
2283
2222
|
}
|
|
2284
2223
|
this.onPullPage(ns, publishedEventCount, result.has_more === true, eventObjects.length > 0 ? Number(eventObjects[eventObjects.length - 1].event_seq ?? 0) : undefined, typeof result.remaining === 'number' && Number.isSafeInteger(result.remaining) && result.remaining >= 0 ? result.remaining : null, eventObjects.length, ackContig, eventObjects.length > 0 ? Number(eventObjects[eventObjects.length - 1].event_seq ?? 0) : undefined);
|
|
2285
2224
|
const nextAfter = Math.max(eventSeqs.length > 0 ? Math.max(...eventSeqs) : nextAfterSeq, nextAfterSeq);
|
|
2286
|
-
|
|
2225
|
+
const needsMore = result.has_more === true || client._seqTracker.getMaxSeenSeq(ns) > nextAfter;
|
|
2226
|
+
if (singlePage && needsMore && nextAfter > nextAfterSeq) {
|
|
2287
2227
|
continuationAfterSeq = nextAfter;
|
|
2288
2228
|
}
|
|
2289
|
-
if (eventObjects.length === 0 || nextAfter <= nextAfterSeq ||
|
|
2229
|
+
if (eventObjects.length === 0 || nextAfter <= nextAfterSeq || !needsMore)
|
|
2290
2230
|
break;
|
|
2291
2231
|
nextAfterSeq = nextAfter;
|
|
2292
2232
|
}
|
|
2293
2233
|
if (pageCount >= maxPages) {
|
|
2294
2234
|
client._clientLog.warn(`group event gap fill reached max_pages=${maxPages} group=${groupId} after_seq=${nextAfterSeq}`);
|
|
2295
2235
|
}
|
|
2236
|
+
if (pendingAckSeq > 0) {
|
|
2237
|
+
try {
|
|
2238
|
+
await client._transport.call('group.ack_events', {
|
|
2239
|
+
group_id: groupId,
|
|
2240
|
+
event_seq: pendingAckSeq,
|
|
2241
|
+
device_id: client._deviceId,
|
|
2242
|
+
slot_id: client._slotId,
|
|
2243
|
+
_rpc_background: true,
|
|
2244
|
+
});
|
|
2245
|
+
}
|
|
2246
|
+
catch (e) {
|
|
2247
|
+
client._clientLog.warn('group event auto-ack failed: group=' + groupId, e);
|
|
2248
|
+
}
|
|
2249
|
+
}
|
|
2296
2250
|
}
|
|
2297
2251
|
catch (exc) {
|
|
2298
2252
|
failed = true;
|
|
@@ -2331,43 +2285,15 @@ export class MessageDeliveryEngine {
|
|
|
2331
2285
|
this.enqueueOnlineUnreadEventHint(data);
|
|
2332
2286
|
return;
|
|
2333
2287
|
}
|
|
2334
|
-
if (this.isSelfJoinGroupChanged(data)) {
|
|
2335
|
-
const contig = client._seqTracker.getContiguousSeq(ns);
|
|
2336
|
-
const maxSeen = client._seqTracker.getMaxSeenSeq(ns);
|
|
2337
|
-
if (contig === 0 && maxSeen === 0 && eventSeq > 1) {
|
|
2338
|
-
client._clientLog.debug(`group.changed self-join baseline: group=${groupId}, event_seq=${eventSeq}, baseline=${eventSeq - 1}`);
|
|
2339
|
-
client._seqTracker.forceContiguousSeq(ns, eventSeq - 1);
|
|
2340
|
-
}
|
|
2341
|
-
}
|
|
2342
2288
|
const contigBefore = client._seqTracker.getContiguousSeq(ns);
|
|
2289
|
+
client._seqTracker.updateMaxSeen(ns, eventSeq);
|
|
2343
2290
|
const publishedDuplicate = client._pushedSeqs.get(ns)?.has(eventSeq) === true;
|
|
2344
2291
|
if (eventSeq <= contigBefore || publishedDuplicate) {
|
|
2345
2292
|
client._clientLog.debug(`group.changed skipped duplicate/stale: group=${groupId}, event_seq=${eventSeq}, contiguous=${contigBefore}`);
|
|
2346
|
-
if (eventSeq <= contigBefore) {
|
|
2347
|
-
this.fireGroupEventAck(groupId, ns, eventSeq, 'group event covered push ack');
|
|
2348
|
-
}
|
|
2349
|
-
else if (contigBefore > 0) {
|
|
2350
|
-
this.fireGroupEventAck(groupId, ns, contigBefore, 'group event covered push ack');
|
|
2351
|
-
}
|
|
2352
2293
|
return;
|
|
2353
2294
|
}
|
|
2354
2295
|
this.enqueueOrderedMessage(ns, 'group.changed', eventSeq, data);
|
|
2355
|
-
needPull =
|
|
2356
|
-
const ackContig = client._seqTracker.getContiguousSeq(ns);
|
|
2357
|
-
await this.drainOrderedMessages(ns);
|
|
2358
|
-
if (ackContig > 0 && ackContig !== contigBefore) {
|
|
2359
|
-
if (data.action !== 'dissolved')
|
|
2360
|
-
this.persistSeq(ns);
|
|
2361
|
-
client._transport.call('group.ack_events', {
|
|
2362
|
-
group_id: groupId,
|
|
2363
|
-
event_seq: ackContig,
|
|
2364
|
-
device_id: client._deviceId,
|
|
2365
|
-
slot_id: client._slotId,
|
|
2366
|
-
_rpc_background: true,
|
|
2367
|
-
}).catch((e) => {
|
|
2368
|
-
client._clientLog.warn('group event push auto-ack failed: group=' + groupId, e);
|
|
2369
|
-
});
|
|
2370
|
-
}
|
|
2296
|
+
needPull = eventSeq > contigBefore;
|
|
2371
2297
|
if (needPull && groupId && !data._from_gap_fill && client._sessionOptions?.background_sync !== false) {
|
|
2372
2298
|
client._safeAsync(this.fillGroupEventGap(groupId));
|
|
2373
2299
|
}
|
|
@@ -2986,20 +2912,19 @@ export class MessageDeliveryEngine {
|
|
|
2986
2912
|
if (forceTail || order[0] === 'tail')
|
|
2987
2913
|
result = await run(true, false, undefined, false, forceTail);
|
|
2988
2914
|
const state = this.syncState(ns);
|
|
2989
|
-
// Tail 的连续性证明只覆盖其返回的 head。Tail 进行期间到达的新
|
|
2990
|
-
// Push 不能再次进入 realtime planner(那会再做一次 Tail);以已经
|
|
2991
|
-
// 落盘的 ack 为起点,至多补一页普通 Forward 即可恢复该小窗口。
|
|
2992
|
-
const tailMissedDuringPull = tailCompleted
|
|
2993
|
-
&& Number(client._seqTracker.getMaxSeenSeq(ns) || 0) > state.head;
|
|
2994
2915
|
const maxSeen = Number(client._seqTracker.getMaxSeenSeq(ns) || 0);
|
|
2916
|
+
// Tail 期间到达的新 Push 只记录在 pending Pull 上界,不写入 SeqTracker。
|
|
2917
|
+
const pendingUpper = Number(this.pendingP2pPullUpper?.get(ns) ?? 0);
|
|
2918
|
+
const observedUpper = Math.max(maxSeen, pendingUpper);
|
|
2919
|
+
const tailMissedDuringPull = tailCompleted && observedUpper > state.head;
|
|
2995
2920
|
const pendingThroughSeq = tailMissedDuringPull
|
|
2996
|
-
?
|
|
2921
|
+
? observedUpper
|
|
2997
2922
|
: 0;
|
|
2998
|
-
const tailForward = tailCompleted && (state.ack < state.
|
|
2923
|
+
const tailForward = tailCompleted && (state.ack < state.head || tailMissedDuringPull);
|
|
2999
2924
|
const backgroundWindowForward = order[0] === 'forward' && !headForward;
|
|
3000
2925
|
if (headForward || tailForward
|
|
3001
2926
|
|| (client._sessionOptions?.background_sync !== false && backgroundWindowForward)) {
|
|
3002
|
-
const forwardTarget = Math.max(headForward ? Math.max(pushSeq, maxSeen) : 0, (tailForward || backgroundWindowForward) ? state.tail - 1 : 0, tailMissedDuringPull ?
|
|
2927
|
+
const forwardTarget = Math.max(headForward ? Math.max(pushSeq, maxSeen) : 0, (tailForward || backgroundWindowForward) ? state.tail - 1 : 0, tailMissedDuringPull ? observedUpper : 0);
|
|
3003
2928
|
const forwardMaxPages = this.forwardMaxPages(state.ack, forwardTarget, pageLimit);
|
|
3004
2929
|
result = await run(false, !(headForward || tailForward), forwardMaxPages, headForward || tailMissedDuringPull);
|
|
3005
2930
|
if (pendingThroughSeq > 0) {
|
|
@@ -3061,17 +2986,18 @@ export class MessageDeliveryEngine {
|
|
|
3061
2986
|
const state = this.syncState(ns);
|
|
3062
2987
|
// 与 P2P 相同:真实完成 Tail 后,至多用一页 Forward 收敛 Tail
|
|
3063
2988
|
// 期间新到达的序号;绝不重新规划或再执行 Tail。
|
|
3064
|
-
const tailMissedDuringPull = tailCompleted
|
|
3065
|
-
&& Number(client._seqTracker.getMaxSeenSeq(ns) || 0) > state.head;
|
|
3066
2989
|
const maxSeen = Number(client._seqTracker.getMaxSeenSeq(ns) || 0);
|
|
2990
|
+
const pendingUpper = Number(this.pendingGroupPullUpper?.get(ns) ?? 0);
|
|
2991
|
+
const observedUpper = Math.max(maxSeen, pendingUpper);
|
|
2992
|
+
const tailMissedDuringPull = tailCompleted && observedUpper > state.head;
|
|
3067
2993
|
const pendingThroughSeq = tailMissedDuringPull
|
|
3068
|
-
?
|
|
2994
|
+
? observedUpper
|
|
3069
2995
|
: 0;
|
|
3070
|
-
const tailForward = tailCompleted && (state.ack < state.
|
|
2996
|
+
const tailForward = tailCompleted && (state.ack < state.head || tailMissedDuringPull);
|
|
3071
2997
|
const backgroundWindowForward = order[0] === 'forward' && !headForward;
|
|
3072
2998
|
if (headForward || tailForward
|
|
3073
2999
|
|| (client._sessionOptions?.background_sync !== false && backgroundWindowForward)) {
|
|
3074
|
-
const forwardTarget = Math.max(headForward ? Math.max(pushSeq, maxSeen) : 0, (tailForward || backgroundWindowForward) ? state.tail - 1 : 0, tailMissedDuringPull ?
|
|
3000
|
+
const forwardTarget = Math.max(headForward ? Math.max(pushSeq, maxSeen) : 0, (tailForward || backgroundWindowForward) ? state.tail - 1 : 0, tailMissedDuringPull ? observedUpper : 0);
|
|
3075
3001
|
const forwardMaxPages = this.forwardMaxPages(state.ack, forwardTarget, pageLimit);
|
|
3076
3002
|
result = await run(false, !(headForward || tailForward), forwardMaxPages, headForward || tailMissedDuringPull);
|
|
3077
3003
|
if (pendingThroughSeq > 0) {
|
|
@@ -3128,15 +3054,13 @@ export class MessageDeliveryEngine {
|
|
|
3128
3054
|
const groupId = typeof row.group_id === 'string' ? row.group_id.trim() : '';
|
|
3129
3055
|
if (!groupId)
|
|
3130
3056
|
return;
|
|
3131
|
-
const seq = typeof row.seq === 'number' ? row.seq : 0;
|
|
3132
3057
|
const eventKind = String(row.kind ?? '').trim();
|
|
3133
3058
|
const ns = this.resolvePendingGroupInlineAckNamespace(`group:${groupId}`);
|
|
3134
|
-
|
|
3135
|
-
|
|
3136
|
-
// 必须在进入 namespace 队列前登记,才能让在途 Tail 看见后来 Push。
|
|
3059
|
+
const seq = positiveSafeSequenceHint(row.seq);
|
|
3060
|
+
if (client._v2Session && eventKind !== 'group.online_unread_hint' && seq > 0) {
|
|
3137
3061
|
client._seqTracker.updateMaxSeen(ns, seq);
|
|
3138
3062
|
}
|
|
3139
|
-
const hasInlineObject =
|
|
3063
|
+
const hasInlineObject = hasNonEmptyInlineMessage(row.inline_message)
|
|
3140
3064
|
&& eventKind !== 'group.online_unread_hint';
|
|
3141
3065
|
const inlineGeneration = hasInlineObject ? this.captureInlineGeneration() : undefined;
|
|
3142
3066
|
const operation = () => this.processGroupV2MessageCreated(data, 'v2', inlineGeneration);
|
|
@@ -3153,7 +3077,6 @@ export class MessageDeliveryEngine {
|
|
|
3153
3077
|
return;
|
|
3154
3078
|
const groupId = typeof data.group_id === 'string' ? data.group_id.trim() : '';
|
|
3155
3079
|
const seq = positiveSafeSequenceHint(data.seq);
|
|
3156
|
-
const strictSeq = typeof data.seq === 'number' && Number.isSafeInteger(data.seq) && data.seq > 0;
|
|
3157
3080
|
if (!groupId)
|
|
3158
3081
|
return;
|
|
3159
3082
|
const eventKind = String(data.kind ?? '').trim();
|
|
@@ -3165,12 +3088,13 @@ export class MessageDeliveryEngine {
|
|
|
3165
3088
|
return;
|
|
3166
3089
|
}
|
|
3167
3090
|
const ns = this.resolvePendingGroupInlineAckNamespace(`group:${groupId}`);
|
|
3168
|
-
const inlinePresent =
|
|
3091
|
+
const inlinePresent = hasNonEmptyInlineMessage(data.inline_message);
|
|
3169
3092
|
if (seq <= 0) {
|
|
3170
3093
|
if (inlinePresent)
|
|
3171
3094
|
await this.recoverInvalidGroupRealtimeHead(groupId, ns, data.seq);
|
|
3172
3095
|
return;
|
|
3173
3096
|
}
|
|
3097
|
+
client._seqTracker.updateMaxSeen(ns, seq);
|
|
3174
3098
|
const inline = this.inlineMessage(data);
|
|
3175
3099
|
const inlineMatches = inline !== null
|
|
3176
3100
|
&& this.inlineGroupBindingMatches(data, inline, groupId, seq, expectedInlineVersion);
|
|
@@ -3189,15 +3113,13 @@ export class MessageDeliveryEngine {
|
|
|
3189
3113
|
const before = this.syncState(ns);
|
|
3190
3114
|
// 无正文的旧服务端 Head 可把 JSON-safe 数字字符串作为恢复 hint;
|
|
3191
3115
|
// inline 绑定仍要求原始 seq 是严格 number,避免类型归一化后消费正文。
|
|
3192
|
-
if (strictSeq || !inlinePresent)
|
|
3193
|
-
client._seqTracker.updateMaxSeen(ns, seq);
|
|
3194
3116
|
if (seq <= before.ack && before.ack >= before.tail - 1) {
|
|
3195
3117
|
const canonicalNs = this.resolvePendingGroupInlineAckNamespace(ns);
|
|
3196
3118
|
const pending = this.pendingGroupInlineAcks?.get(canonicalNs);
|
|
3197
|
-
if (pending && seq >= pending.seq) {
|
|
3119
|
+
if (inlinePresent && pending && seq >= pending.seq) {
|
|
3198
3120
|
this.retryPendingGroupInlineAck(canonicalNs, pending.seq, 'covered inline Group ack', seq);
|
|
3199
3121
|
}
|
|
3200
|
-
else if (
|
|
3122
|
+
else if (inlineMatches) {
|
|
3201
3123
|
this.fireGroupV2Ack(groupId, ns, seq, 'group v2 covered push ack', inlineMatches ? inlineGeneration : null);
|
|
3202
3124
|
}
|
|
3203
3125
|
return;
|
|
@@ -3233,11 +3155,10 @@ export class MessageDeliveryEngine {
|
|
|
3233
3155
|
}
|
|
3234
3156
|
const pushSeq = isJsonObject(data) && typeof data.seq === 'number' ? data.seq : 0;
|
|
3235
3157
|
if (client._v2Session && Number.isSafeInteger(pushSeq) && pushSeq > 0) {
|
|
3236
|
-
// 与 Group 相同,在排队前暴露更高 Head 给当前在途 Tail。
|
|
3237
3158
|
client._seqTracker.updateMaxSeen(ns, pushSeq);
|
|
3238
3159
|
}
|
|
3239
3160
|
const hasInlineObject = isJsonObject(data)
|
|
3240
|
-
&&
|
|
3161
|
+
&& hasNonEmptyInlineMessage(data.inline_message);
|
|
3241
3162
|
const inlineGeneration = hasInlineObject ? this.captureInlineGeneration() : undefined;
|
|
3242
3163
|
const operation = () => this.processV2P2PNotification(data, 'v2', inlineGeneration);
|
|
3243
3164
|
if (hasInlineObject)
|
|
@@ -3252,12 +3173,12 @@ export class MessageDeliveryEngine {
|
|
|
3252
3173
|
if (!client._v2Session)
|
|
3253
3174
|
return;
|
|
3254
3175
|
const pushSeq = isJsonObject(data) ? positiveSafeSequenceHint(data.seq) : 0;
|
|
3255
|
-
const strictSeq = isJsonObject(data)
|
|
3256
|
-
&& typeof data.seq === 'number' && Number.isSafeInteger(data.seq) && data.seq > 0;
|
|
3257
3176
|
const ns = client._aid ? `p2p:${client._aid}` : '';
|
|
3258
3177
|
if (!ns)
|
|
3259
3178
|
return;
|
|
3260
|
-
|
|
3179
|
+
if (pushSeq > 0)
|
|
3180
|
+
client._seqTracker.updateMaxSeen(ns, pushSeq);
|
|
3181
|
+
const inlinePresent = isJsonObject(data) && hasNonEmptyInlineMessage(data.inline_message);
|
|
3261
3182
|
if (pushSeq <= 0) {
|
|
3262
3183
|
if (inlinePresent)
|
|
3263
3184
|
await this.recoverInvalidP2PRealtimeHead(ns, isJsonObject(data) ? data.seq : undefined);
|
|
@@ -3277,11 +3198,9 @@ export class MessageDeliveryEngine {
|
|
|
3277
3198
|
if (inlineMatches && !this.isInlineGenerationCurrent(inlineGeneration))
|
|
3278
3199
|
return;
|
|
3279
3200
|
const before = this.syncState(ns);
|
|
3280
|
-
if (strictSeq || !inlinePresent)
|
|
3281
|
-
client._seqTracker.updateMaxSeen(ns, pushSeq);
|
|
3282
3201
|
if (pushSeq <= before.ack && before.ack >= before.tail - 1) {
|
|
3283
3202
|
const pending = this.pendingP2PInlineAcks?.get(ns);
|
|
3284
|
-
if (pending && pushSeq >= pending.seq) {
|
|
3203
|
+
if (inlinePresent && pending && pushSeq >= pending.seq) {
|
|
3285
3204
|
this.retryPendingP2PInlineAck(ns, pending.seq, 'covered inline P2P ack', pushSeq);
|
|
3286
3205
|
}
|
|
3287
3206
|
else if (inlineMatches) {
|