feat(storage): rpc based implementation
All checks were successful
arcad/edge/pipeline/pr-master This commit looks good
All checks were successful
arcad/edge/pipeline/pr-master This commit looks good
This commit is contained in:
31
pkg/storage/driver/rpc/server/blob/close_bucket.go
Normal file
31
pkg/storage/driver/rpc/server/blob/close_bucket.go
Normal file
@ -0,0 +1,31 @@
|
||||
package blob
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
type CloseBucketArgs struct {
|
||||
BucketID BucketID
|
||||
}
|
||||
|
||||
type CloseBucketReply struct {
|
||||
}
|
||||
|
||||
func (s *Service) CloseBucket(ctx context.Context, args *CloseBucketArgs, reply *CloseBucketReply) error {
|
||||
bucket, err := s.getOpenedBucket(args.BucketID)
|
||||
if err != nil {
|
||||
return errors.WithStack(err)
|
||||
}
|
||||
|
||||
if err := bucket.Close(); err != nil {
|
||||
return errors.WithStack(err)
|
||||
}
|
||||
|
||||
s.buckets.Delete(args.BucketID)
|
||||
|
||||
*reply = CloseBucketReply{}
|
||||
|
||||
return nil
|
||||
}
|
31
pkg/storage/driver/rpc/server/blob/close_reader.go
Normal file
31
pkg/storage/driver/rpc/server/blob/close_reader.go
Normal file
@ -0,0 +1,31 @@
|
||||
package blob
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
type CloseReaderArgs struct {
|
||||
ReaderID ReaderID
|
||||
}
|
||||
|
||||
type CloseReaderReply struct {
|
||||
}
|
||||
|
||||
func (s *Service) CloseReader(ctx context.Context, args *CloseReaderArgs, reply *CloseReaderReply) error {
|
||||
reader, err := s.getOpenedReader(args.ReaderID)
|
||||
if err != nil {
|
||||
return errors.WithStack(err)
|
||||
}
|
||||
|
||||
if err := reader.Close(); err != nil {
|
||||
return errors.WithStack(err)
|
||||
}
|
||||
|
||||
s.readers.Delete(args.ReaderID)
|
||||
|
||||
*reply = CloseReaderReply{}
|
||||
|
||||
return nil
|
||||
}
|
31
pkg/storage/driver/rpc/server/blob/close_writer.go
Normal file
31
pkg/storage/driver/rpc/server/blob/close_writer.go
Normal file
@ -0,0 +1,31 @@
|
||||
package blob
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
type CloseWriterArgs struct {
|
||||
WriterID WriterID
|
||||
}
|
||||
|
||||
type CloseWriterReply struct {
|
||||
}
|
||||
|
||||
func (s *Service) CloseWriter(ctx context.Context, args *CloseWriterArgs, reply *CloseWriterReply) error {
|
||||
writer, err := s.getOpenedWriter(args.WriterID)
|
||||
if err != nil {
|
||||
return errors.WithStack(err)
|
||||
}
|
||||
|
||||
if err := writer.Close(); err != nil {
|
||||
return errors.WithStack(err)
|
||||
}
|
||||
|
||||
s.writers.Delete(args.WriterID)
|
||||
|
||||
*reply = CloseWriterReply{}
|
||||
|
||||
return nil
|
||||
}
|
22
pkg/storage/driver/rpc/server/blob/delete_bucket.go
Normal file
22
pkg/storage/driver/rpc/server/blob/delete_bucket.go
Normal file
@ -0,0 +1,22 @@
|
||||
package blob
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
type DeleteBucketArgs struct {
|
||||
BucketName string
|
||||
}
|
||||
|
||||
type DeleteBucketReply struct {
|
||||
}
|
||||
|
||||
func (s *Service) DeleteBucket(ctx context.Context, args *DeleteBucketArgs, reply *DeleteBucketReply) error {
|
||||
if err := s.store.DeleteBucket(ctx, args.BucketName); err != nil {
|
||||
return errors.WithStack(err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
42
pkg/storage/driver/rpc/server/blob/get_blob_info.go
Normal file
42
pkg/storage/driver/rpc/server/blob/get_blob_info.go
Normal file
@ -0,0 +1,42 @@
|
||||
package blob
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"forge.cadoles.com/arcad/edge/pkg/storage"
|
||||
"forge.cadoles.com/arcad/edge/pkg/storage/driver/rpc/gob"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
type GetBlobInfoArgs struct {
|
||||
BlobID storage.BlobID
|
||||
BucketID BucketID
|
||||
}
|
||||
|
||||
type GetBlobInfoReply struct {
|
||||
BlobInfo storage.BlobInfo
|
||||
}
|
||||
|
||||
func (s *Service) GetBlobInfo(ctx context.Context, args *GetBlobInfoArgs, reply *GetBlobInfoReply) error {
|
||||
bucket, err := s.getOpenedBucket(args.BucketID)
|
||||
if err != nil {
|
||||
return errors.WithStack(err)
|
||||
}
|
||||
|
||||
blobInfo, err := bucket.Get(ctx, args.BlobID)
|
||||
if err != nil {
|
||||
return errors.WithStack(err)
|
||||
}
|
||||
|
||||
*reply = GetBlobInfoReply{
|
||||
BlobInfo: &gob.BlobInfo{
|
||||
Bucket_: blobInfo.Bucket(),
|
||||
ContentType_: blobInfo.ContentType(),
|
||||
BlobID_: blobInfo.ID(),
|
||||
ModTime_: blobInfo.ModTime(),
|
||||
Size_: blobInfo.Size(),
|
||||
},
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
33
pkg/storage/driver/rpc/server/blob/get_bucket_size.go
Normal file
33
pkg/storage/driver/rpc/server/blob/get_bucket_size.go
Normal file
@ -0,0 +1,33 @@
|
||||
package blob
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
type GetBucketSizeArgs struct {
|
||||
BucketID BucketID
|
||||
}
|
||||
|
||||
type GetBucketSizeReply struct {
|
||||
Size int64
|
||||
}
|
||||
|
||||
func (s *Service) GetBucketSize(ctx context.Context, args *GetBucketSizeArgs, reply *GetBucketSizeReply) error {
|
||||
bucket, err := s.getOpenedBucket(args.BucketID)
|
||||
if err != nil {
|
||||
return errors.WithStack(err)
|
||||
}
|
||||
|
||||
size, err := bucket.Size(ctx)
|
||||
if err != nil {
|
||||
return errors.WithStack(err)
|
||||
}
|
||||
|
||||
*reply = GetBucketSizeReply{
|
||||
Size: size,
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
34
pkg/storage/driver/rpc/server/blob/list_blob_info.go
Normal file
34
pkg/storage/driver/rpc/server/blob/list_blob_info.go
Normal file
@ -0,0 +1,34 @@
|
||||
package blob
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"forge.cadoles.com/arcad/edge/pkg/storage"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
type ListBlobInfoArgs struct {
|
||||
BucketID BucketID
|
||||
}
|
||||
|
||||
type ListBlobInfoReply struct {
|
||||
BlobInfos []storage.BlobInfo
|
||||
}
|
||||
|
||||
func (s *Service) ListBlobInfo(ctx context.Context, args *ListBlobInfoArgs, reply *ListBlobInfoReply) error {
|
||||
bucket, err := s.getOpenedBucket(args.BucketID)
|
||||
if err != nil {
|
||||
return errors.WithStack(err)
|
||||
}
|
||||
|
||||
blobInfos, err := bucket.List(ctx)
|
||||
if err != nil {
|
||||
return errors.WithStack(err)
|
||||
}
|
||||
|
||||
*reply = ListBlobInfoReply{
|
||||
BlobInfos: blobInfos,
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
27
pkg/storage/driver/rpc/server/blob/list_buckets.go
Normal file
27
pkg/storage/driver/rpc/server/blob/list_buckets.go
Normal file
@ -0,0 +1,27 @@
|
||||
package blob
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
type ListBucketsArgs struct {
|
||||
}
|
||||
|
||||
type ListBucketsReply struct {
|
||||
Buckets []string
|
||||
}
|
||||
|
||||
func (s *Service) ListBuckets(ctx context.Context, args *ListBucketsArgs, reply *ListBucketsReply) error {
|
||||
buckets, err := s.store.ListBuckets(ctx)
|
||||
if err != nil {
|
||||
return errors.WithStack(err)
|
||||
}
|
||||
|
||||
*reply = ListBucketsReply{
|
||||
Buckets: buckets,
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
57
pkg/storage/driver/rpc/server/blob/new_blob_reader.go
Normal file
57
pkg/storage/driver/rpc/server/blob/new_blob_reader.go
Normal file
@ -0,0 +1,57 @@
|
||||
package blob
|
||||
|
||||
import (
|
||||
"context"
|
||||
"io"
|
||||
|
||||
"forge.cadoles.com/arcad/edge/pkg/storage"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
type NewBlobReaderArgs struct {
|
||||
BlobID storage.BlobID
|
||||
BucketID BucketID
|
||||
}
|
||||
|
||||
type NewBlobReaderReply struct {
|
||||
ReaderID ReaderID
|
||||
}
|
||||
|
||||
func (s *Service) NewBlobReader(ctx context.Context, args *NewBlobReaderArgs, reply *NewBlobReaderReply) error {
|
||||
bucket, err := s.getOpenedBucket(args.BucketID)
|
||||
if err != nil {
|
||||
return errors.WithStack(err)
|
||||
}
|
||||
|
||||
readerID, err := NewReaderID()
|
||||
if err != nil {
|
||||
return errors.WithStack(err)
|
||||
}
|
||||
|
||||
reader, err := bucket.NewReader(ctx, args.BlobID)
|
||||
if err != nil {
|
||||
return errors.WithStack(err)
|
||||
}
|
||||
|
||||
s.readers.Store(readerID, reader)
|
||||
|
||||
*reply = NewBlobReaderReply{
|
||||
ReaderID: readerID,
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *Service) getOpenedReader(id ReaderID) (io.ReadSeekCloser, error) {
|
||||
raw, exists := s.readers.Load(id)
|
||||
if !exists {
|
||||
return nil, errors.Errorf("could not find writer '%s'", id)
|
||||
}
|
||||
|
||||
reader, ok := raw.(io.ReadSeekCloser)
|
||||
if !ok {
|
||||
return nil, errors.Errorf("unexpected type '%T' for writer", raw)
|
||||
}
|
||||
|
||||
return reader, nil
|
||||
}
|
57
pkg/storage/driver/rpc/server/blob/new_blob_writer.go
Normal file
57
pkg/storage/driver/rpc/server/blob/new_blob_writer.go
Normal file
@ -0,0 +1,57 @@
|
||||
package blob
|
||||
|
||||
import (
|
||||
"context"
|
||||
"io"
|
||||
|
||||
"forge.cadoles.com/arcad/edge/pkg/storage"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
type NewBlobWriterArgs struct {
|
||||
BlobID storage.BlobID
|
||||
BucketID BucketID
|
||||
}
|
||||
|
||||
type NewBlobWriterReply struct {
|
||||
WriterID WriterID
|
||||
}
|
||||
|
||||
func (s *Service) NewBlobWriter(ctx context.Context, args *NewBlobWriterArgs, reply *NewBlobWriterReply) error {
|
||||
bucket, err := s.getOpenedBucket(args.BucketID)
|
||||
if err != nil {
|
||||
return errors.WithStack(err)
|
||||
}
|
||||
|
||||
writerID, err := NewWriterID()
|
||||
if err != nil {
|
||||
return errors.WithStack(err)
|
||||
}
|
||||
|
||||
writer, err := bucket.NewWriter(ctx, args.BlobID)
|
||||
if err != nil {
|
||||
return errors.WithStack(err)
|
||||
}
|
||||
|
||||
s.writers.Store(writerID, writer)
|
||||
|
||||
*reply = NewBlobWriterReply{
|
||||
WriterID: writerID,
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *Service) getOpenedWriter(id WriterID) (io.WriteCloser, error) {
|
||||
raw, exists := s.writers.Load(id)
|
||||
if !exists {
|
||||
return nil, errors.Errorf("could not find writer '%s'", id)
|
||||
}
|
||||
|
||||
writer, ok := raw.(io.WriteCloser)
|
||||
if !ok {
|
||||
return nil, errors.Errorf("unexpected type '%T' for writer", raw)
|
||||
}
|
||||
|
||||
return writer, nil
|
||||
}
|
50
pkg/storage/driver/rpc/server/blob/open_bucket.go
Normal file
50
pkg/storage/driver/rpc/server/blob/open_bucket.go
Normal file
@ -0,0 +1,50 @@
|
||||
package blob
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"forge.cadoles.com/arcad/edge/pkg/storage"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
type OpenBucketArgs struct {
|
||||
BucketName string
|
||||
}
|
||||
|
||||
type OpenBucketReply struct {
|
||||
BucketID BucketID
|
||||
}
|
||||
|
||||
func (s *Service) OpenBucket(ctx context.Context, args *OpenBucketArgs, reply *OpenBucketReply) error {
|
||||
bucket, err := s.store.OpenBucket(ctx, args.BucketName)
|
||||
if err != nil {
|
||||
return errors.WithStack(err)
|
||||
}
|
||||
|
||||
bucketID, err := NewBucketID()
|
||||
if err != nil {
|
||||
return errors.WithStack(err)
|
||||
}
|
||||
|
||||
s.buckets.Store(bucketID, bucket)
|
||||
|
||||
*reply = OpenBucketReply{
|
||||
BucketID: bucketID,
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *Service) getOpenedBucket(id BucketID) (storage.BlobBucket, error) {
|
||||
raw, exists := s.buckets.Load(id)
|
||||
if !exists {
|
||||
return nil, errors.WithStack(storage.ErrBucketClosed)
|
||||
}
|
||||
|
||||
bucket, ok := raw.(storage.BlobBucket)
|
||||
if !ok {
|
||||
return nil, errors.Errorf("unexpected type '%T' for blob bucket", raw)
|
||||
}
|
||||
|
||||
return bucket, nil
|
||||
}
|
41
pkg/storage/driver/rpc/server/blob/read_blob.go
Normal file
41
pkg/storage/driver/rpc/server/blob/read_blob.go
Normal file
@ -0,0 +1,41 @@
|
||||
package blob
|
||||
|
||||
import (
|
||||
"context"
|
||||
"io"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
type ReadBlobArgs struct {
|
||||
ReaderID ReaderID
|
||||
Length int
|
||||
}
|
||||
|
||||
type ReadBlobReply struct {
|
||||
Data []byte
|
||||
Read int
|
||||
EOF bool
|
||||
}
|
||||
|
||||
func (s *Service) ReadBlob(ctx context.Context, args *ReadBlobArgs, reply *ReadBlobReply) error {
|
||||
reader, err := s.getOpenedReader(args.ReaderID)
|
||||
if err != nil {
|
||||
return errors.WithStack(err)
|
||||
}
|
||||
|
||||
buff := make([]byte, args.Length)
|
||||
|
||||
read, err := reader.Read(buff)
|
||||
if err != nil && !errors.Is(err, io.EOF) {
|
||||
return errors.WithStack(err)
|
||||
}
|
||||
|
||||
*reply = ReadBlobReply{
|
||||
Read: read,
|
||||
Data: buff,
|
||||
EOF: errors.Is(err, io.EOF),
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
38
pkg/storage/driver/rpc/server/blob/seek_blob.go
Normal file
38
pkg/storage/driver/rpc/server/blob/seek_blob.go
Normal file
@ -0,0 +1,38 @@
|
||||
package blob
|
||||
|
||||
import (
|
||||
"context"
|
||||
"io"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
type SeekBlobArgs struct {
|
||||
ReaderID ReaderID
|
||||
Offset int64
|
||||
Whence int
|
||||
}
|
||||
|
||||
type SeekBlobReply struct {
|
||||
Read int64
|
||||
EOF bool
|
||||
}
|
||||
|
||||
func (s *Service) SeekBlob(ctx context.Context, args *SeekBlobArgs, reply *SeekBlobReply) error {
|
||||
reader, err := s.getOpenedReader(args.ReaderID)
|
||||
if err != nil {
|
||||
return errors.WithStack(err)
|
||||
}
|
||||
|
||||
read, err := reader.Seek(args.Offset, args.Whence)
|
||||
if err != nil && !errors.Is(err, io.EOF) {
|
||||
return errors.WithStack(err)
|
||||
}
|
||||
|
||||
*reply = SeekBlobReply{
|
||||
Read: read,
|
||||
EOF: errors.Is(err, io.EOF),
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
60
pkg/storage/driver/rpc/server/blob/service.go
Normal file
60
pkg/storage/driver/rpc/server/blob/service.go
Normal file
@ -0,0 +1,60 @@
|
||||
package blob
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"sync"
|
||||
|
||||
"forge.cadoles.com/arcad/edge/pkg/storage"
|
||||
"github.com/google/uuid"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
type BucketID string
|
||||
type WriterID string
|
||||
type ReaderID string
|
||||
|
||||
type Service struct {
|
||||
store storage.BlobStore
|
||||
buckets sync.Map
|
||||
writers sync.Map
|
||||
readers sync.Map
|
||||
}
|
||||
|
||||
func NewService(store storage.BlobStore) *Service {
|
||||
return &Service{
|
||||
store: store,
|
||||
}
|
||||
}
|
||||
|
||||
func NewBucketID() (BucketID, error) {
|
||||
uuid, err := uuid.NewUUID()
|
||||
if err != nil {
|
||||
return "", errors.WithStack(err)
|
||||
}
|
||||
|
||||
id := BucketID(fmt.Sprintf("bucket-%s", uuid.String()))
|
||||
|
||||
return id, nil
|
||||
}
|
||||
|
||||
func NewWriterID() (WriterID, error) {
|
||||
uuid, err := uuid.NewUUID()
|
||||
if err != nil {
|
||||
return "", errors.WithStack(err)
|
||||
}
|
||||
|
||||
id := WriterID(fmt.Sprintf("writer-%s", uuid.String()))
|
||||
|
||||
return id, nil
|
||||
}
|
||||
|
||||
func NewReaderID() (ReaderID, error) {
|
||||
uuid, err := uuid.NewUUID()
|
||||
if err != nil {
|
||||
return "", errors.WithStack(err)
|
||||
}
|
||||
|
||||
id := ReaderID(fmt.Sprintf("reader-%s", uuid.String()))
|
||||
|
||||
return id, nil
|
||||
}
|
34
pkg/storage/driver/rpc/server/blob/write_blob.go
Normal file
34
pkg/storage/driver/rpc/server/blob/write_blob.go
Normal file
@ -0,0 +1,34 @@
|
||||
package blob
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
type WriteBlobArgs struct {
|
||||
WriterID WriterID
|
||||
Data []byte
|
||||
}
|
||||
|
||||
type WriteBlobReply struct {
|
||||
Written int
|
||||
}
|
||||
|
||||
func (s *Service) WriteBlob(ctx context.Context, args *WriteBlobArgs, reply *WriteBlobReply) error {
|
||||
writer, err := s.getOpenedWriter(args.WriterID)
|
||||
if err != nil {
|
||||
return errors.WithStack(err)
|
||||
}
|
||||
|
||||
written, err := writer.Write(args.Data)
|
||||
if err != nil {
|
||||
return errors.WithStack(err)
|
||||
}
|
||||
|
||||
*reply = WriteBlobReply{
|
||||
Written: written,
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
26
pkg/storage/driver/rpc/server/document/delete_document.go
Normal file
26
pkg/storage/driver/rpc/server/document/delete_document.go
Normal file
@ -0,0 +1,26 @@
|
||||
package document
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"forge.cadoles.com/arcad/edge/pkg/storage"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
type DeleteDocumentArgs struct {
|
||||
Collection string
|
||||
DocumentID storage.DocumentID
|
||||
}
|
||||
|
||||
type DeleteDocumentReply struct {
|
||||
}
|
||||
|
||||
func (s *Service) DeleteDocument(ctx context.Context, args DeleteDocumentArgs, reply *DeleteDocumentReply) error {
|
||||
if err := s.store.Delete(ctx, args.Collection, args.DocumentID); err != nil {
|
||||
return errors.WithStack(err)
|
||||
}
|
||||
|
||||
*reply = DeleteDocumentReply{}
|
||||
|
||||
return nil
|
||||
}
|
30
pkg/storage/driver/rpc/server/document/get_document.go
Normal file
30
pkg/storage/driver/rpc/server/document/get_document.go
Normal file
@ -0,0 +1,30 @@
|
||||
package document
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"forge.cadoles.com/arcad/edge/pkg/storage"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
type GetDocumentArgs struct {
|
||||
Collection string
|
||||
DocumentID storage.DocumentID
|
||||
}
|
||||
|
||||
type GetDocumentReply struct {
|
||||
Document storage.Document
|
||||
}
|
||||
|
||||
func (s *Service) GetDocument(ctx context.Context, args GetDocumentArgs, reply *GetDocumentReply) error {
|
||||
document, err := s.store.Get(ctx, args.Collection, args.DocumentID)
|
||||
if err != nil {
|
||||
return errors.WithStack(err)
|
||||
}
|
||||
|
||||
*reply = GetDocumentReply{
|
||||
Document: document,
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
53
pkg/storage/driver/rpc/server/document/query_documents.go
Normal file
53
pkg/storage/driver/rpc/server/document/query_documents.go
Normal file
@ -0,0 +1,53 @@
|
||||
package document
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"forge.cadoles.com/arcad/edge/pkg/storage"
|
||||
"forge.cadoles.com/arcad/edge/pkg/storage/filter"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
type QueryDocumentsArgs struct {
|
||||
Collection string
|
||||
Filter map[string]any
|
||||
Options *storage.QueryOptions
|
||||
}
|
||||
|
||||
type QueryDocumentsReply struct {
|
||||
Documents []storage.Document
|
||||
}
|
||||
|
||||
func (s *Service) QueryDocuments(ctx context.Context, args QueryDocumentsArgs, reply *QueryDocumentsReply) error {
|
||||
var (
|
||||
argsFilter *filter.Filter
|
||||
err error
|
||||
)
|
||||
|
||||
if args.Filter != nil {
|
||||
argsFilter, err = filter.NewFrom(args.Filter)
|
||||
if err != nil {
|
||||
return errors.WithStack(err)
|
||||
}
|
||||
}
|
||||
|
||||
documents, err := s.store.Query(ctx, args.Collection, argsFilter, withQueryOptions(args.Options))
|
||||
if err != nil {
|
||||
return errors.WithStack(err)
|
||||
}
|
||||
|
||||
*reply = QueryDocumentsReply{
|
||||
Documents: documents,
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func withQueryOptions(opts *storage.QueryOptions) storage.QueryOptionFunc {
|
||||
return func(o *storage.QueryOptions) {
|
||||
o.Limit = opts.Limit
|
||||
o.Offset = opts.Offset
|
||||
o.OrderBy = opts.OrderBy
|
||||
o.OrderDirection = opts.OrderDirection
|
||||
}
|
||||
}
|
11
pkg/storage/driver/rpc/server/document/service.go
Normal file
11
pkg/storage/driver/rpc/server/document/service.go
Normal file
@ -0,0 +1,11 @@
|
||||
package document
|
||||
|
||||
import "forge.cadoles.com/arcad/edge/pkg/storage"
|
||||
|
||||
type Service struct {
|
||||
store storage.DocumentStore
|
||||
}
|
||||
|
||||
func NewService(store storage.DocumentStore) *Service {
|
||||
return &Service{store}
|
||||
}
|
30
pkg/storage/driver/rpc/server/document/upsert_document.go
Normal file
30
pkg/storage/driver/rpc/server/document/upsert_document.go
Normal file
@ -0,0 +1,30 @@
|
||||
package document
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"forge.cadoles.com/arcad/edge/pkg/storage"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
type UpsertDocumentArgs struct {
|
||||
Collection string
|
||||
Document storage.Document
|
||||
}
|
||||
|
||||
type UpsertDocumentReply struct {
|
||||
Document storage.Document
|
||||
}
|
||||
|
||||
func (s *Service) UpsertDocument(ctx context.Context, args UpsertDocumentArgs, reply *UpsertDocumentReply) error {
|
||||
document, err := s.store.Upsert(ctx, args.Collection, args.Document)
|
||||
if err != nil {
|
||||
return errors.WithStack(err)
|
||||
}
|
||||
|
||||
*reply = UpsertDocumentReply{
|
||||
Document: document,
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
5
pkg/storage/driver/rpc/server/init.go
Normal file
5
pkg/storage/driver/rpc/server/init.go
Normal file
@ -0,0 +1,5 @@
|
||||
package server
|
||||
|
||||
import (
|
||||
_ "forge.cadoles.com/arcad/edge/pkg/storage/driver/rpc/gob"
|
||||
)
|
29
pkg/storage/driver/rpc/server/server.go
Normal file
29
pkg/storage/driver/rpc/server/server.go
Normal file
@ -0,0 +1,29 @@
|
||||
package server
|
||||
|
||||
import (
|
||||
"github.com/keegancsmith/rpc"
|
||||
|
||||
"forge.cadoles.com/arcad/edge/pkg/storage"
|
||||
"forge.cadoles.com/arcad/edge/pkg/storage/driver/rpc/server/blob"
|
||||
"forge.cadoles.com/arcad/edge/pkg/storage/driver/rpc/server/document"
|
||||
shareService "forge.cadoles.com/arcad/edge/pkg/storage/driver/rpc/server/share"
|
||||
"forge.cadoles.com/arcad/edge/pkg/storage/share"
|
||||
)
|
||||
|
||||
func NewBlobStoreServer(store storage.BlobStore) *rpc.Server {
|
||||
server := rpc.NewServer()
|
||||
server.Register(blob.NewService(store))
|
||||
return server
|
||||
}
|
||||
|
||||
func NewDocumentStoreServer(store storage.DocumentStore) *rpc.Server {
|
||||
server := rpc.NewServer()
|
||||
server.Register(document.NewService(store))
|
||||
return server
|
||||
}
|
||||
|
||||
func NewShareStoreServer(store share.Store) *rpc.Server {
|
||||
server := rpc.NewServer()
|
||||
server.Register(shareService.NewService(store))
|
||||
return server
|
||||
}
|
28
pkg/storage/driver/rpc/server/share/delete_attributes.go
Normal file
28
pkg/storage/driver/rpc/server/share/delete_attributes.go
Normal file
@ -0,0 +1,28 @@
|
||||
package share
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"forge.cadoles.com/arcad/edge/pkg/app"
|
||||
"forge.cadoles.com/arcad/edge/pkg/storage/share"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
type DeleteAttributesArgs struct {
|
||||
Origin app.ID
|
||||
ResourceID share.ResourceID
|
||||
Names []string
|
||||
}
|
||||
|
||||
type DeleteAttributesReply struct {
|
||||
}
|
||||
|
||||
func (s *Service) DeleteAttributes(ctx context.Context, args DeleteAttributesArgs, reply *DeleteAttributesReply) error {
|
||||
if err := s.store.DeleteAttributes(ctx, args.Origin, args.ResourceID, args.Names...); err != nil {
|
||||
return errors.WithStack(err)
|
||||
}
|
||||
|
||||
*reply = DeleteAttributesReply{}
|
||||
|
||||
return nil
|
||||
}
|
27
pkg/storage/driver/rpc/server/share/delete_resource.go
Normal file
27
pkg/storage/driver/rpc/server/share/delete_resource.go
Normal file
@ -0,0 +1,27 @@
|
||||
package share
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"forge.cadoles.com/arcad/edge/pkg/app"
|
||||
"forge.cadoles.com/arcad/edge/pkg/storage/share"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
type DeleteResourceArgs struct {
|
||||
Origin app.ID
|
||||
ResourceID share.ResourceID
|
||||
}
|
||||
|
||||
type DeleteResourceReply struct {
|
||||
}
|
||||
|
||||
func (s *Service) DeleteResource(ctx context.Context, args DeleteResourceArgs, reply *DeleteResourceReply) error {
|
||||
if err := s.store.DeleteResource(ctx, args.Origin, args.ResourceID); err != nil {
|
||||
return errors.WithStack(err)
|
||||
}
|
||||
|
||||
*reply = DeleteResourceReply{}
|
||||
|
||||
return nil
|
||||
}
|
41
pkg/storage/driver/rpc/server/share/find_resources.go
Normal file
41
pkg/storage/driver/rpc/server/share/find_resources.go
Normal file
@ -0,0 +1,41 @@
|
||||
package share
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"forge.cadoles.com/arcad/edge/pkg/storage/share"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
type FindResourcesArgs struct {
|
||||
Options *share.FindResourcesOptions
|
||||
}
|
||||
|
||||
type FindResourcesReply struct {
|
||||
Resources []*SerializableResource
|
||||
}
|
||||
|
||||
func (s *Service) FindResources(ctx context.Context, args FindResourcesArgs, reply *FindResourcesReply) error {
|
||||
resources, err := s.store.FindResources(ctx, withFindResourcesOptions(args.Options))
|
||||
if err != nil {
|
||||
return errors.WithStack(err)
|
||||
}
|
||||
|
||||
serializableResources := make([]*SerializableResource, len(resources))
|
||||
for resIdx, r := range resources {
|
||||
serializableResources[resIdx] = FromResource(r)
|
||||
}
|
||||
|
||||
*reply = FindResourcesReply{
|
||||
Resources: serializableResources,
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func withFindResourcesOptions(opts *share.FindResourcesOptions) share.FindResourcesOptionFunc {
|
||||
return func(o *share.FindResourcesOptions) {
|
||||
o.Name = opts.Name
|
||||
o.ValueType = opts.ValueType
|
||||
}
|
||||
}
|
31
pkg/storage/driver/rpc/server/share/get_resource.go
Normal file
31
pkg/storage/driver/rpc/server/share/get_resource.go
Normal file
@ -0,0 +1,31 @@
|
||||
package share
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"forge.cadoles.com/arcad/edge/pkg/app"
|
||||
"forge.cadoles.com/arcad/edge/pkg/storage/share"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
type GetResourceArgs struct {
|
||||
Origin app.ID
|
||||
ResourceID share.ResourceID
|
||||
}
|
||||
|
||||
type GetResourceReply struct {
|
||||
Resource *SerializableResource
|
||||
}
|
||||
|
||||
func (s *Service) GetResource(ctx context.Context, args GetResourceArgs, reply *GetResourceReply) error {
|
||||
resource, err := s.store.GetResource(ctx, args.Origin, args.ResourceID)
|
||||
if err != nil {
|
||||
return errors.WithStack(err)
|
||||
}
|
||||
|
||||
*reply = GetResourceReply{
|
||||
Resource: FromResource(resource),
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
94
pkg/storage/driver/rpc/server/share/serializable.go
Normal file
94
pkg/storage/driver/rpc/server/share/serializable.go
Normal file
@ -0,0 +1,94 @@
|
||||
package share
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"forge.cadoles.com/arcad/edge/pkg/app"
|
||||
"forge.cadoles.com/arcad/edge/pkg/storage/share"
|
||||
)
|
||||
|
||||
func FromResource(res share.Resource) *SerializableResource {
|
||||
serializableAttributes := make([]*SerializableAttribute, len(res.Attributes()))
|
||||
for attrIdx, attr := range res.Attributes() {
|
||||
serializableAttributes[attrIdx] = FromAttribute(attr)
|
||||
}
|
||||
|
||||
return &SerializableResource{
|
||||
ID_: res.ID(),
|
||||
Origin_: res.Origin(),
|
||||
Attributes_: serializableAttributes,
|
||||
}
|
||||
}
|
||||
|
||||
func FromAttribute(attr share.Attribute) *SerializableAttribute {
|
||||
return &SerializableAttribute{
|
||||
Name_: attr.Name(),
|
||||
Value_: attr.Value(),
|
||||
Type_: attr.Type(),
|
||||
UpdatedAt_: attr.UpdatedAt(),
|
||||
CreatedAt_: attr.CreatedAt(),
|
||||
}
|
||||
}
|
||||
|
||||
type SerializableResource struct {
|
||||
ID_ share.ResourceID
|
||||
Origin_ app.ID
|
||||
Attributes_ []*SerializableAttribute
|
||||
}
|
||||
|
||||
// Attributes implements share.Resource.
|
||||
func (r *SerializableResource) Attributes() []share.Attribute {
|
||||
attributes := make([]share.Attribute, len(r.Attributes_))
|
||||
for idx, attr := range r.Attributes_ {
|
||||
attributes[idx] = attr
|
||||
}
|
||||
|
||||
return attributes
|
||||
}
|
||||
|
||||
// ID implements share.Resource.
|
||||
func (r *SerializableResource) ID() share.ResourceID {
|
||||
return r.ID_
|
||||
}
|
||||
|
||||
// Origin implements share.Resource.
|
||||
func (r *SerializableResource) Origin() app.ID {
|
||||
return r.Origin_
|
||||
}
|
||||
|
||||
var _ share.Resource = &SerializableResource{}
|
||||
|
||||
type SerializableAttribute struct {
|
||||
Name_ string
|
||||
Value_ any
|
||||
Type_ share.ValueType
|
||||
UpdatedAt_ time.Time
|
||||
CreatedAt_ time.Time
|
||||
}
|
||||
|
||||
// CreatedAt implements share.Attribute.
|
||||
func (a *SerializableAttribute) CreatedAt() time.Time {
|
||||
return a.CreatedAt_
|
||||
}
|
||||
|
||||
// Name implements share.Attribute.
|
||||
func (a *SerializableAttribute) Name() string {
|
||||
return a.Name_
|
||||
}
|
||||
|
||||
// Type implements share.Attribute.
|
||||
func (a *SerializableAttribute) Type() share.ValueType {
|
||||
return a.Type_
|
||||
}
|
||||
|
||||
// UpdatedAt implements share.Attribute.
|
||||
func (a *SerializableAttribute) UpdatedAt() time.Time {
|
||||
return a.UpdatedAt_
|
||||
}
|
||||
|
||||
// Value implements share.Attribute.
|
||||
func (a *SerializableAttribute) Value() any {
|
||||
return a.Value_
|
||||
}
|
||||
|
||||
var _ share.Attribute = &SerializableAttribute{}
|
13
pkg/storage/driver/rpc/server/share/service.go
Normal file
13
pkg/storage/driver/rpc/server/share/service.go
Normal file
@ -0,0 +1,13 @@
|
||||
package share
|
||||
|
||||
import (
|
||||
"forge.cadoles.com/arcad/edge/pkg/storage/share"
|
||||
)
|
||||
|
||||
type Service struct {
|
||||
store share.Store
|
||||
}
|
||||
|
||||
func NewService(store share.Store) *Service {
|
||||
return &Service{store}
|
||||
}
|
37
pkg/storage/driver/rpc/server/share/update_attributes.go
Normal file
37
pkg/storage/driver/rpc/server/share/update_attributes.go
Normal file
@ -0,0 +1,37 @@
|
||||
package share
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"forge.cadoles.com/arcad/edge/pkg/app"
|
||||
"forge.cadoles.com/arcad/edge/pkg/storage/share"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
type UpdateAttributesArgs struct {
|
||||
Origin app.ID
|
||||
ResourceID share.ResourceID
|
||||
Attributes []*SerializableAttribute
|
||||
}
|
||||
|
||||
type UpdateAttributesReply struct {
|
||||
Resource *SerializableResource
|
||||
}
|
||||
|
||||
func (s *Service) UpdateAttributes(ctx context.Context, args UpdateAttributesArgs, reply *UpdateAttributesReply) error {
|
||||
attributes := make([]share.Attribute, len(args.Attributes))
|
||||
for idx, attr := range args.Attributes {
|
||||
attributes[idx] = attr
|
||||
}
|
||||
|
||||
resource, err := s.store.UpdateAttributes(ctx, args.Origin, args.ResourceID, attributes...)
|
||||
if err != nil {
|
||||
return errors.WithStack(err)
|
||||
}
|
||||
|
||||
*reply = UpdateAttributesReply{
|
||||
Resource: FromResource(resource),
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
Reference in New Issue
Block a user