1
0
mirror of https://github.com/mainflux/mainflux.git synced 2025-05-02 22:17:10 +08:00
Aleksandar Novaković 58cdf2cddc MF-312 - Implement basic MongoDB reader (#344)
* Add mongodb reader service

Signed-off-by: Aleksandar Novakovic <aleksandar.novakovic@mainflux.com>

* Add tests for mongodb reader service

Signed-off-by: Aleksandar Novakovic <aleksandar.novakovic@mainflux.com>

* Add documentation for mongodb reader service

Signed-off-by: Aleksandar Novakovic <aleksandar.novakovic@mainflux.com>

* Fix test function name

Signed-off-by: Aleksandar Novakovic <aleksandar.novakovic@mainflux.com>

* Update comment in docker-compose for mongodb-reader service

Signed-off-by: Aleksandar Novakovic <aleksandar.novakovic@mainflux.com>
2018-08-08 13:38:34 +02:00

185 lines
3.9 KiB
Go

package dbopt
import (
"reflect"
"github.com/mongodb/mongo-go-driver/core/readconcern"
"github.com/mongodb/mongo-go-driver/core/readpref"
"github.com/mongodb/mongo-go-driver/core/session"
"github.com/mongodb/mongo-go-driver/core/writeconcern"
)
var dbBundle = new(DatabaseBundle)
// Option represents a DB option.
type Option interface {
dbOption()
}
// optionFunc adds the option to the DB
type optionFunc func(*Database) error
// Database represents a database.
type Database struct {
ReadConcern *readconcern.ReadConcern
WriteConcern *writeconcern.WriteConcern
ReadPreference *readpref.ReadPref
}
// DatabaseBundle is a bundle of database options.
type DatabaseBundle struct {
option Option
next *DatabaseBundle
}
func (*DatabaseBundle) dbOption() {}
func (optionFunc) dbOption() {}
// DropDB represents all possible params for the dropDatabase() function
type DropDB interface {
dropDB()
}
// DropDBSession is the session for the dropDatabase() function.
type DropDBSession interface {
DropDB
ConvertDropDBSession() *session.Client
}
// DropDBSessionOpt is a dropDatabase session option.
type DropDBSessionOpt struct{}
func (DropDBSessionOpt) dropDB() {}
// ConvertDropDBSession implements the DropDBSession interface.
func (DropDBSessionOpt) ConvertDropDBSession() *session.Client {
return nil
}
// BundleDatabase bundles database options
func BundleDatabase(opts ...Option) *DatabaseBundle {
head := dbBundle
for _, opt := range opts {
newBundle := DatabaseBundle{
option: opt,
next: head,
}
head = &newBundle
}
return head
}
// ReadConcern sets the read concern.
func (db *DatabaseBundle) ReadConcern(rc *readconcern.ReadConcern) *DatabaseBundle {
return &DatabaseBundle{
option: ReadConcern(rc),
next: db,
}
}
// WriteConcern sets the write concern.
func (db *DatabaseBundle) WriteConcern(wc *writeconcern.WriteConcern) *DatabaseBundle {
return &DatabaseBundle{
option: WriteConcern(wc),
next: db,
}
}
// ReadPreference sets the read preference.
func (db *DatabaseBundle) ReadPreference(rp *readpref.ReadPref) *DatabaseBundle {
return &DatabaseBundle{
option: ReadPreference(rp),
next: db,
}
}
// Unbundle unbundles the options, returning a collection.
func (db *DatabaseBundle) Unbundle() (*Database, error) {
database := &Database{}
err := db.unbundle(database)
if err != nil {
return nil, err
}
return database, nil
}
// Helper that recursively unwraps the bundle.
func (db *DatabaseBundle) unbundle(database *Database) error {
if db == nil {
return nil
}
for head := db; head != nil && head.option != nil; head = head.next {
var err error
switch opt := head.option.(type) {
case *DatabaseBundle:
err = opt.unbundle(database) // add all bundle's options to database
case optionFunc:
err = opt(database) // add option to database
default:
return nil
}
if err != nil {
return err
}
}
return nil
}
// String implements the Stringer interface
func (db *DatabaseBundle) String() string {
if db == nil {
return ""
}
str := ""
for head := db; head != nil && head.option != nil; head = head.next {
switch opt := head.option.(type) {
case *DatabaseBundle:
str += opt.String()
case optionFunc:
str += reflect.TypeOf(opt).String() + "\n"
}
}
return str
}
// ReadConcern sets the read concern.
func ReadConcern(rc *readconcern.ReadConcern) Option {
return optionFunc(
func(d *Database) error {
if d.ReadConcern == nil {
d.ReadConcern = rc
}
return nil
})
}
// WriteConcern sets the write concern.
func WriteConcern(wc *writeconcern.WriteConcern) Option {
return optionFunc(
func(d *Database) error {
if d.WriteConcern == nil {
d.WriteConcern = wc
}
return nil
})
}
// ReadPreference sets the read preference.
func ReadPreference(rp *readpref.ReadPref) Option {
return optionFunc(
func(d *Database) error {
if d.ReadPreference == nil {
d.ReadPreference = rp
}
return nil
})
}