mirror of
https://github.com/seaweedfs/seaweedfs.git
synced 2026-11-07 04:27:49 +01:00
filer: mark a store transaction independently of the store's own key
ArangoDB and FoundationDB keep their transaction under other context keys, so the CreateEntry guard keyed on "tx" missed them. The filer now marks every context returned by BeginTransaction and the guard checks that marker. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
b7dfff6616
commit
bd0505eb80
2 files changed
+16
-9
No files matched your search
+13
-7
@@ -451,8 +451,16 @@ func (fs *Filer) GetMaster(ctx context.Context) pb.ServerAddress {
|
||||
return fs.MasterClient.GetMaster(ctx)
|
||||
}
|
||||
|
||||
// storeTransactionKey marks a context inside BeginTransaction, whatever key
|
||||
// the store keeps its own transaction under.
|
||||
type storeTransactionKey struct{}
|
||||
|
||||
func (f *Filer) BeginTransaction(ctx context.Context) (context.Context, error) {
|
||||
return f.Store.BeginTransaction(ctx)
|
||||
txCtx, err := f.Store.BeginTransaction(ctx)
|
||||
if err != nil {
|
||||
return txCtx, err
|
||||
}
|
||||
return context.WithValue(txCtx, storeTransactionKey{}, true), nil
|
||||
}
|
||||
|
||||
func (f *Filer) CommitTransaction(ctx context.Context) error {
|
||||
@@ -516,13 +524,11 @@ func (f *Filer) CreateEntry(ctx context.Context, entry *Entry, existing *Entry,
|
||||
oldEntry := existing
|
||||
if oldEntry == nil {
|
||||
var findErr error
|
||||
// Inside a store transaction the lookup must not run the lazy remote
|
||||
// fetch: the fetch persists on a second connection, which waits on
|
||||
// the row lock this transaction holds when it deleted the path (a
|
||||
// rename onto an existing target). The create writes the path either
|
||||
// way; reads inside the transaction keep the fetch.
|
||||
// A lazy fetch here would persist outside the transaction and wait on
|
||||
// the lock it holds for a target it just deleted; the create writes
|
||||
// the path either way.
|
||||
findCtx := ctx
|
||||
if ctx.Value("tx") != nil {
|
||||
if ctx.Value(storeTransactionKey{}) != nil {
|
||||
findCtx = context.WithValue(ctx, lazyFetchContextKey{}, true)
|
||||
}
|
||||
oldEntry, findErr = f.FindEntry(findCtx, entry.FullPath)
|
||||
|
||||
@@ -743,8 +743,9 @@ func TestCreateEntry_SkipsTheLazyFetchInsideAStoreTransaction(t *testing.T) {
|
||||
}
|
||||
f, store := newMountedTestFiler(t, storageType, countingStub, 0)
|
||||
putDirEntry(store, "/buckets/mybucket/dir")
|
||||
// the key a store transaction travels under (abstract_sql getTxOrDB)
|
||||
txCtx := context.WithValue(context.Background(), "tx", struct{}{})
|
||||
// the stub opens no transaction of its own; the filer marks it anyway
|
||||
txCtx, err := f.BeginTransaction(context.Background())
|
||||
require.NoError(t, err)
|
||||
|
||||
// a create inside the transaction: its lookup does not consult the
|
||||
// remote, the entry is inserted as given
|
||||
|
||||
Reference in new issue
Block a user