-
Notifications
You must be signed in to change notification settings - Fork 3.6k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #2366 from influxdata/er-bucket-delete
Wire up Storage Engine to API-layer BucketService
- Loading branch information
Showing
8 changed files
with
257 additions
and
18 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,90 @@ | ||
package storage | ||
|
||
import ( | ||
"context" | ||
"errors" | ||
|
||
"github.com/influxdata/platform" | ||
) | ||
|
||
// BucketDeleter defines the behaviour of deleting a bucket. | ||
type BucketDeleter interface { | ||
DeleteBucket(platform.ID, platform.ID) error | ||
} | ||
|
||
// BucketService wraps an existing platform.BucketService implementation. | ||
// | ||
// BucketService ensures that when a bucket is deleted, all stored data | ||
// associated with the bucket is either removed, or marked to be removed via a | ||
// future compaction. | ||
type BucketService struct { | ||
inner platform.BucketService | ||
engine BucketDeleter | ||
} | ||
|
||
// NewBucketService returns a new BucketService for the provided BucketDeleter, | ||
// which typically will be an Engine. | ||
func NewBucketService(s platform.BucketService, engine BucketDeleter) *BucketService { | ||
return &BucketService{ | ||
inner: s, | ||
engine: engine, | ||
} | ||
} | ||
|
||
// FindBucketByID returns a single bucket by ID. | ||
func (s *BucketService) FindBucketByID(ctx context.Context, id platform.ID) (*platform.Bucket, error) { | ||
if s.inner == nil || s.engine == nil { | ||
return nil, errors.New("nil inner BucketService or Engine") | ||
} | ||
return s.inner.FindBucketByID(ctx, id) | ||
} | ||
|
||
// FindBucket returns the first bucket that matches filter. | ||
func (s *BucketService) FindBucket(ctx context.Context, filter platform.BucketFilter) (*platform.Bucket, error) { | ||
if s.inner == nil || s.engine == nil { | ||
return nil, errors.New("nil inner BucketService or Engine") | ||
} | ||
return s.inner.FindBucket(ctx, filter) | ||
} | ||
|
||
// FindBuckets returns a list of buckets that match filter and the total count of matching buckets. | ||
// Additional options provide pagination & sorting. | ||
func (s *BucketService) FindBuckets(ctx context.Context, filter platform.BucketFilter, opt ...platform.FindOptions) ([]*platform.Bucket, int, error) { | ||
if s.inner == nil || s.engine == nil { | ||
return nil, 0, errors.New("nil inner BucketService or Engine") | ||
} | ||
return s.inner.FindBuckets(ctx, filter, opt...) | ||
} | ||
|
||
// CreateBucket creates a new bucket and sets b.ID with the new identifier. | ||
func (s *BucketService) CreateBucket(ctx context.Context, b *platform.Bucket) error { | ||
if s.inner == nil || s.engine == nil { | ||
return errors.New("nil inner BucketService or Engine") | ||
} | ||
return s.inner.CreateBucket(ctx, b) | ||
} | ||
|
||
// UpdateBucket updates a single bucket with changeset. | ||
// Returns the new bucket state after update. | ||
func (s *BucketService) UpdateBucket(ctx context.Context, id platform.ID, upd platform.BucketUpdate) (*platform.Bucket, error) { | ||
if s.inner == nil || s.engine == nil { | ||
return nil, errors.New("nil inner BucketService or Engine") | ||
} | ||
return s.inner.UpdateBucket(ctx, id, upd) | ||
} | ||
|
||
// DeleteBucket removes a bucket by ID. | ||
func (s *BucketService) DeleteBucket(ctx context.Context, bucketID platform.ID) error { | ||
bucket, err := s.FindBucketByID(ctx, bucketID) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
// The data is dropped first from the storage engine. If this fails for any | ||
// reason, then the bucket will still be available in the future to retrieve | ||
// the orgID, which is needed for the engine. | ||
if err := s.engine.DeleteBucket(bucket.OrganizationID, bucketID); err != nil { | ||
return err | ||
} | ||
return s.inner.DeleteBucket(ctx, bucketID) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,63 @@ | ||
package storage_test | ||
|
||
import ( | ||
"context" | ||
"testing" | ||
|
||
"github.com/influxdata/platform" | ||
"github.com/influxdata/platform/inmem" | ||
"github.com/influxdata/platform/storage" | ||
) | ||
|
||
func TestBucketService(t *testing.T) { | ||
service := storage.NewBucketService(nil, nil) | ||
|
||
i, err := platform.IDFromString("2222222222222222") | ||
if err != nil { | ||
panic(err) | ||
} | ||
|
||
if err := service.DeleteBucket(context.TODO(), *i); err == nil { | ||
t.Fatal("expected error, got nil") | ||
} | ||
|
||
inmemService := inmem.NewService() | ||
service = storage.NewBucketService(inmemService, nil) | ||
|
||
if err := service.DeleteBucket(context.TODO(), *i); err == nil { | ||
t.Fatal("expected error, got nil") | ||
} | ||
|
||
org := &platform.Organization{} | ||
if err := inmemService.CreateOrganization(context.TODO(), org); err != nil { | ||
panic(err) | ||
} | ||
|
||
bucket := &platform.Bucket{OrganizationID: org.ID} | ||
if err := inmemService.CreateBucket(context.TODO(), bucket); err != nil { | ||
panic(err) | ||
} | ||
|
||
// Test deleting a bucket calls into the deleter. | ||
deleter := &MockDeleter{} | ||
service = storage.NewBucketService(inmemService, deleter) | ||
|
||
if err := service.DeleteBucket(context.TODO(), bucket.ID); err != nil { | ||
t.Fatal(err) | ||
} | ||
|
||
if deleter.orgID != org.ID { | ||
t.Errorf("got org ID: %s, expected %s", deleter.orgID, org.ID) | ||
} else if deleter.bucketID != bucket.ID { | ||
t.Errorf("got bucket ID: %s, expected %s", deleter.bucketID, bucket.ID) | ||
} | ||
} | ||
|
||
type MockDeleter struct { | ||
orgID, bucketID platform.ID | ||
} | ||
|
||
func (m *MockDeleter) DeleteBucket(orgID, bucketID platform.ID) error { | ||
m.orgID, m.bucketID = orgID, bucketID | ||
return nil | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters