blob: 75d6571f684a9dd16578f217546f4eceeaee6b8f [file] [log] [blame]
package expstorage
import (
"database/sql"
"encoding/json"
"skia.googlesource.com/buildbot.git/go/database"
"skia.googlesource.com/buildbot.git/go/util"
)
// Stores expectations in an SQL database without any caching.
type SQLExpectationsStore struct {
vdb *database.VersionedDB
}
func NewSQLExpectationStore(vdb *database.VersionedDB) ExpectationsStore {
return &SQLExpectationsStore{
vdb: vdb,
}
}
// See ExpectationsStore interface.
func (e *SQLExpectationsStore) Get(modifiable bool) (exp *Expectations, err error) {
// Load the newest record from the database.
stmt := `SELECT expectations
FROM expectations
ORDER BY ts DESC
LIMIT 1`
// Read the expectations. If there are no rows, that means we have no
// expectations yet.
var expJSON string
switch err := e.vdb.DB.QueryRow(stmt).Scan(&expJSON); {
case err == sql.ErrNoRows:
return NewExpectations(modifiable), nil
case err != nil:
return nil, err
}
var result Expectations
err = json.Unmarshal([]byte(expJSON), &result)
// Since it's freshly allocated we can just set it to the requested mode.
result.Modifiable = modifiable
return &result, nil
}
// See ExpectationsStore interface.
func (e *SQLExpectationsStore) Put(exp *Expectations, userId string) error {
// Sererialize the expectations to JSON and store them in the DB.
expectationsJSON, err := json.Marshal(exp)
if err != nil {
return err
}
ts := util.TimeStampMs()
stmt := `INSERT INTO expectations (userid, ts, expectations)
VALUES(?, ?, ?)`
_, err = e.vdb.DB.Exec(stmt, userId, ts, expectationsJSON)
return err
}
// Wraps around an ExpectationsStore and caches the expectations using
// MemExpecationsStore.
type CachingExpectationStore struct {
store ExpectationsStore
cache ExpectationsStore
refresh bool
}
func NewCachingExpectationStore(store ExpectationsStore) ExpectationsStore {
return &CachingExpectationStore{
store: store,
cache: NewMemExpectationsStore(),
refresh: true,
}
}
// See ExpectationsStore interface.
func (c *CachingExpectationStore) Get(modifiable bool) (exp *Expectations, err error) {
if c.refresh {
c.refresh = false
tempExp, err := c.store.Get(true)
if err != nil {
return nil, err
}
if err = c.cache.Put(tempExp, ""); err != nil {
return nil, err
}
}
return c.cache.Get(modifiable)
}
// See ExpectationsStore interface.
func (c *CachingExpectationStore) Put(exp *Expectations, userId string) error {
exp.checkModifiable()
if err := c.store.Put(exp, userId); err != nil {
return err
}
return c.cache.Put(exp, userId)
}