Skip to content

Commit

Permalink
feat: flattening getReceiver call
Browse files Browse the repository at this point in the history
  • Loading branch information
Manish Dangi committed Mar 6, 2024
1 parent 50b59c6 commit b6d054c
Show file tree
Hide file tree
Showing 8 changed files with 188 additions and 50 deletions.
31 changes: 16 additions & 15 deletions core/receiver/mocks/receiver_repository.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion core/receiver/receiver.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import (
type Repository interface {
List(context.Context, Filter) ([]Receiver, error)
Create(context.Context, *Receiver) error
Get(context.Context, uint64) (*Receiver, error)
Get(context.Context, uint64, bool) (*Receiver, error)
Update(context.Context, *Receiver) error
Delete(context.Context, uint64) error
}
Expand Down
12 changes: 3 additions & 9 deletions core/receiver/service.go
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,7 @@ func (s *Service) Get(ctx context.Context, id uint64, gopts ...GetOption) (*Rece
g(opt)
}

rcv, err := s.repository.Get(ctx, id)
rcv, err := s.repository.Get(ctx, id, opt.withExpand)
if err != nil {
if errors.As(err, new(NotFoundError)) {
return nil, errors.ErrNotFound.WithMsgf(err.Error())
Expand All @@ -133,12 +133,6 @@ func (s *Service) Get(ctx context.Context, id uint64, gopts ...GetOption) (*Rece
return nil, err
}

receivers, err := s.ExpandParents(ctx, []Receiver{*rcv})
if err != nil {
return nil, err
}
rcv = &receivers[0]

transformedConfigs, err := receiverPlugin.PostHookDBTransformConfigs(ctx, rcv.Configurations)
if err != nil {
return nil, err
Expand All @@ -158,7 +152,7 @@ func (s *Service) Get(ctx context.Context, id uint64, gopts ...GetOption) (*Rece
}

func (s *Service) Update(ctx context.Context, rcv *Receiver) error {
oldReceiver, err := s.repository.Get(ctx, rcv.ID)
oldReceiver, err := s.repository.Get(ctx, rcv.ID, false)
if err != nil {
if errors.As(err, new(NotFoundError)) {
return errors.ErrNotFound.WithMsgf(err.Error())
Expand Down Expand Up @@ -235,7 +229,7 @@ func (s *Service) validateParent(ctx context.Context, rcv *Receiver) error {
return nil
}

parentRcv, err := s.repository.Get(ctx, rcv.ParentID)
parentRcv, err := s.repository.Get(ctx, rcv.ParentID, false)
if err != nil {
return errors.ErrInvalid.WithMsgf("failed to check parent id %d", rcv.ParentID).WithCausef(err.Error())
}
Expand Down
81 changes: 67 additions & 14 deletions core/receiver/service_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -164,7 +164,7 @@ func TestService_CreateReceiver(t *testing.T) {
{
Description: "should return error if type child but wrong parent",
Setup: func(rr *mocks.Repository, ss *mocks.ConfigResolver) {
rr.EXPECT().Get(mock.AnythingOfType("context.todoCtx"), uint64(2)).Return(&receiver.Receiver{Type: receiver.TypeFile}, nil)
rr.EXPECT().Get(mock.AnythingOfType("context.todoCtx"), uint64(2), false).Return(&receiver.Receiver{Type: receiver.TypeFile}, nil)
},
Rcv: &receiver.Receiver{
ID: 123,
Expand All @@ -179,7 +179,7 @@ func TestService_CreateReceiver(t *testing.T) {
{
Description: "should return error if validateParent return error",
Setup: func(rr *mocks.Repository, ss *mocks.ConfigResolver) {
rr.EXPECT().Get(mock.AnythingOfType("context.todoCtx"), uint64(2)).Return(nil, errors.New("some error"))
rr.EXPECT().Get(mock.AnythingOfType("context.todoCtx"), uint64(2), false).Return(nil, errors.New("some error"))
},
Rcv: &receiver.Receiver{
ID: 123,
Expand Down Expand Up @@ -298,14 +298,14 @@ func TestService_GetReceiver(t *testing.T) {
{
Description: "should return error if Get repository error",
Setup: func(rr *mocks.Repository, ss *mocks.ConfigResolver) {
rr.EXPECT().Get(mock.AnythingOfType("context.todoCtx"), testID).Return(nil, errors.New("some error"))
rr.EXPECT().Get(mock.AnythingOfType("context.todoCtx"), testID, true).Return(nil, errors.New("some error"))
},
Err: errors.New("some error"),
},
{
Description: "should return error if type unknown",
Setup: func(rr *mocks.Repository, ss *mocks.ConfigResolver) {
rr.EXPECT().Get(mock.AnythingOfType("context.todoCtx"), testID).Return(&receiver.Receiver{
rr.EXPECT().Get(mock.AnythingOfType("context.todoCtx"), testID, true).Return(&receiver.Receiver{
Type: "random",
}, nil)
},
Expand All @@ -314,14 +314,14 @@ func TestService_GetReceiver(t *testing.T) {
{
Description: "should return error not found if Get repository return not found error",
Setup: func(rr *mocks.Repository, ss *mocks.ConfigResolver) {
rr.EXPECT().Get(mock.AnythingOfType("context.todoCtx"), testID).Return(nil, receiver.NotFoundError{})
rr.EXPECT().Get(mock.AnythingOfType("context.todoCtx"), testID, true).Return(nil, receiver.NotFoundError{})
},
Err: errors.New("receiver not found"),
},
{
Description: "should return error if Get repository success and decrypt error",
Setup: func(rr *mocks.Repository, ss *mocks.ConfigResolver) {
rr.EXPECT().Get(mock.AnythingOfType("context.todoCtx"), testID).Return(&receiver.Receiver{
rr.EXPECT().Get(mock.AnythingOfType("context.todoCtx"), testID, true).Return(&receiver.Receiver{
ID: 10,
Name: "foo",
Type: receiver.TypeSlack,
Expand All @@ -343,7 +343,7 @@ func TestService_GetReceiver(t *testing.T) {
{
Description: "should success if Get repository and decrypt success",
Setup: func(rr *mocks.Repository, ss *mocks.ConfigResolver) {
rr.EXPECT().Get(mock.AnythingOfType("context.todoCtx"), testID).Return(&receiver.Receiver{
rr.EXPECT().Get(mock.AnythingOfType("context.todoCtx"), testID, true).Return(&receiver.Receiver{
ID: 10,
Name: "foo",
Type: receiver.TypeSlack,
Expand Down Expand Up @@ -385,6 +385,58 @@ func TestService_GetReceiver(t *testing.T) {
},
Err: nil,
},
{
Description: "should success if Get repository and decrypt success with parent",
Setup: func(rr *mocks.Repository, ss *mocks.ConfigResolver) {
rr.EXPECT().Get(mock.AnythingOfType("context.todoCtx"), testID, true).Return(&receiver.Receiver{
ID: 10,
Name: "foo",
Type: receiver.TypeSlackChannel,
Labels: map[string]string{
"foo": "bar",
},
Configurations: map[string]any{
"channel_name": "de",
"token": "val",
},
CreatedAt: timeNow,
UpdatedAt: timeNow,
ParentID: 9,
}, nil)
ss.EXPECT().PostHookDBTransformConfigs(mock.AnythingOfType("context.todoCtx"), map[string]any{
"token": "val",
"channel_name": "de",
}).Return(map[string]any{
"token": "decrypted_key",
"channel_name": "de",
}, nil)
ss.EXPECT().BuildData(mock.AnythingOfType("context.todoCtx"), map[string]any{
"token": "decrypted_key",
"channel_name": "de",
}).Return(map[string]any{
"newdata": "populated",
}, nil)
},
ExpectedReceiver: &receiver.Receiver{
ID: 10,
Name: "foo",
Type: receiver.TypeSlackChannel,
Labels: map[string]string{
"foo": "bar",
},
Data: map[string]any{
"newdata": "populated",
},
Configurations: map[string]any{
"token": "decrypted_key",
"channel_name": "de",
},
CreatedAt: timeNow,
UpdatedAt: timeNow,
ParentID: 9,
},
Err: nil,
},
}
)

Expand All @@ -396,7 +448,8 @@ func TestService_GetReceiver(t *testing.T) {
)

registry := map[string]receiver.ConfigResolver{
receiver.TypeSlack: resolverMock,
receiver.TypeSlack: resolverMock,
receiver.TypeSlackChannel: resolverMock,
}

svc := receiver.NewService(repositoryMock, registry)
Expand Down Expand Up @@ -431,7 +484,7 @@ func TestService_UpdateReceiver(t *testing.T) {
{
Description: "should return error if get receiver return error",
Setup: func(rr *mocks.Repository, ss *mocks.ConfigResolver) {
rr.EXPECT().Get(mock.AnythingOfType("context.todoCtx"), mock.AnythingOfType("uint64")).Return(nil, errors.New("some error"))
rr.EXPECT().Get(mock.AnythingOfType("context.todoCtx"), mock.AnythingOfType("uint64"), false).Return(nil, errors.New("some error"))
},
Rcv: &receiver.Receiver{
ID: 123,
Expand All @@ -441,7 +494,7 @@ func TestService_UpdateReceiver(t *testing.T) {
{
Description: "should return error if type unknown",
Setup: func(rr *mocks.Repository, ss *mocks.ConfigResolver) {
rr.EXPECT().Get(mock.AnythingOfType("context.todoCtx"), mock.AnythingOfType("uint64")).Return(&receiver.Receiver{
rr.EXPECT().Get(mock.AnythingOfType("context.todoCtx"), mock.AnythingOfType("uint64"), false).Return(&receiver.Receiver{
Type: "random",
}, nil)
},
Expand All @@ -453,7 +506,7 @@ func TestService_UpdateReceiver(t *testing.T) {
{
Description: "should return error if PreHookDBTransformConfigs return error",
Setup: func(rr *mocks.Repository, ss *mocks.ConfigResolver) {
rr.EXPECT().Get(mock.AnythingOfType("context.todoCtx"), mock.AnythingOfType("uint64")).Return(&receiver.Receiver{
rr.EXPECT().Get(mock.AnythingOfType("context.todoCtx"), mock.AnythingOfType("uint64"), false).Return(&receiver.Receiver{
ID: 123,
Type: receiver.TypeSlack,
Configurations: map[string]any{
Expand All @@ -474,7 +527,7 @@ func TestService_UpdateReceiver(t *testing.T) {
{
Description: "should return error if Update repository return error",
Setup: func(rr *mocks.Repository, ss *mocks.ConfigResolver) {
rr.EXPECT().Get(mock.AnythingOfType("context.todoCtx"), mock.AnythingOfType("uint64")).Return(&receiver.Receiver{
rr.EXPECT().Get(mock.AnythingOfType("context.todoCtx"), mock.AnythingOfType("uint64"), false).Return(&receiver.Receiver{
ID: 123,
Type: receiver.TypeSlack,
Configurations: map[string]any{
Expand Down Expand Up @@ -504,7 +557,7 @@ func TestService_UpdateReceiver(t *testing.T) {
{
Description: "should return nil error if no error returned",
Setup: func(rr *mocks.Repository, ss *mocks.ConfigResolver) {
rr.EXPECT().Get(mock.AnythingOfType("context.todoCtx"), mock.AnythingOfType("uint64")).Return(&receiver.Receiver{
rr.EXPECT().Get(mock.AnythingOfType("context.todoCtx"), mock.AnythingOfType("uint64"), false).Return(&receiver.Receiver{
ID: 123,
Type: receiver.TypeSlack,
Configurations: map[string]any{
Expand Down Expand Up @@ -533,7 +586,7 @@ func TestService_UpdateReceiver(t *testing.T) {
}, {
Description: "should return error not found if repository return not found error",
Setup: func(rr *mocks.Repository, ss *mocks.ConfigResolver) {
rr.EXPECT().Get(mock.AnythingOfType("context.todoCtx"), mock.AnythingOfType("uint64")).Return(&receiver.Receiver{
rr.EXPECT().Get(mock.AnythingOfType("context.todoCtx"), mock.AnythingOfType("uint64"), false).Return(&receiver.Receiver{
ID: 123,
Type: receiver.TypeSlack,
Configurations: map[string]any{
Expand Down
14 changes: 14 additions & 0 deletions internal/store/model/receiver.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,19 @@ type Receiver struct {
UpdatedAt time.Time `db:"updated_at"`
}

type ExpandedReceiver struct {
ID uint64 `db:"id"`
Name string `db:"name"`
Type string `db:"type"`
Labels pgc.StringStringMap `db:"labels"`
Configurations pgc.StringAnyMap `db:"configurations"`
Data pgc.StringAnyMap `db:"-"` //TODO do we need this?
ParentID sql.NullInt64 `db:"parent_id"`
CreatedAt time.Time `db:"created_at"`
UpdatedAt time.Time `db:"updated_at"`
ParentConfigurations pgc.StringAnyMap `db:"parent_configurations"`
}

func (rcv *Receiver) FromDomain(t receiver.Receiver) {
rcv.ID = t.ID
rcv.Name = t.Name
Expand Down Expand Up @@ -53,3 +66,4 @@ func (rcv *Receiver) ToDomain() *receiver.Receiver {
UpdatedAt: rcv.UpdatedAt,
}
}

45 changes: 35 additions & 10 deletions internal/store/postgres/receiver.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,17 @@ var receiverListQueryBuilder = sq.Select(
"updated_at",
).From("receivers")

var receiverListLeftJoinSelfQueryBuilder = sq.Select(
"r.id",
"r.name",
"r.type",
"r.labels",
"r.configurations || p.configurations AS configurations",
"r.parent_id",
"r.created_at",
"r.updated_at",
).From("receivers r")

// ReceiverRepository talks to the store to read or insert data
type ReceiverRepository struct {
client *pgc.Client
Expand Down Expand Up @@ -117,18 +128,32 @@ func (r ReceiverRepository) Create(ctx context.Context, rcv *receiver.Receiver)
return nil
}

func (r ReceiverRepository) Get(ctx context.Context, id uint64) (*receiver.Receiver, error) {
query, args, err := receiverListQueryBuilder.Where("id = ?", id).PlaceholderFormat(sq.Dollar).ToSql()
if err != nil {
return nil, err
}

func (r ReceiverRepository) Get(ctx context.Context, id uint64, withExpand bool) (*receiver.Receiver, error) {
var receiverModel model.Receiver
if err := r.client.GetContext(ctx, &receiverModel, query, args...); err != nil {
if errors.Is(err, sql.ErrNoRows) {
return nil, receiver.NotFoundError{ID: id}
if withExpand {
query, args, err := receiverListLeftJoinSelfQueryBuilder.LeftJoin("receivers p ON r.parent_id = p.id"). Where("r.id = ?", id).PlaceholderFormat(sq.Dollar).ToSql()

if err != nil {
return nil, err
}
if err := r.client.GetContext(ctx, &receiverModel, query, args...); err != nil {
if errors.Is(err, sql.ErrNoRows) {
return nil, receiver.NotFoundError{ID: id}
}
return nil, err
}
return receiverModel.ToDomain(), nil
} else {
query, args, err := receiverListQueryBuilder.Where("id = ?", id).PlaceholderFormat(sq.Dollar).ToSql()
if err != nil {
return nil, err
}
if err := r.client.GetContext(ctx, &receiverModel, query, args...); err != nil {
if errors.Is(err, sql.ErrNoRows) {
return nil, receiver.NotFoundError{ID: id}
}
return nil, err
}
return nil, err
}

return receiverModel.ToDomain(), nil
Expand Down
Loading

0 comments on commit b6d054c

Please sign in to comment.