Skip to content

Commit 3110230

Browse files
authored
Merge pull request #32 from raulk/getexpiration
Ability to get entry expirations
2 parents ee73605 + 0c44ff1 commit 3110230

File tree

4 files changed

+102
-6
lines changed

4 files changed

+102
-6
lines changed

.gx/lastpubver

+1-1
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
1.6.1: QmUCfrikzKVGAfpE31RPwPd32fu1DYxSG7HTGCadba5Wza
1+
1.7.0: QmaiEBFgkgB1wjrPRxru5PyXPEkx58WuMjXNaR1Q9QNRjn

datastore.go

+22-2
Original file line numberDiff line numberDiff line change
@@ -73,8 +73,7 @@ func NewDatastore(path string, options *Options) (*Datastore, error) {
7373
}
7474

7575
return &Datastore{
76-
DB: kv,
77-
76+
DB: kv,
7877
gcDiscardRatio: gcDiscardRatio,
7978
}, nil
8079
}
@@ -125,6 +124,13 @@ func (d *Datastore) SetTTL(key ds.Key, ttl time.Duration) error {
125124
return txn.Commit()
126125
}
127126

127+
func (d *Datastore) GetExpiration(key ds.Key) (time.Time, error) {
128+
txn := d.newImplicitTransaction(false).(*txn)
129+
defer txn.Discard()
130+
131+
return txn.GetExpiration(key)
132+
}
133+
128134
func (d *Datastore) Get(key ds.Key) (value []byte, err error) {
129135
txn := d.newImplicitTransaction(true)
130136
defer txn.Discard()
@@ -192,6 +198,16 @@ func (t *txn) PutWithTTL(key ds.Key, value []byte, ttl time.Duration) error {
192198
return t.txn.SetWithTTL(key.Bytes(), value, ttl)
193199
}
194200

201+
func (t *txn) GetExpiration(key ds.Key) (time.Time, error) {
202+
item, err := t.txn.Get(key.Bytes())
203+
if err == badger.ErrKeyNotFound {
204+
return time.Time{}, ds.ErrNotFound
205+
} else if err != nil {
206+
return time.Time{}, err
207+
}
208+
return time.Unix(int64(item.ExpiresAt()), 0), nil
209+
}
210+
195211
func (t *txn) SetTTL(key ds.Key, ttl time.Duration) error {
196212
data, err := t.Get(key)
197213
if err != nil {
@@ -286,6 +302,10 @@ func (t *txn) Query(q dsq.Query) (dsq.Results, error) {
286302
result = dsq.Result{Entry: e}
287303
}
288304

305+
if q.ReturnExpirations {
306+
result.Expiration = time.Unix(int64(item.ExpiresAt()), 0)
307+
}
308+
289309
select {
290310
case qrb.Output <- result:
291311
case <-worker.Closing(): // client told us to close early

ds_test.go

+76
Original file line numberDiff line numberDiff line change
@@ -672,3 +672,79 @@ func TestTTL(t *testing.T) {
672672

673673
d.Close()
674674
}
675+
676+
func TestExpirations(t *testing.T) {
677+
var err error
678+
679+
d, done := newDS(t)
680+
defer done()
681+
682+
txn := d.NewTransaction(false)
683+
ttltxn := txn.(ds.TTLDatastore)
684+
defer txn.Discard()
685+
686+
key := ds.NewKey("/abc/def")
687+
val := make([]byte, 32)
688+
if n, err := rand.Read(val); n != 32 || err != nil {
689+
t.Fatal("source of randomness failed")
690+
}
691+
692+
ttl := time.Hour
693+
now := time.Now()
694+
tgt := now.Add(ttl)
695+
696+
if err = ttltxn.PutWithTTL(key, val, ttl); err != nil {
697+
t.Fatalf("adding with ttl failed: %v", err)
698+
}
699+
700+
if err = txn.Commit(); err != nil {
701+
t.Fatalf("commiting transaction failed: %v", err)
702+
}
703+
704+
// Second transaction to retrieve expirations.
705+
txn = d.NewTransaction(true)
706+
ttltxn = txn.(ds.TTLDatastore)
707+
defer txn.Discard()
708+
709+
// GetExpiration returns expected value.
710+
var dsExp time.Time
711+
if dsExp, err = ttltxn.GetExpiration(key); err != nil {
712+
t.Fatalf("getting expiration failed: %v", err)
713+
} else if tgt.Sub(dsExp) >= 5*time.Second {
714+
t.Fatal("expiration returned by datastore not within the expected range (tolerance: 5 seconds)")
715+
} else if tgt.Sub(dsExp) < 0 {
716+
t.Fatal("expiration returned by datastore was earlier than expected")
717+
}
718+
719+
// Iterator returns expected value.
720+
q := dsq.Query{
721+
ReturnExpirations: true,
722+
KeysOnly: true,
723+
}
724+
var ress dsq.Results
725+
if ress, err = txn.Query(q); err != nil {
726+
t.Fatalf("querying datastore failed: %v", err)
727+
}
728+
729+
defer ress.Close()
730+
if res, ok := ress.NextSync(); !ok {
731+
t.Fatal("expected 1 result in iterator")
732+
} else if res.Expiration != dsExp {
733+
t.Fatalf("expiration returned from iterator differs from GetExpiration, expected: %v, actual: %v", dsExp, res.Expiration)
734+
}
735+
736+
if _, ok := ress.NextSync(); ok {
737+
t.Fatal("expected no more results in iterator")
738+
}
739+
740+
// Datastore->GetExpiration()
741+
if exp, err := d.GetExpiration(key); err != nil {
742+
t.Fatalf("querying datastore failed: %v", err)
743+
} else if exp != dsExp {
744+
t.Fatalf("expiration returned from DB differs from that returned by txn, expected: %v, actual: %v", dsExp, exp)
745+
}
746+
747+
if _, err := d.GetExpiration(ds.NewKey("/foo/bar")); err != ds.ErrNotFound {
748+
t.Fatalf("wrong error type: %v", err)
749+
}
750+
}

package.json

+3-3
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,9 @@
1515
},
1616
{
1717
"author": "jbenet",
18-
"hash": "QmSpg1CvpXQQow5ernt1gNBXaXV6yxyNqi7XoeerWfzB5w",
18+
"hash": "QmUyz7JTJzgegC6tiJrfby3mPhzcdswVtG4x58TQ6pq8jV",
1919
"name": "go-datastore",
20-
"version": "3.1.0"
20+
"version": "3.2.0"
2121
},
2222
{
2323
"author": "dgraph-io",
@@ -37,6 +37,6 @@
3737
"license": "",
3838
"name": "go-ds-badger",
3939
"releaseCmd": "git commit -a -m \"gx publish $VERSION\"",
40-
"version": "1.6.1"
40+
"version": "1.7.0"
4141
}
4242

0 commit comments

Comments
 (0)