1
0
mirror of https://github.com/raseels-repos/golang-saas-starter-kit.git synced 2025-06-06 23:46:29 +02:00

125 lines
3.4 KiB
Go

// All material is licensed under the Apache License Version 2.0, January 2004
// http://www.apache.org/licenses/LICENSE-2.0
package db
import (
"context"
"encoding/json"
"time"
"github.com/pkg/errors"
"go.opencensus.io/trace"
mgo "gopkg.in/mgo.v2"
)
// ErrInvalidDBProvided is returned in the event that an uninitialized db is
// used to perform actions against.
var ErrInvalidDBProvided = errors.New("invalid DB provided")
// DB is a collection of support for different DB technologies. Currently
// only MongoDB has been implemented. We want to be able to access the raw
// database support for the given DB so an interface does not work. Each
// database is too different.
type DB struct {
// MongoDB Support.
database *mgo.Database
session *mgo.Session
}
// New returns a new DB value for use with MongoDB based on a registered
// master session.
func New(url string, timeout time.Duration) (*DB, error) {
// Set the default timeout for the session.
if timeout == 0 {
timeout = 60 * time.Second
}
// Create a session which maintains a pool of socket connections
// to our MongoDB.
ses, err := mgo.DialWithTimeout(url, timeout)
if err != nil {
return nil, errors.Wrapf(err, "mgo.DialWithTimeout: %s,%v", url, timeout)
}
// Reads may not be entirely up-to-date, but they will always see the
// history of changes moving forward, the data read will be consistent
// across sequential queries in the same session, and modifications made
// within the session will be observed in following queries (read-your-writes).
// http://godoc.org/labix.org/v2/mgo#Session.SetMode
ses.SetMode(mgo.Monotonic, true)
db := DB{
database: ses.DB(""),
session: ses,
}
return &db, nil
}
// Close closes a DB value being used with MongoDB.
func (db *DB) Close() {
db.session.Close()
}
// Copy returns a new DB value for use with MongoDB based on master session.
func (db *DB) Copy() *DB {
ses := db.session.Copy()
// As per the mgo documentation, https://godoc.org/gopkg.in/mgo.v2#Session.DB
// if no database name is specified, then use the default one, or the one that
// the connection was dialed with.
newDB := DB{
database: ses.DB(""),
session: ses,
}
return &newDB
}
// Execute is used to execute MongoDB commands.
func (db *DB) Execute(ctx context.Context, collName string, f func(*mgo.Collection) error) error {
ctx, span := trace.StartSpan(ctx, "platform.DB.Execute")
defer span.End()
if db == nil || db.session == nil {
return errors.Wrap(ErrInvalidDBProvided, "db == nil || db.session == nil")
}
return f(db.database.C(collName))
}
// ExecuteTimeout is used to execute MongoDB commands with a timeout.
func (db *DB) ExecuteTimeout(ctx context.Context, timeout time.Duration, collName string, f func(*mgo.Collection) error) error {
ctx, span := trace.StartSpan(ctx, "platform.DB.ExecuteTimeout")
defer span.End()
if db == nil || db.session == nil {
return errors.Wrap(ErrInvalidDBProvided, "db == nil || db.session == nil")
}
db.session.SetSocketTimeout(timeout)
return f(db.database.C(collName))
}
// StatusCheck validates the DB status good.
func (db *DB) StatusCheck(ctx context.Context) error {
ctx, span := trace.StartSpan(ctx, "platform.DB.StatusCheck")
defer span.End()
return nil
}
// Query provides a string version of the value
func Query(value interface{}) string {
json, err := json.Marshal(value)
if err != nil {
return ""
}
return string(json)
}