50 lines
1.8 KiB
Go
50 lines
1.8 KiB
Go
package models
|
|
|
|
import (
|
|
"encoding/json"
|
|
"sync"
|
|
"time"
|
|
)
|
|
|
|
var _ = json.RawMessage{}
|
|
var _ = sync.Mutex{}
|
|
var _ = time.Now
|
|
|
|
//
|
|
// Durable log of every RPC method the server has no semantic handler for yet.
|
|
// Writes to logs/unknown-methods.log so future work can replay shapes
|
|
// (method id + name, body length, hex prefix). Return behavior of callers is unchanged.
|
|
//
|
|
//
|
|
// ⛑ 2026-09-30 加按 methodId 节流(原因见下)。此前是「一次调用一行」,
|
|
// 而实机证明高频 Notify 会把这里打成洪水:AskOnMetroEnterStation 累计 4.8 万次、
|
|
// AskOnMetroExitStation 4.7 万次、ReportSetActionGroup 2.4 万次、AskTriggerPlotEvent 1.3 万次,
|
|
// 日志涨到 39 MB 且每次调用都要 lock + File.AppendAllText(开-写-关)。
|
|
// 现在:每个 id 首次必写完整行(保留取证/差集能力),
|
|
// 之后在 RepeatFlushSeconds 窗口内只累加计数不落盘,
|
|
// 窗口到点写一条 REPEAT 汇总。落盘次数从 O(调用数) 降到 O(id 数 × 时长/窗口)。
|
|
//
|
|
type UnknownMethodLogger struct {
|
|
SyncRoot any `json:"syncRoot"`
|
|
LogPath *string `json:"_logPath"`
|
|
States map[uint32]ThrottleState `json:"states"`
|
|
}
|
|
|
|
const (
|
|
UnknownMethodLogger_MaxHexBytesPerLine int32 = 256
|
|
UnknownMethodLogger_RepeatFlushSeconds int32 = 60
|
|
UnknownMethodLogger_TailReadBytes int32 = 64 * 1024
|
|
)
|
|
|
|
type ThrottleState struct {
|
|
// 自上次落盘以来累计的调用次数。
|
|
Pending int32 `json:"pending"`
|
|
// 上次真正落盘的时间(UTC)。仅在 SyncRoot 内读写。
|
|
LastWriteUtc time.Time `json:"lastWriteUtc"`
|
|
// 是否已写过首行(首行含 hex,是取证关键)。仅在 SyncRoot 内写。
|
|
Seen bool `json:"seen"`
|
|
// Seen 的 volatile 镜像,用于无锁快路径判定。
|
|
SeenFlag int32 `json:"seenFlag"`
|
|
}
|
|
|