-
Notifications
You must be signed in to change notification settings - Fork 27
/
delete.go
77 lines (64 loc) · 2.11 KB
/
delete.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
package nds
import (
"context"
"sync"
"cloud.google.com/go/datastore"
"go.opencensus.io/trace"
)
// deleteMultiLimit is the Google Cloud Datastore limit for the maximum number
// of entities that can be deleted by datastore.DeleteMulti at once.
// https://cloud.google.com/datastore/docs/concepts/limits
const deleteMultiLimit = 500
// DeleteMulti works just like datastore.DeleteMulti except it maintains
// cache consistency with other NDS methods. It also removes the API limit of
// 500 entities per request by calling the datastore as many times as required
// to put all the keys. It does this efficiently and concurrently.
func (c *Client) DeleteMulti(ctx context.Context, keys []*datastore.Key) error {
var span *trace.Span
ctx, span = trace.StartSpan(ctx, "github.com/qedus/nds.DeleteMulti")
defer span.End()
callCount := (len(keys)-1)/deleteMultiLimit + 1
errs := make([]error, callCount)
var wg sync.WaitGroup
wg.Add(callCount)
for i := 0; i < callCount; i++ {
lo := i * deleteMultiLimit
hi := (i + 1) * deleteMultiLimit
if hi > len(keys) {
hi = len(keys)
}
go func(i int, keys []*datastore.Key) {
errs[i] = c.deleteMulti(ctx, keys)
wg.Done()
}(i, keys[lo:hi])
}
wg.Wait()
if isErrorsNil(errs) {
return nil
}
return groupErrors(errs, len(keys), deleteMultiLimit)
}
// Delete deletes the entity for the given key.
func (c *Client) Delete(ctx context.Context, key *datastore.Key) error {
var span *trace.Span
ctx, span = trace.StartSpan(ctx, "github.com/qedus/nds.Delete")
defer span.End()
err := c.deleteMulti(ctx, []*datastore.Key{key})
if me, ok := err.(datastore.MultiError); ok {
return me[0]
}
return err
}
// deleteMulti will batch delete keys by first locking the corresponding items in the
// cache then deleting them from datastore.
func (c *Client) deleteMulti(ctx context.Context, keys []*datastore.Key) error {
if c.cacher != nil {
_, lockCacheItems := getCacheLocks(keys)
// Make sure we can lock the cache with no errors before deleting.
if err := c.cacher.SetMulti(ctx,
lockCacheItems); err != nil {
return err
}
}
return c.Client.DeleteMulti(ctx, keys)
}