Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 10 additions & 10 deletions buntdb.go
Original file line number Diff line number Diff line change
Expand Up @@ -913,16 +913,16 @@ func (db *DB) readLoad(rd io.Reader, modTime time.Time) (n int64, err error) {
} else {
exat = time.Unix(ex, 0)
}
if exat.After(now) {
db.insertIntoDatabase(&dbItem{
key: parts[1],
val: parts[2],
opts: &dbItemOpts{
ex: true,
exat: exat,
},
})
}
// just insert there and update in case of the TTL changed
// even if the key expired already, we still have enough infomation to get with ignoreExpired before any shrink.
db.insertIntoDatabase(&dbItem{
key: parts[1],
val: parts[2],
opts: &dbItemOpts{
ex: true,
exat: exat,
},
})
} else {
db.insertIntoDatabase(&dbItem{key: parts[1], val: parts[2]})
}
Expand Down
57 changes: 53 additions & 4 deletions buntdb_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2499,10 +2499,10 @@ func Benchmark_Descend_10000(t *testing.B) {
}

/*
func Benchmark_Spatial_2D(t *testing.B) {
N := 100000
db, _, _ := benchOpenFillData(t, N, true, true, false, true, 100)
defer benchClose(t, false, db)
func Benchmark_Spatial_2D(t *testing.B) {
N := 100000
db, _, _ := benchOpenFillData(t, N, true, true, false, true, 100)
defer benchClose(t, false, db)

}
*/
Expand Down Expand Up @@ -2918,3 +2918,52 @@ func TestWrappedError(t *testing.T) {
}()
panicErr(errors.New("my fake error"))
}

func TestKeyExpiredAfterCloseAndBeforeReopen(t *testing.T) {
// This tests an bug identified in Issue #112.
// A SET without TTL followed by another SET with TTL on the same key,
// and accidentally the key expired after the db closed therefor the key wasn't
// DEL by backgroundManager. On the next time we load the db, Oops,
// db.readLoad just ignore the second OP and remains the first one.

f, err := os.CreateTemp("", "")
if err != nil {
panicErr(err)
}
defer os.Remove(f.Name())
defer f.Close()

db, err := Open(f.Name())
if err != nil {
panicErr(err)
}
err = db.Update(func(tx *Tx) error {
_, _, err := tx.Set("key:112", "value:112-old", nil)
return err
})
if err != nil {
panicErr(err)
}
err = db.Update(func(tx *Tx) error {
_, _, err := tx.Set("key:112", "value:112", &SetOptions{Expires: true, TTL: time.Second})
return err
})
if err != nil {
panicErr(err)
}
db.Close()

// make sure the key expired
time.Sleep(time.Second)

db, err = Open(f.Name())
if err != nil {
panicErr(err)
}
err = db.View(func(tx *Tx) error {
_, err := tx.Get("key:112")
return err
})
assert.Assert(err == ErrNotFound)

}