Skip to content

Commit

Permalink
Simplify wrapper
Browse files Browse the repository at this point in the history
  • Loading branch information
nakabonne committed Aug 24, 2020
1 parent bb7bc70 commit 1dc024c
Show file tree
Hide file tree
Showing 3 changed files with 58 additions and 91 deletions.
4 changes: 2 additions & 2 deletions pkg/datastore/mongodb/iterator.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,14 +31,14 @@ func (it *Iterator) Next(dst interface{}) error {
if !it.cur.Next(it.ctx) {
return datastore.ErrIteratorDone
}
wrapper, err := newWrapper(dst)
wrapper, err := wrapModel(dst)
if err != nil {
return err
}
if err := it.cur.Decode(wrapper); err != nil {
return err
}
return wrapper.storeModel(dst)
return extractModel(wrapper, dst)
}

func (it *Iterator) Cursor() (string, error) {
Expand Down
133 changes: 51 additions & 82 deletions pkg/datastore/mongodb/model_wrapper.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,15 +20,9 @@ import (
"github.com/pipe-cd/pipe/pkg/model"
)

// modelWrapper wraps a model representing a BSON document so that the model comes with "_id".
type modelWrapper interface {
// setID populates the given id to its own "_id".
setID(id string)
// storeModel stores the unwrapped model in the value pointed to by v.
storeModel(v interface{}) error
}

func newWrapper(entity interface{}) (modelWrapper, error) {
// wrapModel returns a wrapper corresponding to the given entity.
// A wrapper wraps a model representing BSON a document so that the model comes with "_id".
func wrapModel(entity interface{}) (interface{}, error) {
switch e := entity.(type) {
case *model.Application:
if e == nil {
Expand Down Expand Up @@ -79,108 +73,83 @@ func newWrapper(entity interface{}) (modelWrapper, error) {
Project: *e,
}, nil
default:
return nil, fmt.Errorf("the given entity is unknown type")
return nil, fmt.Errorf("%T is not supported", e)
}
}

type application struct {
model.Application `bson:",inline"`
ID string `bson:"_id"`
}
// extractModel stores the unwrapped model in the value pointed to by e.
func extractModel(wrapper interface{}, e interface{}) error {
msg := "entity type doesn't correspond to the wrapper type (%T)"

func (a *application) setID(id string) {
a.ID = id
switch w := wrapper.(type) {
case *application:
e, ok := e.(*model.Application)
if !ok {
return fmt.Errorf(msg, w)
}
*e = w.Application
case *command:
e, ok := e.(*model.Command)
if !ok {
return fmt.Errorf(msg, w)
}
*e = w.Command
case *deployment:
e, ok := e.(*model.Deployment)
if !ok {
return fmt.Errorf(msg, w)
}
*e = w.Deployment
case *environment:
e, ok := e.(*model.Environment)
if !ok {
return fmt.Errorf(msg, w)
}
*e = w.Environment
case *piped:
e, ok := e.(*model.Piped)
if !ok {
return fmt.Errorf(msg, w)
}
*e = w.Piped
case *project:
e, ok := e.(*model.Project)
if !ok {
return fmt.Errorf(msg, w)
}
*e = w.Project
default:
return fmt.Errorf("%T is not supported", w)
}
return nil
}

func (a *application) storeModel(v interface{}) error {
if app, ok := v.(*model.Application); ok {
*app = a.Application
return nil
}
return fmt.Errorf("the given v is not a pointer to model.Application")
type application struct {
model.Application `bson:",inline"`
ID string `bson:"_id"`
}

type command struct {
model.Command `bson:",inline"`
ID string `bson:"_id"`
}

func (c *command) setID(id string) {
c.ID = id
}

func (c *command) storeModel(v interface{}) error {
if command, ok := v.(*model.Command); ok {
*command = c.Command
return nil
}
return fmt.Errorf("the given v is not a pointer to model.Command")
}

type deployment struct {
model.Deployment `bson:",inline"`
ID string `bson:"_id"`
}

func (d *deployment) setID(id string) {
d.ID = id
}

func (d *deployment) storeModel(v interface{}) error {
if deployment, ok := v.(*model.Deployment); ok {
*deployment = d.Deployment
return nil
}
return fmt.Errorf("the given v is not a pointer to model.Deployment")
}

type environment struct {
model.Environment `bson:",inline"`
ID string `bson:"_id"`
}

func (e *environment) setID(id string) {
e.ID = id
}

func (e *environment) storeModel(v interface{}) error {
if environment, ok := v.(*model.Environment); ok {
*environment = e.Environment
return nil
}
return fmt.Errorf("the given v is not a pointer to model.Environment")
}

type piped struct {
model.Piped `bson:",inline"`
ID string `bson:"_id"`
}

func (p *piped) setID(id string) {
p.ID = id
}

func (p *piped) storeModel(v interface{}) error {
if piped, ok := v.(*model.Piped); ok {
*piped = p.Piped
return nil
}
return fmt.Errorf("the given v is not a pointer to model.Piped")
}

type project struct {
model.Project `bson:",inline"`
ID string `bson:"_id"`
}

func (p *project) setID(id string) {
p.ID = id
}

func (p *project) storeModel(v interface{}) error {
if project, ok := v.(*model.Project); ok {
*project = p.Project
return nil
}
return fmt.Errorf("the given v is not a pointer to model.Project")
}
12 changes: 5 additions & 7 deletions pkg/datastore/mongodb/mongodb.go
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,7 @@ func (m *MongoDB) Find(ctx context.Context, kind string, opts datastore.ListOpti
}

func (m *MongoDB) Get(ctx context.Context, kind, id string, v interface{}) error {
wrapper, err := newWrapper(v)
wrapper, err := wrapModel(v)
if err != nil {
return err
}
Expand All @@ -128,11 +128,11 @@ func (m *MongoDB) Get(ctx context.Context, kind, id string, v interface{}) error
return err
}

return wrapper.storeModel(v)
return extractModel(wrapper, v)
}

func (m *MongoDB) Create(ctx context.Context, kind, id string, entity interface{}) error {
wrapper, err := newWrapper(entity)
wrapper, err := wrapModel(entity)
if err != nil {
return err
}
Expand Down Expand Up @@ -170,7 +170,7 @@ func (m *MongoDB) Create(ctx context.Context, kind, id string, entity interface{
}

func (m *MongoDB) Put(ctx context.Context, kind, id string, entity interface{}) error {
wrapper, err := newWrapper(entity)
wrapper, err := wrapModel(entity)
if err != nil {
return err
}
Expand Down Expand Up @@ -204,12 +204,10 @@ func (m *MongoDB) Update(ctx context.Context, kind, id string, factory datastore
)
return err
}
wrapper, err := newWrapper(entity)
wrapper, err := wrapModel(entity)
if err != nil {
return err
}
// NOTE: Not allowed to give it an empty "_id".
wrapper.setID(id)
update := bson.D{{"$set", wrapper}}
if _, err := col.UpdateOne(ctx, makePrimaryKeyFilter(id), update); err != nil {
m.logger.Error("failed to update entity",
Expand Down

0 comments on commit 1dc024c

Please sign in to comment.