From 563a4dfb78aaa97febd0763e9f81a740af0dd666 Mon Sep 17 00:00:00 2001 From: Runxi Yu Date: Sat, 7 Mar 2026 19:37:20 +0800 Subject: refstore/files: Implement batching --- refstore/files/batch_apply.go | 70 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 70 insertions(+) create mode 100644 refstore/files/batch_apply.go (limited to 'refstore/files/batch_apply.go') diff --git a/refstore/files/batch_apply.go b/refstore/files/batch_apply.go new file mode 100644 index 00000000..4274df0b --- /dev/null +++ b/refstore/files/batch_apply.go @@ -0,0 +1,70 @@ +package files + +import ( + "errors" + + "codeberg.org/lindenii/furgit/refstore" +) + +func (batch *Batch) Apply() ([]refstore.BatchResult, error) { + if batch.closed { + return nil, errors.New("refstore/files: batch already closed") + } + + results := make([]refstore.BatchResult, len(batch.ops)) + seen := make(map[string]struct{}, len(batch.ops)) + + for i, op := range batch.ops { + results[i].Name = op.name + + if _, exists := seen[op.name]; exists { + batch.closed = true + + err := errors.New("refstore/files: duplicate batch operation for " + `"` + op.name + `"`) + for j := i; j < len(results); j++ { + results[j].Name = batch.ops[j].name + results[j].Error = err + } + + return results, err + } + + seen[op.name] = struct{}{} + } + + for i, op := range batch.ops { + tx := &Transaction{ + store: batch.store, + ops: []txOp{op}, + } + + if err := tx.validateOp(op); err != nil { + results[i].Error = err + continue + } + + err := tx.Commit() + if err == nil { + continue + } + + if isBatchRejected(err) { + results[i].Error = err + continue + } + + batch.closed = true + results[i].Error = err + + for j := i + 1; j < len(results); j++ { + results[j].Name = batch.ops[j].name + results[j].Error = err + } + + return results, err + } + + batch.closed = true + + return results, nil +} -- cgit v1.3.1-10-gc9f91