Skip to content

Instantly share code, notes, and snippets.

@icholy
Last active August 29, 2015 14:08
Show Gist options
  • Star 7 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save icholy/d56873d4733e5b8dec2a to your computer and use it in GitHub Desktop.
Save icholy/d56873d4733e5b8dec2a to your computer and use it in GitHub Desktop.
// Use Case:
//
// Say you have a bunch of decoupled components which access the same set of databases.
// Since database/sql does connection pooling it makes sense for the components to share instances of *sql.DB
// This package lets you do that with minimal code changes.
package dbmanager
import (
"database/sql"
"time"
"sync"
)
type Factory struct {
connections map[string]*DB
sync.Mutex
}
func NewFactory() *Factory {
return &Factory{
connections: make(map[string]*DB),
}
}
func (f *Factory) open(driverName, dataSourceName string) (*DB, error) {
db, err := sql.Open(driverName, dataSourceName)
if err != nil {
return nil, err
}
return &DB{
key: dataSourceName,
factory: f,
DB: db,
}, nil
}
// Open returns a DB connection.
func (f *Factory) Open(driverName, dataSourceName string) (*DB, error) {
f.Lock()
defer f.Unlock()
db, ok := f.connections[dataSourceName]
if !ok {
var err error
db, err = f.open(driverName, dataSourceName)
if err != nil {
return nil, err
}
f.connections[dataSourceName] = db
}
db.leases++
return db, nil
}
// release is called by the DB's Close() method
func (f *Factory) release(key string) {
f.Lock()
defer f.Unlock()
db, ok := f.connections[key]
if !ok {
return
}
db.leases--
if db.leases == 0 {
delete(f.connections, key)
db.DB.Close()
}
}
type DB struct {
leases int
key string
factory *Factory
*sql.DB
}
func (db *DB) Close() {
db.factory.release(db.key)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment