From 054e02546a9b65c3a9bc0667ead5a36d1a520371 Mon Sep 17 00:00:00 2001 From: George MacRorie Date: Wed, 5 Aug 2020 11:23:23 +0100 Subject: [PATCH] feat(paging): add support for after id parameter in find options --- kv/bucket.go | 22 +++++++++++++++--- paging.go | 17 ++++++++++++++ tenant/storage_bucket.go | 12 +++++++++- testing/bucket_service.go | 48 +++++++++++++++++++++++++++++++++++++++ 4 files changed, 95 insertions(+), 4 deletions(-) diff --git a/kv/bucket.go b/kv/bucket.go index abacaad23a6..e652672bf1f 100644 --- a/kv/bucket.go +++ b/kv/bucket.go @@ -403,18 +403,34 @@ func (s *Service) findBuckets(ctx context.Context, tx Tx, filter influxdb.Bucket filter.OrganizationID = &o.ID } - var offset, limit, count int - var descending bool + var ( + offset, limit, count int + descending bool + ) + + after := func(*influxdb.Bucket) bool { + return true + } + if len(opts) > 0 { offset = opts[0].Offset limit = opts[0].Limit descending = opts[0].Descending + if opts[0].After != nil { + after = func(b *influxdb.Bucket) bool { + if descending { + return b.ID < *opts[0].After + } + + return b.ID > *opts[0].After + } + } } filterFn := filterBucketsFn(filter) err := s.forEachBucket(ctx, tx, descending, func(b *influxdb.Bucket) bool { if filterFn(b) { - if count >= offset { + if count >= offset && after(b) { bs = append(bs, b) } count++ diff --git a/paging.go b/paging.go index 87075311e30..71667132918 100644 --- a/paging.go +++ b/paging.go @@ -29,6 +29,7 @@ type PagingLinks struct { type FindOptions struct { Limit int Offset int + After *ID SortBy string Descending bool } @@ -50,6 +51,18 @@ func DecodeFindOptions(r *http.Request) (*FindOptions, error) { opts.Offset = o } + if after := qp.Get("after"); after != "" { + id, err := IDFromString(after) + if err != nil { + return nil, &Error{ + Code: EInvalid, + Err: fmt.Errorf("decoding after: %w", err), + } + } + + opts.After = id + } + if limit := qp.Get("limit"); limit != "" { l, err := strconv.Atoi(limit) if err != nil { @@ -109,6 +122,10 @@ func (f FindOptions) QueryParams() map[string][]string { "offset": {strconv.Itoa(f.Offset)}, } + if f.After != nil { + qp["after"] = []string{f.After.String()} + } + if f.Limit > 0 { qp["limit"] = []string{strconv.Itoa(f.Limit)} } diff --git a/tenant/storage_bucket.go b/tenant/storage_bucket.go index bae48d012fa..7bd9d3dacd4 100644 --- a/tenant/storage_bucket.go +++ b/tenant/storage_bucket.go @@ -190,7 +190,17 @@ func (s *Store) ListBuckets(ctx context.Context, tx kv.Tx, filter BucketFilter, if o.Descending { opts = append(opts, kv.WithCursorDirection(kv.CursorDescending)) } - cursor, err := b.ForwardCursor(nil, opts...) + + var seek []byte + if o.After != nil { + after := (*o.After) + 1 + seek, err = after.Encode() + if err != nil { + return nil, err + } + } + + cursor, err := b.ForwardCursor(seek, opts...) if err != nil { return nil, err } diff --git a/testing/bucket_service.go b/testing/bucket_service.go index 46c6e843550..da49f082582 100644 --- a/testing/bucket_service.go +++ b/testing/bucket_service.go @@ -617,6 +617,54 @@ func FindBuckets( }, }, }, + { + name: "find all buckets by after and limit", + fields: BucketFields{ + BucketIDs: mock.NewIncrementingIDGenerator(idOne), + Organizations: []*influxdb.Organization{ + { + Name: "theorg", + }, + }, + Buckets: []*influxdb.Bucket{ + { + // ID(1) + OrgID: idOne, + Name: "abc", + }, + { + // ID(2) + OrgID: idOne, + Name: "def", + }, + { + // ID(3) + OrgID: idOne, + Name: "xyz", + }, + }, + }, + args: args{ + findOptions: influxdb.FindOptions{ + After: idPtr(idOne), + Limit: 2, + }, + }, + wants: wants{ + buckets: []*influxdb.Bucket{ + { + ID: idTwo, + OrgID: idOne, + Name: "def", + }, + { + ID: idThree, + OrgID: idOne, + Name: "xyz", + }, + }, + }, + }, { name: "find all buckets by descending", fields: BucketFields{