Skip to content

Commit

Permalink
Add db ping to check for liveness in CreateShare
Browse files Browse the repository at this point in the history
  • Loading branch information
Jesse Geens committed Jan 7, 2025
1 parent c1f4b58 commit ac1fc44
Show file tree
Hide file tree
Showing 3 changed files with 29 additions and 12 deletions.
8 changes: 8 additions & 0 deletions changelog/unreleased/pseudo-tx-share.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
Enhancement: pseudo-transactionalize sharing

Currently, sharing is not transactionalized: setting ACLs and writing the share to the db is completely independent. Because of this, sometimes a share is written to the database even though the ACLs have not been set. This enhancement fixes this by
a) first pinging the db
b) writing the ACLs
c) writing to the db

https://github.com/cs3org/reva/pull/5029
31 changes: 20 additions & 11 deletions internal/grpc/services/gateway/usershareprovider.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import (
"context"
"fmt"
"path"
"strings"

userpb "github.com/cs3org/go-cs3apis/cs3/identity/user/v1beta1"
rpc "github.com/cs3org/go-cs3apis/cs3/rpc/v1beta1"
Expand All @@ -44,6 +45,8 @@ func (s *svc) CreateShare(ctx context.Context, req *collaboration.CreateShareReq
return nil, errtypes.AlreadyExists("gateway: can't share the share folder itself")
}

log := appctx.GetLogger(ctx)

shareClient, err := pool.GetUserShareProviderClient(pool.Endpoint(s.c.UserShareProviderEndpoint))
if err != nil {
return &collaboration.CreateShareResponse{
Expand All @@ -53,19 +56,25 @@ func (s *svc) CreateShare(ctx context.Context, req *collaboration.CreateShareReq

// First we ping the db
// --------------------

// Then we set ACLs on the storage layer
// -------------------------------------

// First, we keep a copy of the original permissions, so we can revert if necessary
statResp, err := s.Stat(ctx, &provider.StatRequest{
Ref: &provider.Reference{
ResourceId: req.ResourceInfo.Id,
Path: req.ResourceInfo.Path,
// See ADR-REVA-003
_, err = shareClient.GetShare(ctx, &collaboration.GetShareRequest{
Ref: &collaboration.ShareReference{
Spec: &collaboration.ShareReference_Id{
Id: &collaboration.ShareId{
OpaqueId: "0",
},
},
},
})

originalPermissions := statResp.GetInfo().PermissionSet
// We expect a "not found" error when querying ID 0
// error checking is kind of ugly, because we lose the original error object over grpc
if !strings.HasSuffix(err.Error(), errtypes.NotFound("0").Error()) {
return nil, errtypes.InternalError("ShareManager is not online")
}

// Then we set ACLs on the storage layer
// -------------------------------------

// TODO(labkode): if both commits are enabled they could be done concurrently.
if s.c.CommitShareToStorageGrant {
Expand Down Expand Up @@ -101,8 +110,8 @@ func (s *svc) CreateShare(ctx context.Context, req *collaboration.CreateShareReq
// jfd: AFAICT this can only be determined by a storage driver - either the storage provider is queried first or the share manager needs to access the storage using a storage driver
res, err := shareClient.CreateShare(ctx, req)

// If this fails, we undo updating the storage provider
if err != nil {
log.Error().Msg("Failed to Create Share but ACLs are already set")
return nil, errors.Wrap(err, "gateway: error calling CreateShare")
}
if res.Status.Code != rpc.Code_CODE_OK {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -172,7 +172,7 @@ func (s *service) GetShare(ctx context.Context, req *collaboration.GetShareReque
if err != nil {
return &collaboration.GetShareResponse{
Status: status.NewInternal(ctx, err, "error getting share"),
}, nil
}, err
}

return &collaboration.GetShareResponse{
Expand Down

0 comments on commit ac1fc44

Please sign in to comment.