package tasklist // memory_store.go 实现基于 map + mutex 的内存 Store. // // 模块定位: // // MemoryStore 是 tasklist.Store 接口的同进程默认实现 -- // 零外部依赖, dogfood CLI / 单元测试 / 单实例 SaaS 场景首选. // // 核心设计决策: // 1. sync.RWMutex (vs. sync.Mutex): // List 是读密集操作, 多 Worker 频繁查看板; 写操作 (CAS) 相对少. // RWMutex 让 List 并发进行, 提升吞吐. // 精妙之处(CLEVER): Go 标准库 sync.RWMutex 针对此场景优化, 写少读多 // 可显著降低争用. // 2. CAS 走 sync.Mutex 写锁: // 读-改-写必须持有写锁, 否则两个 goroutine 同时读到 v=1 会冲突. // 替代方案: - 否决: // Task 是大结构体, 指针操作需要 interface 转换和额外分配, 反而更慢. // 3. Close 幂等 (对齐 MemoryInbox): // 多次调用不 panic, 消费层生命周期管理更友好. import ( "context" "sort" "sync" ) // MemoryStore 是 tasklist.Store 的同进程实现. type MemoryStore struct { mu sync.RWMutex tasks map[string]Task } // NewMemoryStore 创建空的内存 Store. func NewMemoryStore() *MemoryStore { return &MemoryStore{ tasks: make(map[string]Task), } } // Get 读取任务. 不存在返回 ErrTaskNotFound. func (s *MemoryStore) Get(ctx context.Context, id string) (Task, error) { s.mu.RLock() defer s.mu.RUnlock() t, ok := s.tasks[id] if !ok { return Task{}, ErrTaskNotFound } return t, nil } // CAS 原子比较并交换. // // expectedVersion == 0 语义: 新增任务, 仅当 id 不存在时成功. // 否则: 现有 Version 必须等于 expectedVersion 才写入, 不等返回 ErrConcurrentModification. func (s *MemoryStore) CAS(ctx context.Context, id string, expectedVersion int, newTask Task) error { s.mu.Lock() defer s.mu.Unlock() current, exists := s.tasks[id] if expectedVersion == 0 { // 新增模式 if exists { return ErrTaskAlreadyExists } s.tasks[id] = newTask return nil } // 更新模式 if !exists { return ErrTaskNotFound } if current.Version != expectedVersion { return ErrConcurrentModification } s.tasks[id] = newTask return nil } // List 返回所有任务 (按 CreatedAt 升序). // // 精妙之处(CLEVER): 返回切片副本而非 map values -- // 调用方可自由排序 / 过滤, 不影响内部状态; map 遍历顺序不稳定, // 副本排序后语义明确. func (s *MemoryStore) List(ctx context.Context) ([]Task, error) { s.mu.RLock() defer s.mu.RUnlock() out := make([]Task, 0, len(s.tasks)) for _, t := range s.tasks { out = append(out, t) } sort.Slice(out, func(i, j int) bool { return out[i].CreatedAt.Before(out[j].CreatedAt) }) return out, nil } // Close 无操作返回 nil (内存 Store 无需清理). func (s *MemoryStore) Close() error { return nil } // 编译时接口检查. var _ Store = (*MemoryStore)(nil)