feat: add idempotent batch task submission and recovery examples
This commit is contained in:
@@ -28,6 +28,11 @@ func NewTaskStore(db *sql.DB) *TaskStore { return &TaskStore{db: db} }
|
||||
|
||||
var _ service.Store = (*TaskStore)(nil)
|
||||
|
||||
// AuthorizeSubmit 用于批量请求的只读预认证;每项事务仍独立校验凭据、动作与队列范围。
|
||||
func (s *TaskStore) AuthorizeSubmit(ctx context.Context, token auth.Token) error {
|
||||
return s.transaction(ctx, token, "tasks:submit", func(*sql.Tx, auth.Permissions) error { return nil })
|
||||
}
|
||||
|
||||
func (s *TaskStore) transaction(ctx context.Context, token auth.Token, action string, fn func(*sql.Tx, auth.Permissions) error) error {
|
||||
return WithTx(ctx, s.db, func(tx *sql.Tx) error {
|
||||
p, err := authenticate(ctx, tx, token)
|
||||
@@ -159,6 +164,12 @@ func (s *TaskStore) Submit(ctx context.Context, token auth.Token, key string, in
|
||||
if !p.AllowsQueue(in.QueueID) {
|
||||
return fault.Forbidden
|
||||
}
|
||||
// 先按既有应用额度锁串行进入受理,再占用幂等唯一键。
|
||||
// 满额回滚时,同键并发INSERT的重复检查锁不能与应用额度锁互相等待。
|
||||
// 此处只取得锁,不检查/扣减额度;已有回执在满额时仍可返回。
|
||||
if _, err := lockApplicationResources(ctx, tx, token.NamespaceID, false); err != nil {
|
||||
return err
|
||||
}
|
||||
taskID, err := core.NewID()
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -174,7 +185,7 @@ func (s *TaskStore) Submit(ctx context.Context, token auth.Token, key string, in
|
||||
out.Deduplicated = true
|
||||
return nil
|
||||
}
|
||||
if _, _, err := lockQueue(ctx, tx, token.NamespaceID, in.QueueID); err != nil {
|
||||
if _, _, err := lockQueueAfterApplication(ctx, tx, token.NamespaceID, in.QueueID); err != nil {
|
||||
return err
|
||||
}
|
||||
now, err := dbNow(ctx, tx)
|
||||
|
||||
Reference in New Issue
Block a user