This is a simple way of having an in-memory DB which is safe to use across multiple goroutines without needing to use any kind of mutex for updates.
type FooDB interface {
Refresh() // Update the database
GetFoo(id int) (Foo, error)
}type InMemFooDB struct {
Ready chan bool
db *map[int]Foo // whatever format your data takes
}
func NewInMemFooDB() FooDB {
db := map[int]Foo
fdb := InMemFooDB{make(chan bool), &db}
// trigger refresh so it loads at the start
fdb.Refresh()
return fdb
}
func (t *InMemFooDB) GetFoo(id int) (Foo, error) {
if foo, ok := t.db[id]; ok {
return foo
}
return errors.New(fmt.Sprintf("'%s' was not found in db", id))
}
func (t *InMemFooDB) Refresh() {
go func() {
newDB := map[int]Foo{} // create a new 'db' value in a goroutine
// do long running thing that slowly updates newDB, meanwhile
// GetFoo continues to operate on the current data..
t.db = &newDB // Atomic switch from one complete DB to another
close(t.Ready) // indicate that we are ready for business (first run)
}
}db := NewInMemFooDB()
<- db.Ready //wait for it to load
db.GetFoo(123)