From 9249dc18319e83b5757342077f28d6ba08e105df Mon Sep 17 00:00:00 2001 From: Naman Jain Date: Wed, 9 Sep 2020 17:42:44 +0530 Subject: [PATCH] Fix Sequence generates duplicate values (#1281) (#1500) Fix issue https://github.com/dgraph-io/badger/issues/1280 (cherry picked from commit fa94030a483889c25ce32443ef72c8254b3d294b) Co-authored-by: GameXG --- db.go | 23 ++++++++++++++++++++--- db_test.go | 27 +++++++++++++++++++++++++++ 2 files changed, 47 insertions(+), 3 deletions(-) diff --git a/db.go b/db.go index 6d9cbb123..bc7023eb1 100644 --- a/db.go +++ b/db.go @@ -1110,9 +1110,26 @@ func (seq *Sequence) Release() error { seq.Lock() defer seq.Unlock() err := seq.db.Update(func(txn *Txn) error { - var buf [8]byte - binary.BigEndian.PutUint64(buf[:], seq.next) - return txn.SetEntry(NewEntry(seq.key, buf[:])) + item, err := txn.Get(seq.key) + if err != nil { + return err + } + + var num uint64 + if err := item.Value(func(v []byte) error { + num = binary.BigEndian.Uint64(v) + return nil + }); err != nil { + return err + } + + if num == seq.leased { + var buf [8]byte + binary.BigEndian.PutUint64(buf[:], seq.next) + return txn.SetEntry(NewEntry(seq.key, buf[:])) + } + + return nil }) if err != nil { return err diff --git a/db_test.go b/db_test.go index 2ecc660be..f47d598ad 100644 --- a/db_test.go +++ b/db_test.go @@ -1373,6 +1373,33 @@ func TestSequence_Release(t *testing.T) { }) } +func TestTestSequence2(t *testing.T) { + runBadgerTest(t, nil, func(t *testing.T, db *DB) { + key := []byte("key") + seq1, err := db.GetSequence(key, 2) + require.NoError(t, err) + + seq2, err := db.GetSequence(key, 2) + require.NoError(t, err) + num, err := seq2.Next() + require.NoError(t, err) + require.Equal(t, uint64(2), num) + + require.NoError(t, seq2.Release()) + require.NoError(t, seq1.Release()) + + seq3, err := db.GetSequence(key, 2) + require.NoError(t, err) + for i := 0; i < 5; i++ { + num2, err := seq3.Next() + require.NoError(t, err) + require.Equal(t, uint64(i)+3, num2) + } + + require.NoError(t, seq3.Release()) + }) +} + func TestReadOnly(t *testing.T) { dir, err := ioutil.TempDir("", "badger-test") require.NoError(t, err)