fix(persist,channel): 同类定宽时间戳修复 — checkpoint 恢复与渠道会话列表排序
- persist: formatTime 定宽;loadLatestSQL 补 rowid 兜底;New 时归一化历史行(避免 LoadLatest 挑到更旧检查点) - channel/session: 写入定宽;listSessionSQL 补 rowid 兜底;核实无 INSERT 吃 DDL 默认值,故只加注释不改默认值 - 新增回归测试并做变异验证(改回 RFC3339Nano 即 FAIL)
This commit is contained in:
1 parent
31086ed1ab
commit
fbbfcc95ee
7 files changed
+445
-14
No files matched your search
@@ -19,6 +19,11 @@ import (
|
||||
// channel maps to exactly one internal session_id. created_at/updated_at follow
|
||||
// the project's timestamp convention; actor_role records the identity lane so the
|
||||
// mapping survives restarts.
|
||||
//
|
||||
// The created_at/updated_at DEFAULT expressions are a fallback only: every write
|
||||
// path (insertOrIgnoreSessionSQL) supplies explicit fixed-width UTC timestamps
|
||||
// via formatSessionTime, so the 3-digit-millisecond strftime defaults are never
|
||||
// exercised and no row mixes timestamp widths.
|
||||
const createTableSQL = `
|
||||
CREATE TABLE IF NOT EXISTS channel_sessions (
|
||||
platform TEXT NOT NULL,
|
||||
@@ -43,10 +48,13 @@ SELECT session_id FROM channel_sessions WHERE platform = ? AND channel_id = ?`
|
||||
|
||||
// listSessionsSQL selects every persisted channel mapping, newest first. Group
|
||||
// sessions key on a channel_id carrying groupChannelPrefix; direct sessions use
|
||||
// their channel id.
|
||||
// their channel id. created_at is fixed-width UTC text (see sessionTimeLayout),
|
||||
// so its text order is its time order; rowid breaks created_at ties so mappings
|
||||
// written in the same coarse clock tick still list in a stable order
|
||||
// (channel_sessions is an ordinary rowid table, not WITHOUT ROWID).
|
||||
const listSessionSQL = `
|
||||
SELECT platform, channel_id, session_id, actor_role FROM channel_sessions
|
||||
ORDER BY created_at DESC`
|
||||
ORDER BY created_at DESC, rowid DESC`
|
||||
|
||||
// groupChannelPrefix marks a channel id as a group conversation so a session
|
||||
// reconstructed from the backing table (where no IsGroup flag is persisted) can
|
||||
@@ -178,7 +186,7 @@ func (m *SessionManager) lookupCached(key string) (Session, bool) {
|
||||
// winning writer's session_id becomes the binding. It is called under the write
|
||||
// lock so the in-memory cache and the table stay in agreement.
|
||||
func (m *SessionManager) persist(ctx context.Context, platform, cid string, actor adapter.Actor) (string, error) {
|
||||
now := time.Now().UTC().Format(time.RFC3339Nano)
|
||||
now := formatSessionTime(time.Now())
|
||||
if _, err := m.db.ExecContext(ctx, insertOrIgnoreSessionSQL, platform, cid, newSessionID(), string(actor.Role), now, now); err != nil {
|
||||
return "", fmt.Errorf("session: persist %s/%s: %w", platform, cid, err)
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user