Skip to content

Commit b4f00d7

Browse files
added support for nil values (#14)
* added support for nil values in indices * added context to collection.Find
1 parent 1efadc8 commit b4f00d7

12 files changed

+248
-350
lines changed

collection.go

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
package leia
2121

2222
import (
23+
"context"
2324
"crypto/sha1"
2425
"errors"
2526

@@ -55,7 +56,9 @@ type Collection interface {
5556
Delete(doc Document) error
5657
// Find queries the collection for documents
5758
// returns ErrNoIndex when no suitable index can be found
58-
Find(query Query) ([]Document, error)
59+
// returns context errors when the context has been cancelled or deadline has exceeded.
60+
// passing ctx prevents adding too many records to the result set.
61+
Find(ctx context.Context, query Query) ([]Document, error)
5962
// Reference uses the configured reference function to generate a reference of the function
6063
Reference(doc Document) Reference
6164
// Iterate over documents that match the given query
@@ -193,9 +196,14 @@ func (c *collection) add(tx *bbolt.Tx, jsonSet []Document) error {
193196
return nil
194197
}
195198

196-
func (c *collection) Find(query Query) ([]Document, error) {
199+
func (c *collection) Find(ctx context.Context, query Query) ([]Document, error) {
197200
docs := make([]Document, 0)
198201
walker := func(key Reference, value []byte) error {
202+
// stop iteration when needed
203+
if err := ctx.Err(); err != nil {
204+
return err
205+
}
206+
199207
docs = append(docs, DocumentFromBytes(value))
200208
return nil
201209
}

collection_test.go

Lines changed: 72 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,10 @@
2020
package leia
2121

2222
import (
23+
"context"
2324
"errors"
2425
"testing"
26+
"time"
2527

2628
"github.com/stretchr/testify/assert"
2729
"go.etcd.io/bbolt"
@@ -143,7 +145,6 @@ func TestCollection_Delete(t *testing.T) {
143145
}
144146

145147
assertIndexSize(t, db, i, 0)
146-
// the index sub-bucket counts as 1
147148
assertSize(t, db, documentCollection, 0)
148149
})
149150

@@ -170,7 +171,7 @@ func TestCollection_Find(t *testing.T) {
170171
c.Add([]Document{exampleDoc})
171172
q := New(Eq("key", "value"))
172173

173-
docs, err := c.Find(q)
174+
docs, err := c.Find(context.TODO(), q)
174175

175176
if !assert.NoError(t, err) {
176177
return
@@ -185,7 +186,7 @@ func TestCollection_Find(t *testing.T) {
185186
c.Add([]Document{exampleDoc})
186187
q := New(Eq("key", "value")).And(Eq("non_indexed", "value"))
187188

188-
docs, err := c.Find(q)
189+
docs, err := c.Find(context.TODO(), q)
189190

190191
if !assert.NoError(t, err) {
191192
return
@@ -200,7 +201,7 @@ func TestCollection_Find(t *testing.T) {
200201
c.Add([]Document{exampleDoc})
201202
q := New(Eq("non_indexed", "value"))
202203

203-
docs, err := c.Find(q)
204+
docs, err := c.Find(context.TODO(), q)
204205

205206
if !assert.NoError(t, err) {
206207
return
@@ -215,7 +216,7 @@ func TestCollection_Find(t *testing.T) {
215216
c.Add([]Document{exampleDoc})
216217
q := New(Eq("key", "value")).And(Range("non_indexed", "v", "value1"))
217218

218-
docs, err := c.Find(q)
219+
docs, err := c.Find(context.TODO(), q)
219220

220221
if !assert.NoError(t, err) {
221222
return
@@ -230,7 +231,7 @@ func TestCollection_Find(t *testing.T) {
230231
c.Add([]Document{exampleDoc})
231232
q := New(Eq("key", "value")).And(Range("non_indexed", "value1", "value2"))
232233

233-
docs, err := c.Find(q)
234+
docs, err := c.Find(context.TODO(), q)
234235

235236
if !assert.NoError(t, err) {
236237
return
@@ -245,7 +246,7 @@ func TestCollection_Find(t *testing.T) {
245246
c.AddIndex(i)
246247
q := New(Eq("key", "value"))
247248

248-
docs, err := c.Find(q)
249+
docs, err := c.Find(context.TODO(), q)
249250

250251
if !assert.NoError(t, err) {
251252
return
@@ -260,7 +261,7 @@ func TestCollection_Find(t *testing.T) {
260261
c.Add([]Document{exampleDoc})
261262
q := New(Eq("key", struct{}{}))
262263

263-
_, err := c.Find(q)
264+
_, err := c.Find(context.TODO(), q)
264265

265266
assert.Error(t, err)
266267
})
@@ -270,10 +271,43 @@ func TestCollection_Find(t *testing.T) {
270271
c.AddIndex(i)
271272
c.Add([]Document{exampleDoc})
272273

273-
_, err := c.Find(nil)
274+
_, err := c.Find(context.TODO(), nil)
274275

275276
assert.Error(t, err)
276277
})
278+
279+
t.Run("error - ctx cancelled", func(t *testing.T) {
280+
c := createCollection(db)
281+
c.AddIndex(i)
282+
c.Add([]Document{exampleDoc})
283+
q := New(Eq("key", "value"))
284+
ctx, cancelFn := context.WithCancel(context.Background())
285+
286+
cancelFn()
287+
_, err := c.Find(ctx, q)
288+
289+
if !assert.Error(t, err) {
290+
return
291+
}
292+
293+
assert.Equal(t, context.Canceled, err)
294+
})
295+
296+
t.Run("error - deadline exceeded", func(t *testing.T) {
297+
c := createCollection(db)
298+
c.AddIndex(i)
299+
c.Add([]Document{exampleDoc})
300+
q := New(Eq("key", "value"))
301+
ctx, _ := context.WithTimeout(context.Background(), time.Nanosecond)
302+
303+
_, err := c.Find(ctx, q)
304+
305+
if !assert.Error(t, err) {
306+
return
307+
}
308+
309+
assert.Equal(t, context.DeadlineExceeded, err)
310+
})
277311
}
278312

279313
func TestCollection_Iterate(t *testing.T) {
@@ -287,24 +321,42 @@ func TestCollection_Iterate(t *testing.T) {
287321
t.Run("ok - count fn", func(t *testing.T) {
288322
count := 0
289323

290-
err := db.View(func(tx *bbolt.Tx) error {
291-
b := testBucket(t, tx)
292-
return i.Iterate(b, q, func(key Reference, value []byte) error {
293-
count++
294-
return nil
295-
})
324+
err := c.Iterate(q, func(key Reference, value []byte) error {
325+
count++
326+
return nil
296327
})
297328

298329
assert.NoError(t, err)
299330
assert.Equal(t, 1, count)
300331
})
301332

333+
t.Run("ok - document indexed multiple times, query should un double", func(t *testing.T) {
334+
doc := DocumentFromString(jsonExample)
335+
doc2 := DocumentFromString(jsonExample2)
336+
db := testDB(t)
337+
count := 0
338+
339+
i := NewIndex(t.Name(),
340+
NewFieldIndexer("path.part", AliasOption("key")),
341+
NewFieldIndexer("path.more.#.parts", AliasOption("key3")),
342+
)
343+
344+
c := createCollection(db)
345+
c.AddIndex(i)
346+
c.Add([]Document{doc, doc2})
347+
348+
err := c.Iterate(q, func(key Reference, value []byte) error {
349+
count++
350+
return nil
351+
})
352+
353+
assert.NoError(t, err)
354+
assert.Equal(t, 2, count)
355+
})
356+
302357
t.Run("error", func(t *testing.T) {
303-
err := db.View(func(tx *bbolt.Tx) error {
304-
b := testBucket(t, tx)
305-
return i.Iterate(b, q, func(key Reference, value []byte) error {
306-
return errors.New("b00m!")
307-
})
358+
err := c.Iterate(q, func(key Reference, value []byte) error {
359+
return errors.New("b00m!")
308360
})
309361

310362
assert.Error(t, err)

entry.go

Lines changed: 0 additions & 125 deletions
This file was deleted.

0 commit comments

Comments
 (0)