fix: 推送 meta 用 UseNumber 保留超过 2^53 的整数
This commit is contained in:
@@ -509,6 +509,15 @@
|
|||||||
- 备选方案:把桶挪到 broker 层(B-09 范围)。
|
- 备选方案:把桶挪到 broker 层(B-09 范围)。
|
||||||
- 影响:开放注册后的非 send 请求也计入配额;直接调 `Submit` 的单测不再覆盖限速。
|
- 影响:开放注册后的非 send 请求也计入配额;直接调 `Submit` 的单测不再覆盖限速。
|
||||||
|
|
||||||
|
### 复审修复 C-06
|
||||||
|
|
||||||
|
1. **推送 meta 数字用 UseNumber 解码**
|
||||||
|
- 原条款:PRD F07 / D11 自定义键值送达应与提交一致。
|
||||||
|
- 实际做法:`decodeMetaJSON` 改用 `protocol.Unmarshal`(`UseNumber`),超过 2^53 的整数以 `json.Number` 保留原文再编码进推送帧。不改 `Msg.Meta` 类型与协议包。
|
||||||
|
- 原因:标准 `json.Unmarshal` 把数字变成 float64,雪花 ID 会被改掉。
|
||||||
|
- 备选方案:`Meta` 改为 `json.RawMessage` 原样输出(需改 protocol,牵动 SDK)。
|
||||||
|
- 影响:仅推送路径;入库仍是提交时的规范 JSON。
|
||||||
|
|
||||||
## 身份 I
|
## 身份 I
|
||||||
|
|
||||||
### I1 2026-09-30
|
### I1 2026-09-30
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
package message
|
package message
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bytes"
|
||||||
"context"
|
"context"
|
||||||
"database/sql"
|
"database/sql"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
@@ -742,3 +743,37 @@ func TestPushRevokedOnRecallAfterPush(t *testing.T) {
|
|||||||
t.Fatal("expected revoked frame")
|
t.Fatal("expected revoked frame")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestPushPreservesLargeMetaInteger(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
raw := `{"id":12345678901234567890}`
|
||||||
|
decoded := decodeMetaJSON(raw)
|
||||||
|
n, ok := decoded["id"].(json.Number)
|
||||||
|
if !ok || n.String() != "12345678901234567890" {
|
||||||
|
t.Fatalf("decode meta=%v", decoded)
|
||||||
|
}
|
||||||
|
|
||||||
|
e := openDeliveryEnv(t, nil)
|
||||||
|
insertEndpoint(t, e.db, "alice", "", 1, 0)
|
||||||
|
insertEndpoint(t, e.db, "bob", "", 1, 0)
|
||||||
|
e.online("bob", "c-bob")
|
||||||
|
ctx := context.Background()
|
||||||
|
req := baseSend("meta-big", "bob")
|
||||||
|
req.Meta = map[string]any{"id": json.Number("12345678901234567890")}
|
||||||
|
if _, err := e.app.Submit(ctx, "alice", port.ConnInfo{}, req); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
if err := e.app.PushPending(ctx, "bob", "c-bob"); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
found := false
|
||||||
|
for _, p := range e.down.Snapshots() {
|
||||||
|
if bytes.Contains(p.Payload, []byte("12345678901234567890")) {
|
||||||
|
found = true
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if !found {
|
||||||
|
t.Fatalf("push payloads missing large int: %v", e.down.Snapshots())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -3,7 +3,6 @@ package message
|
|||||||
import (
|
import (
|
||||||
"database/sql"
|
"database/sql"
|
||||||
"encoding/base64"
|
"encoding/base64"
|
||||||
"encoding/json"
|
|
||||||
|
|
||||||
"git.asio.asia/nixevol/NixMsg/internal/protocol"
|
"git.asio.asia/nixevol/NixMsg/internal/protocol"
|
||||||
)
|
)
|
||||||
@@ -94,7 +93,7 @@ func (a *App) dispatchFullTx(tx *sql.Tx, seq int64, senderID, destKind, destID s
|
|||||||
SELECT gm.endpoint_id, e.enabled
|
SELECT gm.endpoint_id, e.enabled
|
||||||
FROM group_members gm
|
FROM group_members gm
|
||||||
JOIN endpoints e ON e.id = gm.endpoint_id
|
JOIN endpoints e ON e.id = gm.endpoint_id
|
||||||
WHERE gm.group_id = ? AND gm.endpoint_id != ?`, destID, senderID)
|
WHERE gm.group_id = ? AND gm.endpoint_id != ? AND gm.joined_at <= ?`, destID, senderID, sendAt)
|
||||||
if qErr != nil {
|
if qErr != nil {
|
||||||
return "", true, qErr
|
return "", true, qErr
|
||||||
}
|
}
|
||||||
@@ -342,7 +341,7 @@ func decodeMetaJSON(s string) map[string]any {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
var m map[string]any
|
var m map[string]any
|
||||||
if err := json.Unmarshal([]byte(s), &m); err != nil {
|
if err := protocol.Unmarshal([]byte(s), &m); err != nil {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
return m
|
return m
|
||||||
|
|||||||
Reference in New Issue
Block a user