Files
NixMsg/internal/store/queue.go
T

63 lines
1.3 KiB
Go

package store
import (
"context"
"database/sql"
"errors"
"sync"
)
// ErrQueueClosed 表示写入队列已关闭。
var ErrQueueClosed = errors.New("store: write queue closed")
// WriteFunc 在单个写事务中执行的操作。
type WriteFunc func(tx *sql.Tx) error
// Queue 写入队列:提交一个写操作并拿到结果。
//
// 本任务(T0.3)实现为互斥串行的一操作一事务,不做合并;DEVELOPMENT 7.2
// 要求的写 goroutine 合并提交(最多 256 个或凑满 2ms、SAVEPOINT 隔离失败)留给 P2。
type Queue struct {
db *sql.DB
mu sync.Mutex
closed bool
}
// NewQueue 创建简单写入队列(一操作一事务)。
func NewQueue(db *sql.DB) *Queue {
return &Queue{db: db}
}
// Do 提交写操作并等待提交结果。
func (q *Queue) Do(ctx context.Context, fn WriteFunc) error {
if fn == nil {
return errors.New("store: nil write func")
}
q.mu.Lock()
defer q.mu.Unlock()
if q.closed {
return ErrQueueClosed
}
if err := ctx.Err(); err != nil {
return err
}
tx, err := q.db.BeginTx(ctx, nil)
if err != nil {
return err
}
if err := fn(tx); err != nil {
_ = tx.Rollback()
return err
}
return tx.Commit()
}
// Close 关闭队列,之后 Do 返回 ErrQueueClosed。
func (q *Queue) Close() error {
q.mu.Lock()
defer q.mu.Unlock()
q.closed = true
return nil
}