package common import "context" // serialWriter 单写者执行器:所有 SQLite 写链路(含「查订单→算 expiresAt→更新订单→写 license→ // 清缓存」等读改写事务)排入同一 goroutine 串行执行,规避无 WAL 时并发写 "database is locked"; // 任务结果经 buffered channel 回调用方,不额外开池(写路径天然无并行点)。 type serialWriter struct { jobs chan func() } var serial = &serialWriter{jobs: make(chan func(), 64)} func init() { go func() { for f := range serial.jobs { f() } }() } // Serial 返回进程级单写者:SQLite 写操作必须经此串行执行。 func Serial() *serialWriter { return serial } // Submit 排队执行写任务并等待结果,返回任务的 error;ctx 取消/超时不再等待。 // 已排队未执行的任务在 ctx 取消后仍会执行(结果入 buffered channel 无泄漏), // 调用方以返回的 ctx.Err() 为准不再消费其结果。 func (w *serialWriter) Submit(ctx context.Context, fn func() error) error { res := make(chan error, 1) select { case w.jobs <- func() { res <- fn() }: case <-ctx.Done(): return ctx.Err() } select { case err := <-res: return err case <-ctx.Done(): return ctx.Err() } }