@agentunion/fastaun-browser 0.4.3 → 0.4.4
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 +190 -178
- package/_packed_docs/AUN_SDK_0.4.0_/350/256/276/350/256/241/345/257/271/346/257/224/345/210/206/346/236/220.md +194 -194
- package/_packed_docs/AUN_SDK_/351/207/215/346/236/204/345/256/236/346/226/275/350/256/241/345/210/222.md +596 -596
- package/_packed_docs/AUN_SDK_/351/207/215/346/236/204/350/256/276/350/256/241/346/226/271/346/241/210_v3.md +1698 -1697
- package/_packed_docs/CHANGELOG.md +190 -178
- package/_packed_docs/INDEX.md +17 -17
- package/_packed_docs/KITE_DOCS_GUIDE.md +11 -11
- package/_packed_docs/agent.md/SCHEMA.md +49 -49
- package/_packed_docs/agent.md/examples/signed-openclaw-lobster.md +22 -22
- package/_packed_docs/agent.md//350/277/234/347/250/213agent.md/347/274/223/345/255/230/344/270/216etag/351/200/217/344/274/240/346/226/271/346/241/210.md +327 -327
- package/_packed_docs/cli/AUN-CLI/350/256/276/350/256/241/346/226/207/346/241/243.md +686 -686
- package/_packed_docs/design/2026-05-22-aun-rpc-trace-enhancement.md +542 -542
- package/_packed_docs/design/E2EE_V2/347/256/200/345/214/226/344/270/2721DH/345/212/240Per-AID_Wrap/346/226/271/346/241/210.md +124 -124
- package/_packed_docs/design//350/267/250/350/257/255/350/250/200/345/256/271/345/231/250E2E/346/265/213/350/257/225/346/226/271/346/241/210.md +665 -665
- package/_packed_docs/protocol/01-/350/272/253/344/273/275/344/270/216/345/207/255/350/257/201/345/215/217/350/256/256-auth.md +2 -2
- package/_packed_docs/protocol/14-/344/272/244/344/272/222/346/234/272/345/210/266-/345/223/215/345/272/224/346/250/241/345/274/217/344/270/216/350/207/252/344/270/273/346/250/241/345/274/217.md +170 -170
- package/_packed_docs/protocol/15-/347/246/273/347/272/277/346/216/250/351/200/201/351/200/232/347/237/245/345/215/217/350/256/256.md +419 -419
- package/_packed_docs/protocol/README.md +1 -1
- package/_packed_docs/protocol/aun-docs-guide.md +1 -1
- package/_packed_docs/protocol//351/231/204/345/275/225A-/346/234/257/350/257/255/350/241/250.md +15 -15
- package/_packed_docs/protocol//351/231/204/345/275/225B-/346/211/251/345/261/225/346/200/247/346/214/207/345/215/227.md +4 -4
- package/_packed_docs/protocol//351/231/204/345/275/225J-/345/256/242/346/210/267/347/253/257/346/216/245/345/205/245/347/244/272/344/276/213.md +98 -98
- package/_packed_docs/protocol//351/231/204/345/275/225M-JWT/350/256/244/350/257/201/345/256/236/347/216/260/346/214/207/345/215/227.md +46 -46
- package/_packed_docs/protocol//351/231/204/345/275/225N-/345/210/206/345/270/203/345/274/217Trace/345/215/217/350/256/256.md +257 -257
- package/_packed_docs/python-sdk-v2-only-changelog.md +189 -189
- package/_packed_docs/sdk/01-/345/277/253/351/200/237/345/274/200/345/247/213.md +1 -1
- package/_packed_docs/sdk/05-E2EE/345/212/240/345/257/206/351/200/232/344/277/241.md +1 -1
- package/_packed_docs/sdk/06-API/346/211/213/345/206/214.md +1 -0
- package/_packed_docs/sdk/09-payload-reference.md +13 -13
- package/_packed_docs/sdk/E2EE_V2/346/266/210/346/201/257/351/200/232/344/277/241/346/227/266/345/272/217/345/233/276.md +171 -171
- package/dist/aid.d.ts +2 -1
- package/dist/aid.d.ts.map +1 -1
- package/dist/aid.js +7 -6
- package/dist/aid.js.map +1 -1
- package/dist/auth.d.ts.map +1 -1
- package/dist/auth.js +4 -0
- package/dist/auth.js.map +1 -1
- package/dist/bundle.js +237 -149
- package/dist/client.d.ts +7 -1
- package/dist/client.d.ts.map +1 -1
- package/dist/client.js +238 -153
- package/dist/client.js.map +1 -1
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/package.json +1 -1
|
@@ -1,419 +1,419 @@
|
|
|
1
|
-
# 15 - 离线推送通知协议 (Push Notification)
|
|
2
|
-
|
|
3
|
-
## 1. 概述
|
|
4
|
-
|
|
5
|
-
当目标 AID 的所有设备均离线时,AUN Gateway 通过事件通知将推送摘要发送给 `push_notify_aid`(推送代理 AID),由其完成最终的平台推送(APNs / FCM / WebPush 等)。
|
|
6
|
-
|
|
7
|
-
**设计原则:**
|
|
8
|
-
|
|
9
|
-
- push_notify_aid 是普通客户端 AID,不是 AUN 内部服务
|
|
10
|
-
- 通过事件通知(非 P2P 消息)下发推送摘要——轻量、实时、不持久化
|
|
11
|
-
- push_token 对 Gateway 完全不透明(opaque),push_notify_aid 自签自验
|
|
12
|
-
- 任意一台设备在线即不触发推送
|
|
13
|
-
- 推送内容仅含元数据,不含消息正文(E2EE 安全保证)
|
|
14
|
-
- 背压控制:串行确认,Gateway 等 push_notify_aid ack 后再发下一批
|
|
15
|
-
- 跨域推送:推送由**目标 AID 所属域**的 Gateway 触发,发送方域不参与
|
|
16
|
-
|
|
17
|
-
---
|
|
18
|
-
|
|
19
|
-
## 2. 架构
|
|
20
|
-
|
|
21
|
-
```mermaid
|
|
22
|
-
graph TB
|
|
23
|
-
Sender[发送方 AID] -->|message.send| GW[Gateway]
|
|
24
|
-
GW -->|目标全部离线| PA[PushAggregator]
|
|
25
|
-
PA -->|event/push.offline_message| GW
|
|
26
|
-
GW -->|事件通知| PNA[push_notify_aid<br/>推送代理客户端]
|
|
27
|
-
PNA -->|push.ack| GW
|
|
28
|
-
PNA -->|平台推送| PLATFORM[APNs / FCM / WebPush]
|
|
29
|
-
PLATFORM -->|通知| Target[目标终端]
|
|
30
|
-
|
|
31
|
-
PNA -.->|connect 到 Gateway 保持在线| GW
|
|
32
|
-
```
|
|
33
|
-
|
|
34
|
-
**关键约束:**
|
|
35
|
-
|
|
36
|
-
- push_notify_aid 作为普通客户端 AID 连接到 Gateway,通过事件通知接收推送摘要
|
|
37
|
-
- push_notify_aid 离线时事件丢弃——推送是 best-effort,消息可靠性由 message.pull 保证
|
|
38
|
-
- 目标 AID 有任意一台设备在线时,不触发推送
|
|
39
|
-
|
|
40
|
-
---
|
|
41
|
-
|
|
42
|
-
## 3. 推送注册流程
|
|
43
|
-
|
|
44
|
-
### 3.1 应用层:客户端向推送代理注册
|
|
45
|
-
|
|
46
|
-
```mermaid
|
|
47
|
-
sequenceDiagram
|
|
48
|
-
participant App as 应用客户端
|
|
49
|
-
participant PNA as push_notify_aid
|
|
50
|
-
|
|
51
|
-
Note over App,PNA: 应用层行为,AUN 协议不规定细节
|
|
52
|
-
App->>PNA: 注册推送(aid, device_id, platform, device_token)
|
|
53
|
-
PNA->>PNA: 生成 push_token(格式自定)
|
|
54
|
-
PNA-->>App: push_token
|
|
55
|
-
```
|
|
56
|
-
|
|
57
|
-
push_token 的格式、签名算法、有效期完全由 push_notify_aid 自行决定。AUN 协议不做任何约束。
|
|
58
|
-
|
|
59
|
-
### 3.2 协议层:connect 时携带推送配置
|
|
60
|
-
|
|
61
|
-
```mermaid
|
|
62
|
-
sequenceDiagram
|
|
63
|
-
participant C as Client
|
|
64
|
-
participant GW as Gateway
|
|
65
|
-
|
|
66
|
-
C->>GW: connect(aid, token, push_notify_aid, push_token)
|
|
67
|
-
GW->>GW: 认证 AID 身份 ✓
|
|
68
|
-
GW->>GW: 持久化 push_config
|
|
69
|
-
GW-->>C: connected
|
|
70
|
-
```
|
|
71
|
-
|
|
72
|
-
---
|
|
73
|
-
|
|
74
|
-
## 4. 离线推送时序
|
|
75
|
-
|
|
76
|
-
```mermaid
|
|
77
|
-
sequenceDiagram
|
|
78
|
-
participant A as Sender AID
|
|
79
|
-
participant GW as Gateway
|
|
80
|
-
participant PA as PushAggregator
|
|
81
|
-
participant PNA as push_notify_aid
|
|
82
|
-
|
|
83
|
-
A->>GW: message.send(to=B, payload=...)
|
|
84
|
-
GW->>GW: 持久化消息 + 查询 B 在线状态
|
|
85
|
-
|
|
86
|
-
alt B 有任意设备在线
|
|
87
|
-
GW->>GW: 投递到 B 的在线 session
|
|
88
|
-
Note over GW: 不触发推送
|
|
89
|
-
else B 全部设备离线
|
|
90
|
-
GW->>PA: enqueue(target=B, from=A, msg_id, ts)
|
|
91
|
-
PA->>PA: 聚合窗口 + 频控 + 背压检查
|
|
92
|
-
|
|
93
|
-
alt 触发推送 且 in_flight < max
|
|
94
|
-
PA->>GW: event/push.offline_message
|
|
95
|
-
GW->>PNA: 事件通知(batch_id, summary, push_token)
|
|
96
|
-
PA->>PA: in_flight++, 启动 ack_timeout
|
|
97
|
-
PNA->>PNA: 验证 push_token ✓ → 发送平台推送
|
|
98
|
-
PNA->>GW: push.ack(batch_id)
|
|
99
|
-
GW->>PA: release(batch_id)
|
|
100
|
-
PA->>PA: in_flight--
|
|
101
|
-
else in_flight = max(背压)
|
|
102
|
-
PA->>PA: 排队等待槽位释放
|
|
103
|
-
else 频控抑制
|
|
104
|
-
PA->>PA: 延迟到下一窗口
|
|
105
|
-
end
|
|
106
|
-
end
|
|
107
|
-
|
|
108
|
-
GW-->>A: ack(msg_id, seq)
|
|
109
|
-
```
|
|
110
|
-
|
|
111
|
-
---
|
|
112
|
-
|
|
113
|
-
## 5. 背压与 in-flight 控制
|
|
114
|
-
|
|
115
|
-
```mermaid
|
|
116
|
-
stateDiagram-v2
|
|
117
|
-
[*] --> Idle: 初始状态
|
|
118
|
-
Idle --> Sending: 有待推送 & in_flight < max
|
|
119
|
-
Sending --> WaitAck: 事件已发出, in_flight++
|
|
120
|
-
WaitAck --> Idle: 收到 push.ack, in_flight--
|
|
121
|
-
WaitAck --> Idle: ack_timeout 超时, in_flight--
|
|
122
|
-
WaitAck --> Queued: 新推送到达但 in_flight = max
|
|
123
|
-
Queued --> Sending: 槽位释放
|
|
124
|
-
```
|
|
125
|
-
|
|
126
|
-
### 参数
|
|
127
|
-
|
|
128
|
-
| 参数 | 默认值 | 说明 |
|
|
129
|
-
|------|--------|------|
|
|
130
|
-
| max_in_flight | 1 | 同一 push_notify_aid 未确认批次上限(串行) |
|
|
131
|
-
| ack_timeout | 30s | 超时未 ack 自动释放槽位 |
|
|
132
|
-
| batch_size | 50 | 每批最多聚合多少个 target_aid 的通知 |
|
|
133
|
-
|
|
134
|
-
### 行为规则
|
|
135
|
-
|
|
136
|
-
- in_flight < max → 发送事件,in_flight++
|
|
137
|
-
- in_flight = max → 排队等待
|
|
138
|
-
- 收到 `push.ack(batch_id)` → in_flight--,触发队列中下一批
|
|
139
|
-
- 超时 → in_flight--,**不重试**(推送是 best-effort,过时推送是噪音)
|
|
140
|
-
- push_notify_aid 离线 → 事件丢弃,in_flight 不增加
|
|
141
|
-
|
|
142
|
-
---
|
|
143
|
-
|
|
144
|
-
## 6. 在线判断规则
|
|
145
|
-
|
|
146
|
-
```mermaid
|
|
147
|
-
flowchart TD
|
|
148
|
-
A[消息到达,目标 AID = B] --> B{B 的在线设备数 > 0?}
|
|
149
|
-
B -->|≥ 1 台在线| C[投递到在线 session,不推送]
|
|
150
|
-
B -->|0 台在线| D{push_config 存在?}
|
|
151
|
-
D -->|是| F[进入 PushAggregator]
|
|
152
|
-
D -->|否| G[仅持久化,等对方上线 pull]
|
|
153
|
-
F --> H[聚合 + 频控 + 背压 → 推送]
|
|
154
|
-
```
|
|
155
|
-
|
|
156
|
-
**边界情况:**
|
|
157
|
-
|
|
158
|
-
- 目标 AID 上线瞬间:清空该 AID 的聚合桶,取消待发推送
|
|
159
|
-
- 最后一台设备断连:不立即触发推送,只有后续新消息到达时发现全离线才走推送路径
|
|
160
|
-
|
|
161
|
-
---
|
|
162
|
-
|
|
163
|
-
## 7. 跨域推送
|
|
164
|
-
|
|
165
|
-
**核心原则:推送由目标 AID 所属域的 Gateway 触发。**
|
|
166
|
-
|
|
167
|
-
发送方域不感知目标域的 push_config 和白名单,也不需要任何跨域配置同步。
|
|
168
|
-
|
|
169
|
-
```mermaid
|
|
170
|
-
sequenceDiagram
|
|
171
|
-
participant A as alice.domain-a.com
|
|
172
|
-
participant GW_A as Gateway A
|
|
173
|
-
participant GW_B as Gateway B
|
|
174
|
-
participant PA_B as PushAggregator B
|
|
175
|
-
participant PNA as push.domain-b.com<br/>(连在 GW_B)
|
|
176
|
-
|
|
177
|
-
A->>GW_A: message.send(to=bob.domain-b.com)
|
|
178
|
-
GW_A->>GW_A: 持久化消息
|
|
179
|
-
GW_A->>GW_B: 跨域 relay 消息
|
|
180
|
-
GW_B->>GW_B: 查询 bob 本地在线状态
|
|
181
|
-
|
|
182
|
-
alt bob 在本域有设备在线
|
|
183
|
-
GW_B->>GW_B: 投递到 bob 的在线 session
|
|
184
|
-
else bob 本域全部离线
|
|
185
|
-
GW_B->>PA_B: enqueue(target=bob, from=alice.domain-a.com)
|
|
186
|
-
PA_B->>GW_B: event/push.offline_message
|
|
187
|
-
GW_B->>PNA: 事件通知
|
|
188
|
-
PNA->>GW_B: push.ack
|
|
189
|
-
end
|
|
190
|
-
|
|
191
|
-
GW_B-->>GW_A: relay ack
|
|
192
|
-
GW_A-->>A: ack
|
|
193
|
-
```
|
|
194
|
-
|
|
195
|
-
**规则:**
|
|
196
|
-
|
|
197
|
-
| 关注点 | 行为 |
|
|
198
|
-
|--------|------|
|
|
199
|
-
| 推送配置存储 | 仅存于目标 AID 所属域,不跨域同步 |
|
|
200
|
-
| 白名单管理 | 各域独立配置 `allowed_notify_aids`,互不影响 |
|
|
201
|
-
| push_notify_aid 必须连接位置 | 目标 AID 所属域的 Gateway |
|
|
202
|
-
| push_notify_aid 跨域时 | 不支持。push_notify_aid 必须与其服务的 AID 同域 |
|
|
203
|
-
| summary.senders 中的跨域 AID | 保留完整 AID(含域名),如 `alice.domain-a.com` |
|
|
204
|
-
|
|
205
|
-
**约束:** push_notify_aid 必须与其服务的目标 AID 处于同一域。如果应用希望在多个域提供推送服务,需要在每个域部署独立的 push_notify_aid 并分别加入白名单。
|
|
206
|
-
|
|
207
|
-
---
|
|
208
|
-
|
|
209
|
-
## 8. 聚合与频控
|
|
210
|
-
|
|
211
|
-
### 8.1 PushAggregator 数据结构
|
|
212
|
-
|
|
213
|
-
每个离线目标 AID 一个聚合桶:
|
|
214
|
-
|
|
215
|
-
```
|
|
216
|
-
bucket[target_aid] = {
|
|
217
|
-
push_notify_aid: "push.myapp.com",
|
|
218
|
-
push_token: "eyJhb...",
|
|
219
|
-
pending: [{from, msg_id, ts}, ...],
|
|
220
|
-
first_enqueue_ts: timestamp,
|
|
221
|
-
last_push_ts: timestamp,
|
|
222
|
-
}
|
|
223
|
-
```
|
|
224
|
-
|
|
225
|
-
### 8.2 去重规则
|
|
226
|
-
|
|
227
|
-
同一 target_aid 在频控窗口内只产生一次推送通知。具体行为:
|
|
228
|
-
|
|
229
|
-
- 首条消息触发推送后,该 target_aid 进入频控冷却期(默认 60s)
|
|
230
|
-
- 冷却期内新消息只更新聚合桶的 summary(unread_count++、senders 去重追加),不产生新推送
|
|
231
|
-
- 冷却期结束时,若桶内有新增未推送内容,合并为一条推送发出
|
|
232
|
-
|
|
233
|
-
效果:无论短时间内收到多少条消息,target_aid 最多每 60s 收到一次推送通知,且 summary 是累积聚合的。
|
|
234
|
-
|
|
235
|
-
### 8.3 触发规则
|
|
236
|
-
|
|
237
|
-
| 规则 | 说明 | 默认值 |
|
|
238
|
-
|------|------|--------|
|
|
239
|
-
| 首条即推 | 桶为空且不在冷却期时,第一条消息立即触发 | 开启 |
|
|
240
|
-
| 窗口聚合 | 首条之后的消息等待窗口合并 | 5 秒 |
|
|
241
|
-
| 数量上限 | 桶内积累 N 条立即触发(不等窗口) | 20 条 |
|
|
242
|
-
|
|
243
|
-
### 8.4 频控规则
|
|
244
|
-
|
|
245
|
-
| 维度 | 限制 | 说明 |
|
|
246
|
-
|------|------|------|
|
|
247
|
-
| 同一 target_aid | 60 秒内最多 1 次推送 | 避免终端刷屏 |
|
|
248
|
-
| 同一 push_notify_aid | 1000 次/分钟 | 保护推送代理服务 |
|
|
249
|
-
| 全局 | 5000 次/分钟 | 系统保护 |
|
|
250
|
-
|
|
251
|
-
频控被触发时消息不丢弃,等窗口过后下一次聚合时一并推送。
|
|
252
|
-
|
|
253
|
-
---
|
|
254
|
-
|
|
255
|
-
## 9. 协议字段
|
|
256
|
-
|
|
257
|
-
### 9.1 connect 扩展字段
|
|
258
|
-
|
|
259
|
-
```json
|
|
260
|
-
{
|
|
261
|
-
"method": "auth.login",
|
|
262
|
-
"params": {
|
|
263
|
-
"aid": "bob.example.com",
|
|
264
|
-
"challenge_response": "...",
|
|
265
|
-
"push_notify_aid": "push.myapp.com",
|
|
266
|
-
"push_token": "eyJhbGciOiJIUzI1NiJ9..."
|
|
267
|
-
}
|
|
268
|
-
}
|
|
269
|
-
```
|
|
270
|
-
|
|
271
|
-
- `push_notify_aid` 和 `push_token` 均为可选字段
|
|
272
|
-
- 两者必须同时提供或同时不提供
|
|
273
|
-
- 不提供 = 不需要离线推送
|
|
274
|
-
- 每次 connect 覆盖写(最新连接为准)
|
|
275
|
-
|
|
276
|
-
### 9.2 事件通知格式
|
|
277
|
-
|
|
278
|
-
Gateway 向 push_notify_aid 下发的事件通知:
|
|
279
|
-
|
|
280
|
-
```json
|
|
281
|
-
{
|
|
282
|
-
"method": "event/push.offline_message",
|
|
283
|
-
"params": {
|
|
284
|
-
"batch_id": "uuid-xxx",
|
|
285
|
-
"items": [
|
|
286
|
-
{
|
|
287
|
-
"target_aid": "bob.example.com",
|
|
288
|
-
"push_token": "eyJhbGciOiJIUzI1NiJ9...",
|
|
289
|
-
"summary": {
|
|
290
|
-
"unread_count": 3,
|
|
291
|
-
"senders": ["alice.example.com", "charlie.example.com"],
|
|
292
|
-
"latest_ts": 1716100005,
|
|
293
|
-
"group_ids": ["group-uuid-1"]
|
|
294
|
-
}
|
|
295
|
-
}
|
|
296
|
-
]
|
|
297
|
-
}
|
|
298
|
-
}
|
|
299
|
-
```
|
|
300
|
-
|
|
301
|
-
**安全约束:** 不包含消息正文。E2EE 场景下 Gateway 无法解密,推送代理只需知道"有 N 条未读来自谁"即可构造推送文案。
|
|
302
|
-
|
|
303
|
-
### 9.3 push.ack RPC
|
|
304
|
-
|
|
305
|
-
push_notify_aid 处理完一批推送后回调确认:
|
|
306
|
-
|
|
307
|
-
```json
|
|
308
|
-
{
|
|
309
|
-
"method": "push.ack",
|
|
310
|
-
"params": {
|
|
311
|
-
"batch_id": "uuid-xxx"
|
|
312
|
-
}
|
|
313
|
-
}
|
|
314
|
-
```
|
|
315
|
-
|
|
316
|
-
Gateway 收到后释放 in-flight 槽位,触发下一批。
|
|
317
|
-
|
|
318
|
-
### 9.4 push.update_config RPC(可选)
|
|
319
|
-
|
|
320
|
-
允许客户端在不重连的情况下更新推送配置:
|
|
321
|
-
|
|
322
|
-
```json
|
|
323
|
-
{
|
|
324
|
-
"method": "push.update_config",
|
|
325
|
-
"params": {
|
|
326
|
-
"push_notify_aid": "push.myapp.com",
|
|
327
|
-
"push_token": "new-token..."
|
|
328
|
-
}
|
|
329
|
-
}
|
|
330
|
-
```
|
|
331
|
-
|
|
332
|
-
---
|
|
333
|
-
|
|
334
|
-
## 10. push_token 鉴权模型
|
|
335
|
-
|
|
336
|
-
### 10.1 push_notify_aid 白名单
|
|
337
|
-
|
|
338
|
-
Gateway 配置允许的 push_notify_aid 白名单,只有白名单内的 AID 才能被设置为推送代理:
|
|
339
|
-
|
|
340
|
-
- 客户端 connect 时携带的 `push_notify_aid` 不在白名单内 → 忽略该字段,不报错,不存储
|
|
341
|
-
- 白名单为空 → 禁用推送功能
|
|
342
|
-
- 白名单配置在 Gateway 启动配置中,运行时不可动态修改
|
|
343
|
-
|
|
344
|
-
```json
|
|
345
|
-
{
|
|
346
|
-
"push": {
|
|
347
|
-
"allowed_notify_aids": [
|
|
348
|
-
"push.myapp.com",
|
|
349
|
-
"push.partner.com"
|
|
350
|
-
]
|
|
351
|
-
}
|
|
352
|
-
}
|
|
353
|
-
```
|
|
354
|
-
|
|
355
|
-
### 10.2 token 透传模型
|
|
356
|
-
|
|
357
|
-
```mermaid
|
|
358
|
-
sequenceDiagram
|
|
359
|
-
participant PNA as push_notify_aid
|
|
360
|
-
participant GW as Gateway
|
|
361
|
-
|
|
362
|
-
Note over PNA,GW: push_token 生命周期
|
|
363
|
-
PNA->>PNA: 签发 push_token(格式/算法自定)
|
|
364
|
-
Note over GW: Gateway 存储 push_token(opaque bytes)
|
|
365
|
-
Note over GW: 不验签、不解析、不判断过期
|
|
366
|
-
GW->>PNA: event/push.offline_message(..., push_token="xxx")
|
|
367
|
-
PNA->>PNA: 自己验签 push_token
|
|
368
|
-
alt token 有效
|
|
369
|
-
PNA->>PNA: 执行推送
|
|
370
|
-
PNA->>GW: push.ack(batch_id)
|
|
371
|
-
else token 无效/过期
|
|
372
|
-
PNA->>PNA: 丢弃
|
|
373
|
-
PNA->>GW: push.ack(batch_id)
|
|
374
|
-
Note over PNA: 客户端下次 connect 带新 token
|
|
375
|
-
end
|
|
376
|
-
```
|
|
377
|
-
|
|
378
|
-
**职责划分:**
|
|
379
|
-
|
|
380
|
-
| 角色 | 职责 |
|
|
381
|
-
|------|------|
|
|
382
|
-
| push_notify_aid | 签发 token、验证 token、决定格式和有效期、处理后 ack |
|
|
383
|
-
| Gateway | 存储 token、透传 token、不解析不验证、管理 in-flight |
|
|
384
|
-
| Client | 向 push_notify_aid 申请 token、connect 时携带 |
|
|
385
|
-
|
|
386
|
-
---
|
|
387
|
-
|
|
388
|
-
## 11. 持久化
|
|
389
|
-
|
|
390
|
-
### push_config 表
|
|
391
|
-
|
|
392
|
-
```sql
|
|
393
|
-
CREATE TABLE push_config (
|
|
394
|
-
aid VARCHAR(255) PRIMARY KEY,
|
|
395
|
-
push_notify_aid VARCHAR(255) NOT NULL,
|
|
396
|
-
push_token TEXT NOT NULL,
|
|
397
|
-
updated_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP
|
|
398
|
-
);
|
|
399
|
-
```
|
|
400
|
-
|
|
401
|
-
- 随 connect 写入/更新(UPSERT)
|
|
402
|
-
- 可加内存缓存(TTL 5 分钟)
|
|
403
|
-
|
|
404
|
-
---
|
|
405
|
-
|
|
406
|
-
## 12. 边界情况
|
|
407
|
-
|
|
408
|
-
| 场景 | 处理 |
|
|
409
|
-
|------|------|
|
|
410
|
-
| push_notify_aid 离线 | 事件丢弃,不持久化。推送是 best-effort,消息可靠性由 pull 保证 |
|
|
411
|
-
| 目标 AID 未配置推送 | 不推送,消息正常持久化等对方上线 pull |
|
|
412
|
-
| 目标 AID 上线瞬间 | 清空聚合桶,取消待发推送 |
|
|
413
|
-
| E2EE 消息 | 推送内容只含元数据(发送者、数量),不含密文 |
|
|
414
|
-
| 群组消息 | 群内每个离线成员独立聚合,summary 含 group_ids |
|
|
415
|
-
| push_token 过期 | push_notify_aid 丢弃但仍 ack,客户端下次 connect 刷新 token |
|
|
416
|
-
| ack 超时 | 释放槽位,不重试。后续新消息触发新批次时会包含累积通知 |
|
|
417
|
-
| 同一 AID 多设备不同推送配置 | 以最后一次 connect 为准(单条记录覆盖) |
|
|
418
|
-
| 跨域消息推送 | 由目标 AID 所属域的 Gateway 触发,发送方域不参与 |
|
|
419
|
-
| push_notify_aid 跨域 | 不支持,必须与目标 AID 同域 |
|
|
1
|
+
# 15 - 离线推送通知协议 (Push Notification)
|
|
2
|
+
|
|
3
|
+
## 1. 概述
|
|
4
|
+
|
|
5
|
+
当目标 AID 的所有设备均离线时,AUN Gateway 通过事件通知将推送摘要发送给 `push_notify_aid`(推送代理 AID),由其完成最终的平台推送(APNs / FCM / WebPush 等)。
|
|
6
|
+
|
|
7
|
+
**设计原则:**
|
|
8
|
+
|
|
9
|
+
- push_notify_aid 是普通客户端 AID,不是 AUN 内部服务
|
|
10
|
+
- 通过事件通知(非 P2P 消息)下发推送摘要——轻量、实时、不持久化
|
|
11
|
+
- push_token 对 Gateway 完全不透明(opaque),push_notify_aid 自签自验
|
|
12
|
+
- 任意一台设备在线即不触发推送
|
|
13
|
+
- 推送内容仅含元数据,不含消息正文(E2EE 安全保证)
|
|
14
|
+
- 背压控制:串行确认,Gateway 等 push_notify_aid ack 后再发下一批
|
|
15
|
+
- 跨域推送:推送由**目标 AID 所属域**的 Gateway 触发,发送方域不参与
|
|
16
|
+
|
|
17
|
+
---
|
|
18
|
+
|
|
19
|
+
## 2. 架构
|
|
20
|
+
|
|
21
|
+
```mermaid
|
|
22
|
+
graph TB
|
|
23
|
+
Sender[发送方 AID] -->|message.send| GW[Gateway]
|
|
24
|
+
GW -->|目标全部离线| PA[PushAggregator]
|
|
25
|
+
PA -->|event/push.offline_message| GW
|
|
26
|
+
GW -->|事件通知| PNA[push_notify_aid<br/>推送代理客户端]
|
|
27
|
+
PNA -->|push.ack| GW
|
|
28
|
+
PNA -->|平台推送| PLATFORM[APNs / FCM / WebPush]
|
|
29
|
+
PLATFORM -->|通知| Target[目标终端]
|
|
30
|
+
|
|
31
|
+
PNA -.->|connect 到 Gateway 保持在线| GW
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
**关键约束:**
|
|
35
|
+
|
|
36
|
+
- push_notify_aid 作为普通客户端 AID 连接到 Gateway,通过事件通知接收推送摘要
|
|
37
|
+
- push_notify_aid 离线时事件丢弃——推送是 best-effort,消息可靠性由 message.pull 保证
|
|
38
|
+
- 目标 AID 有任意一台设备在线时,不触发推送
|
|
39
|
+
|
|
40
|
+
---
|
|
41
|
+
|
|
42
|
+
## 3. 推送注册流程
|
|
43
|
+
|
|
44
|
+
### 3.1 应用层:客户端向推送代理注册
|
|
45
|
+
|
|
46
|
+
```mermaid
|
|
47
|
+
sequenceDiagram
|
|
48
|
+
participant App as 应用客户端
|
|
49
|
+
participant PNA as push_notify_aid
|
|
50
|
+
|
|
51
|
+
Note over App,PNA: 应用层行为,AUN 协议不规定细节
|
|
52
|
+
App->>PNA: 注册推送(aid, device_id, platform, device_token)
|
|
53
|
+
PNA->>PNA: 生成 push_token(格式自定)
|
|
54
|
+
PNA-->>App: push_token
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
push_token 的格式、签名算法、有效期完全由 push_notify_aid 自行决定。AUN 协议不做任何约束。
|
|
58
|
+
|
|
59
|
+
### 3.2 协议层:connect 时携带推送配置
|
|
60
|
+
|
|
61
|
+
```mermaid
|
|
62
|
+
sequenceDiagram
|
|
63
|
+
participant C as Client
|
|
64
|
+
participant GW as Gateway
|
|
65
|
+
|
|
66
|
+
C->>GW: connect(aid, token, push_notify_aid, push_token)
|
|
67
|
+
GW->>GW: 认证 AID 身份 ✓
|
|
68
|
+
GW->>GW: 持久化 push_config
|
|
69
|
+
GW-->>C: connected
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
---
|
|
73
|
+
|
|
74
|
+
## 4. 离线推送时序
|
|
75
|
+
|
|
76
|
+
```mermaid
|
|
77
|
+
sequenceDiagram
|
|
78
|
+
participant A as Sender AID
|
|
79
|
+
participant GW as Gateway
|
|
80
|
+
participant PA as PushAggregator
|
|
81
|
+
participant PNA as push_notify_aid
|
|
82
|
+
|
|
83
|
+
A->>GW: message.send(to=B, payload=...)
|
|
84
|
+
GW->>GW: 持久化消息 + 查询 B 在线状态
|
|
85
|
+
|
|
86
|
+
alt B 有任意设备在线
|
|
87
|
+
GW->>GW: 投递到 B 的在线 session
|
|
88
|
+
Note over GW: 不触发推送
|
|
89
|
+
else B 全部设备离线
|
|
90
|
+
GW->>PA: enqueue(target=B, from=A, msg_id, ts)
|
|
91
|
+
PA->>PA: 聚合窗口 + 频控 + 背压检查
|
|
92
|
+
|
|
93
|
+
alt 触发推送 且 in_flight < max
|
|
94
|
+
PA->>GW: event/push.offline_message
|
|
95
|
+
GW->>PNA: 事件通知(batch_id, summary, push_token)
|
|
96
|
+
PA->>PA: in_flight++, 启动 ack_timeout
|
|
97
|
+
PNA->>PNA: 验证 push_token ✓ → 发送平台推送
|
|
98
|
+
PNA->>GW: push.ack(batch_id)
|
|
99
|
+
GW->>PA: release(batch_id)
|
|
100
|
+
PA->>PA: in_flight--
|
|
101
|
+
else in_flight = max(背压)
|
|
102
|
+
PA->>PA: 排队等待槽位释放
|
|
103
|
+
else 频控抑制
|
|
104
|
+
PA->>PA: 延迟到下一窗口
|
|
105
|
+
end
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
GW-->>A: ack(msg_id, seq)
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
---
|
|
112
|
+
|
|
113
|
+
## 5. 背压与 in-flight 控制
|
|
114
|
+
|
|
115
|
+
```mermaid
|
|
116
|
+
stateDiagram-v2
|
|
117
|
+
[*] --> Idle: 初始状态
|
|
118
|
+
Idle --> Sending: 有待推送 & in_flight < max
|
|
119
|
+
Sending --> WaitAck: 事件已发出, in_flight++
|
|
120
|
+
WaitAck --> Idle: 收到 push.ack, in_flight--
|
|
121
|
+
WaitAck --> Idle: ack_timeout 超时, in_flight--
|
|
122
|
+
WaitAck --> Queued: 新推送到达但 in_flight = max
|
|
123
|
+
Queued --> Sending: 槽位释放
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
### 参数
|
|
127
|
+
|
|
128
|
+
| 参数 | 默认值 | 说明 |
|
|
129
|
+
|------|--------|------|
|
|
130
|
+
| max_in_flight | 1 | 同一 push_notify_aid 未确认批次上限(串行) |
|
|
131
|
+
| ack_timeout | 30s | 超时未 ack 自动释放槽位 |
|
|
132
|
+
| batch_size | 50 | 每批最多聚合多少个 target_aid 的通知 |
|
|
133
|
+
|
|
134
|
+
### 行为规则
|
|
135
|
+
|
|
136
|
+
- in_flight < max → 发送事件,in_flight++
|
|
137
|
+
- in_flight = max → 排队等待
|
|
138
|
+
- 收到 `push.ack(batch_id)` → in_flight--,触发队列中下一批
|
|
139
|
+
- 超时 → in_flight--,**不重试**(推送是 best-effort,过时推送是噪音)
|
|
140
|
+
- push_notify_aid 离线 → 事件丢弃,in_flight 不增加
|
|
141
|
+
|
|
142
|
+
---
|
|
143
|
+
|
|
144
|
+
## 6. 在线判断规则
|
|
145
|
+
|
|
146
|
+
```mermaid
|
|
147
|
+
flowchart TD
|
|
148
|
+
A[消息到达,目标 AID = B] --> B{B 的在线设备数 > 0?}
|
|
149
|
+
B -->|≥ 1 台在线| C[投递到在线 session,不推送]
|
|
150
|
+
B -->|0 台在线| D{push_config 存在?}
|
|
151
|
+
D -->|是| F[进入 PushAggregator]
|
|
152
|
+
D -->|否| G[仅持久化,等对方上线 pull]
|
|
153
|
+
F --> H[聚合 + 频控 + 背压 → 推送]
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
**边界情况:**
|
|
157
|
+
|
|
158
|
+
- 目标 AID 上线瞬间:清空该 AID 的聚合桶,取消待发推送
|
|
159
|
+
- 最后一台设备断连:不立即触发推送,只有后续新消息到达时发现全离线才走推送路径
|
|
160
|
+
|
|
161
|
+
---
|
|
162
|
+
|
|
163
|
+
## 7. 跨域推送
|
|
164
|
+
|
|
165
|
+
**核心原则:推送由目标 AID 所属域的 Gateway 触发。**
|
|
166
|
+
|
|
167
|
+
发送方域不感知目标域的 push_config 和白名单,也不需要任何跨域配置同步。
|
|
168
|
+
|
|
169
|
+
```mermaid
|
|
170
|
+
sequenceDiagram
|
|
171
|
+
participant A as alice.domain-a.com
|
|
172
|
+
participant GW_A as Gateway A
|
|
173
|
+
participant GW_B as Gateway B
|
|
174
|
+
participant PA_B as PushAggregator B
|
|
175
|
+
participant PNA as push.domain-b.com<br/>(连在 GW_B)
|
|
176
|
+
|
|
177
|
+
A->>GW_A: message.send(to=bob.domain-b.com)
|
|
178
|
+
GW_A->>GW_A: 持久化消息
|
|
179
|
+
GW_A->>GW_B: 跨域 relay 消息
|
|
180
|
+
GW_B->>GW_B: 查询 bob 本地在线状态
|
|
181
|
+
|
|
182
|
+
alt bob 在本域有设备在线
|
|
183
|
+
GW_B->>GW_B: 投递到 bob 的在线 session
|
|
184
|
+
else bob 本域全部离线
|
|
185
|
+
GW_B->>PA_B: enqueue(target=bob, from=alice.domain-a.com)
|
|
186
|
+
PA_B->>GW_B: event/push.offline_message
|
|
187
|
+
GW_B->>PNA: 事件通知
|
|
188
|
+
PNA->>GW_B: push.ack
|
|
189
|
+
end
|
|
190
|
+
|
|
191
|
+
GW_B-->>GW_A: relay ack
|
|
192
|
+
GW_A-->>A: ack
|
|
193
|
+
```
|
|
194
|
+
|
|
195
|
+
**规则:**
|
|
196
|
+
|
|
197
|
+
| 关注点 | 行为 |
|
|
198
|
+
|--------|------|
|
|
199
|
+
| 推送配置存储 | 仅存于目标 AID 所属域,不跨域同步 |
|
|
200
|
+
| 白名单管理 | 各域独立配置 `allowed_notify_aids`,互不影响 |
|
|
201
|
+
| push_notify_aid 必须连接位置 | 目标 AID 所属域的 Gateway |
|
|
202
|
+
| push_notify_aid 跨域时 | 不支持。push_notify_aid 必须与其服务的 AID 同域 |
|
|
203
|
+
| summary.senders 中的跨域 AID | 保留完整 AID(含域名),如 `alice.domain-a.com` |
|
|
204
|
+
|
|
205
|
+
**约束:** push_notify_aid 必须与其服务的目标 AID 处于同一域。如果应用希望在多个域提供推送服务,需要在每个域部署独立的 push_notify_aid 并分别加入白名单。
|
|
206
|
+
|
|
207
|
+
---
|
|
208
|
+
|
|
209
|
+
## 8. 聚合与频控
|
|
210
|
+
|
|
211
|
+
### 8.1 PushAggregator 数据结构
|
|
212
|
+
|
|
213
|
+
每个离线目标 AID 一个聚合桶:
|
|
214
|
+
|
|
215
|
+
```
|
|
216
|
+
bucket[target_aid] = {
|
|
217
|
+
push_notify_aid: "push.myapp.com",
|
|
218
|
+
push_token: "eyJhb...",
|
|
219
|
+
pending: [{from, msg_id, ts}, ...],
|
|
220
|
+
first_enqueue_ts: timestamp,
|
|
221
|
+
last_push_ts: timestamp,
|
|
222
|
+
}
|
|
223
|
+
```
|
|
224
|
+
|
|
225
|
+
### 8.2 去重规则
|
|
226
|
+
|
|
227
|
+
同一 target_aid 在频控窗口内只产生一次推送通知。具体行为:
|
|
228
|
+
|
|
229
|
+
- 首条消息触发推送后,该 target_aid 进入频控冷却期(默认 60s)
|
|
230
|
+
- 冷却期内新消息只更新聚合桶的 summary(unread_count++、senders 去重追加),不产生新推送
|
|
231
|
+
- 冷却期结束时,若桶内有新增未推送内容,合并为一条推送发出
|
|
232
|
+
|
|
233
|
+
效果:无论短时间内收到多少条消息,target_aid 最多每 60s 收到一次推送通知,且 summary 是累积聚合的。
|
|
234
|
+
|
|
235
|
+
### 8.3 触发规则
|
|
236
|
+
|
|
237
|
+
| 规则 | 说明 | 默认值 |
|
|
238
|
+
|------|------|--------|
|
|
239
|
+
| 首条即推 | 桶为空且不在冷却期时,第一条消息立即触发 | 开启 |
|
|
240
|
+
| 窗口聚合 | 首条之后的消息等待窗口合并 | 5 秒 |
|
|
241
|
+
| 数量上限 | 桶内积累 N 条立即触发(不等窗口) | 20 条 |
|
|
242
|
+
|
|
243
|
+
### 8.4 频控规则
|
|
244
|
+
|
|
245
|
+
| 维度 | 限制 | 说明 |
|
|
246
|
+
|------|------|------|
|
|
247
|
+
| 同一 target_aid | 60 秒内最多 1 次推送 | 避免终端刷屏 |
|
|
248
|
+
| 同一 push_notify_aid | 1000 次/分钟 | 保护推送代理服务 |
|
|
249
|
+
| 全局 | 5000 次/分钟 | 系统保护 |
|
|
250
|
+
|
|
251
|
+
频控被触发时消息不丢弃,等窗口过后下一次聚合时一并推送。
|
|
252
|
+
|
|
253
|
+
---
|
|
254
|
+
|
|
255
|
+
## 9. 协议字段
|
|
256
|
+
|
|
257
|
+
### 9.1 connect 扩展字段
|
|
258
|
+
|
|
259
|
+
```json
|
|
260
|
+
{
|
|
261
|
+
"method": "auth.login",
|
|
262
|
+
"params": {
|
|
263
|
+
"aid": "bob.example.com",
|
|
264
|
+
"challenge_response": "...",
|
|
265
|
+
"push_notify_aid": "push.myapp.com",
|
|
266
|
+
"push_token": "eyJhbGciOiJIUzI1NiJ9..."
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
```
|
|
270
|
+
|
|
271
|
+
- `push_notify_aid` 和 `push_token` 均为可选字段
|
|
272
|
+
- 两者必须同时提供或同时不提供
|
|
273
|
+
- 不提供 = 不需要离线推送
|
|
274
|
+
- 每次 connect 覆盖写(最新连接为准)
|
|
275
|
+
|
|
276
|
+
### 9.2 事件通知格式
|
|
277
|
+
|
|
278
|
+
Gateway 向 push_notify_aid 下发的事件通知:
|
|
279
|
+
|
|
280
|
+
```json
|
|
281
|
+
{
|
|
282
|
+
"method": "event/push.offline_message",
|
|
283
|
+
"params": {
|
|
284
|
+
"batch_id": "uuid-xxx",
|
|
285
|
+
"items": [
|
|
286
|
+
{
|
|
287
|
+
"target_aid": "bob.example.com",
|
|
288
|
+
"push_token": "eyJhbGciOiJIUzI1NiJ9...",
|
|
289
|
+
"summary": {
|
|
290
|
+
"unread_count": 3,
|
|
291
|
+
"senders": ["alice.example.com", "charlie.example.com"],
|
|
292
|
+
"latest_ts": 1716100005,
|
|
293
|
+
"group_ids": ["group-uuid-1"]
|
|
294
|
+
}
|
|
295
|
+
}
|
|
296
|
+
]
|
|
297
|
+
}
|
|
298
|
+
}
|
|
299
|
+
```
|
|
300
|
+
|
|
301
|
+
**安全约束:** 不包含消息正文。E2EE 场景下 Gateway 无法解密,推送代理只需知道"有 N 条未读来自谁"即可构造推送文案。
|
|
302
|
+
|
|
303
|
+
### 9.3 push.ack RPC
|
|
304
|
+
|
|
305
|
+
push_notify_aid 处理完一批推送后回调确认:
|
|
306
|
+
|
|
307
|
+
```json
|
|
308
|
+
{
|
|
309
|
+
"method": "push.ack",
|
|
310
|
+
"params": {
|
|
311
|
+
"batch_id": "uuid-xxx"
|
|
312
|
+
}
|
|
313
|
+
}
|
|
314
|
+
```
|
|
315
|
+
|
|
316
|
+
Gateway 收到后释放 in-flight 槽位,触发下一批。
|
|
317
|
+
|
|
318
|
+
### 9.4 push.update_config RPC(可选)
|
|
319
|
+
|
|
320
|
+
允许客户端在不重连的情况下更新推送配置:
|
|
321
|
+
|
|
322
|
+
```json
|
|
323
|
+
{
|
|
324
|
+
"method": "push.update_config",
|
|
325
|
+
"params": {
|
|
326
|
+
"push_notify_aid": "push.myapp.com",
|
|
327
|
+
"push_token": "new-token..."
|
|
328
|
+
}
|
|
329
|
+
}
|
|
330
|
+
```
|
|
331
|
+
|
|
332
|
+
---
|
|
333
|
+
|
|
334
|
+
## 10. push_token 鉴权模型
|
|
335
|
+
|
|
336
|
+
### 10.1 push_notify_aid 白名单
|
|
337
|
+
|
|
338
|
+
Gateway 配置允许的 push_notify_aid 白名单,只有白名单内的 AID 才能被设置为推送代理:
|
|
339
|
+
|
|
340
|
+
- 客户端 connect 时携带的 `push_notify_aid` 不在白名单内 → 忽略该字段,不报错,不存储
|
|
341
|
+
- 白名单为空 → 禁用推送功能
|
|
342
|
+
- 白名单配置在 Gateway 启动配置中,运行时不可动态修改
|
|
343
|
+
|
|
344
|
+
```json
|
|
345
|
+
{
|
|
346
|
+
"push": {
|
|
347
|
+
"allowed_notify_aids": [
|
|
348
|
+
"push.myapp.com",
|
|
349
|
+
"push.partner.com"
|
|
350
|
+
]
|
|
351
|
+
}
|
|
352
|
+
}
|
|
353
|
+
```
|
|
354
|
+
|
|
355
|
+
### 10.2 token 透传模型
|
|
356
|
+
|
|
357
|
+
```mermaid
|
|
358
|
+
sequenceDiagram
|
|
359
|
+
participant PNA as push_notify_aid
|
|
360
|
+
participant GW as Gateway
|
|
361
|
+
|
|
362
|
+
Note over PNA,GW: push_token 生命周期
|
|
363
|
+
PNA->>PNA: 签发 push_token(格式/算法自定)
|
|
364
|
+
Note over GW: Gateway 存储 push_token(opaque bytes)
|
|
365
|
+
Note over GW: 不验签、不解析、不判断过期
|
|
366
|
+
GW->>PNA: event/push.offline_message(..., push_token="xxx")
|
|
367
|
+
PNA->>PNA: 自己验签 push_token
|
|
368
|
+
alt token 有效
|
|
369
|
+
PNA->>PNA: 执行推送
|
|
370
|
+
PNA->>GW: push.ack(batch_id)
|
|
371
|
+
else token 无效/过期
|
|
372
|
+
PNA->>PNA: 丢弃
|
|
373
|
+
PNA->>GW: push.ack(batch_id)
|
|
374
|
+
Note over PNA: 客户端下次 connect 带新 token
|
|
375
|
+
end
|
|
376
|
+
```
|
|
377
|
+
|
|
378
|
+
**职责划分:**
|
|
379
|
+
|
|
380
|
+
| 角色 | 职责 |
|
|
381
|
+
|------|------|
|
|
382
|
+
| push_notify_aid | 签发 token、验证 token、决定格式和有效期、处理后 ack |
|
|
383
|
+
| Gateway | 存储 token、透传 token、不解析不验证、管理 in-flight |
|
|
384
|
+
| Client | 向 push_notify_aid 申请 token、connect 时携带 |
|
|
385
|
+
|
|
386
|
+
---
|
|
387
|
+
|
|
388
|
+
## 11. 持久化
|
|
389
|
+
|
|
390
|
+
### push_config 表
|
|
391
|
+
|
|
392
|
+
```sql
|
|
393
|
+
CREATE TABLE push_config (
|
|
394
|
+
aid VARCHAR(255) PRIMARY KEY,
|
|
395
|
+
push_notify_aid VARCHAR(255) NOT NULL,
|
|
396
|
+
push_token TEXT NOT NULL,
|
|
397
|
+
updated_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP
|
|
398
|
+
);
|
|
399
|
+
```
|
|
400
|
+
|
|
401
|
+
- 随 connect 写入/更新(UPSERT)
|
|
402
|
+
- 可加内存缓存(TTL 5 分钟)
|
|
403
|
+
|
|
404
|
+
---
|
|
405
|
+
|
|
406
|
+
## 12. 边界情况
|
|
407
|
+
|
|
408
|
+
| 场景 | 处理 |
|
|
409
|
+
|------|------|
|
|
410
|
+
| push_notify_aid 离线 | 事件丢弃,不持久化。推送是 best-effort,消息可靠性由 pull 保证 |
|
|
411
|
+
| 目标 AID 未配置推送 | 不推送,消息正常持久化等对方上线 pull |
|
|
412
|
+
| 目标 AID 上线瞬间 | 清空聚合桶,取消待发推送 |
|
|
413
|
+
| E2EE 消息 | 推送内容只含元数据(发送者、数量),不含密文 |
|
|
414
|
+
| 群组消息 | 群内每个离线成员独立聚合,summary 含 group_ids |
|
|
415
|
+
| push_token 过期 | push_notify_aid 丢弃但仍 ack,客户端下次 connect 刷新 token |
|
|
416
|
+
| ack 超时 | 释放槽位,不重试。后续新消息触发新批次时会包含累积通知 |
|
|
417
|
+
| 同一 AID 多设备不同推送配置 | 以最后一次 connect 为准(单条记录覆盖) |
|
|
418
|
+
| 跨域消息推送 | 由目标 AID 所属域的 Gateway 触发,发送方域不参与 |
|
|
419
|
+
| push_notify_aid 跨域 | 不支持,必须与目标 AID 同域 |
|