Skip to content

Commit

Permalink
chore(api): use transaction for member addition and invite sending
Browse files Browse the repository at this point in the history
To prevent errors where a member is created in the namespace but the
invite cannot be sent, we’re encapsulating this process within a
database transaction.
  • Loading branch information
heiytor committed Sep 11, 2024
1 parent e5a359f commit b706ab2
Show file tree
Hide file tree
Showing 2 changed files with 180 additions and 131 deletions.
45 changes: 30 additions & 15 deletions api/services/namespace.go
Original file line number Diff line number Diff line change
Expand Up @@ -256,27 +256,42 @@ func (s *service) AddNamespaceMember(ctx context.Context, req *requests.Namespac
AddedAt: addedAt,
ExpiresAt: expiresAt,
Role: req.MemberRole,
Status: models.MemberStatusAccepted,
}

// In cloud instances, the member must accept the invite before enter in the namespace.
if envs.IsCloud() {
member.Status = models.MemberStatusPending
if err := s.client.InviteMember(ctx, req.TenantID, member.ID, req.FowardedHost); err != nil {
return nil, err
}
if err := s.store.WithTransaction(ctx, s.addMember(req.TenantID, req.FowardedHost, member)); err != nil {
return nil, err
}

if err := s.store.NamespaceAddMember(ctx, req.TenantID, member); err != nil {
switch {
case errors.Is(err, mongo.ErrNamespaceDuplicatedMember):
return nil, NewErrNamespaceMemberDuplicated(passiveUser.ID, err)
default:
return nil, err
return s.store.NamespaceGet(ctx, req.TenantID, true)
}

// addMember returns a transaction callback that adds a member and sends an invite if the instance is cloud.
func (s *service) addMember(tenantID, fowardedHost string, member *models.Member) store.TransactionCb {
return func(ctx context.Context) error {
// In cloud instances, the member must accept the invite before enter in the namespace.
if envs.IsCloud() {
member.Status = models.MemberStatusPending
} else {
member.Status = models.MemberStatusAccepted
}
}

return s.store.NamespaceGet(ctx, req.TenantID, true)
if err := s.store.NamespaceAddMember(ctx, tenantID, member); err != nil {
switch {
case errors.Is(err, mongo.ErrNamespaceDuplicatedMember):
return NewErrNamespaceMemberDuplicated(member.ID, err)
default:
return err
}
}

if envs.IsCloud() {
if err := s.client.InviteMember(ctx, tenantID, member.ID, fowardedHost); err != nil {
return err
}
}

return nil
}
}

func (s *service) UpdateNamespaceMember(ctx context.Context, req *requests.NamespaceUpdateMember) error {
Expand Down
Loading

0 comments on commit b706ab2

Please sign in to comment.