This repository has been archived on 2022-07-30. You can view files and clone it, but cannot push or open issues/pull-requests.
mdb/kvstore/store.go

129 lines
2.1 KiB
Go
Raw Normal View History

2022-07-26 07:35:30 +00:00
package kvstore
import (
"database/sql"
"sync"
"time"
_ "github.com/mattn/go-sqlite3"
)
type KV struct {
2022-07-29 19:36:42 +00:00
primary bool
dbPath string
2022-07-26 07:35:30 +00:00
2022-07-26 12:01:52 +00:00
db *sql.DB
2022-07-26 07:35:30 +00:00
2022-07-29 19:36:42 +00:00
maxSeqNumStmt *sql.Stmt
logIterateStmt *sql.Stmt
w *writer
2022-07-26 07:35:30 +00:00
onStore func(string, uint64, []byte)
onDelete func(string, uint64)
2022-07-29 19:36:42 +00:00
closeLock sync.Mutex
recvLock sync.Mutex
2022-07-26 07:35:30 +00:00
}
2022-07-29 19:36:42 +00:00
func newKV(
dir string,
primary bool,
onStore func(string, uint64, []byte),
onDelete func(string, uint64),
) *KV {
kv := &KV{
dbPath: dbPath(dir),
primary: primary,
onStore: onStore,
onDelete: onDelete,
}
2022-07-26 07:35:30 +00:00
opts := `?_journal=WAL`
2022-07-29 19:36:42 +00:00
db, err := sql.Open("sqlite3", kv.dbPath+opts)
2022-07-26 07:35:30 +00:00
must(err)
_, err = db.Exec(sqlSchema)
must(err)
2022-07-29 19:36:42 +00:00
kv.maxSeqNumStmt, err = db.Prepare(sqlMaxSeqNumGet)
must(err)
kv.logIterateStmt, err = db.Prepare(sqlLogIterate)
must(err)
_, err = db.Exec(sqlSchema)
must(err)
2022-07-26 07:35:30 +00:00
kv.db = db
2022-07-29 19:36:42 +00:00
if kv.primary {
kv.w = newWriter(kv.db)
kv.w.Start(kv.MaxSeqNum())
}
return kv
2022-07-26 07:35:30 +00:00
}
func NewPrimary(dir string) *KV {
2022-07-29 19:36:42 +00:00
return newKV(dir, true, nil, nil)
2022-07-26 07:35:30 +00:00
}
func NewSecondary(
dir string,
onStore func(collection string, id uint64, data []byte),
onDelete func(collection string, id uint64),
) *KV {
2022-07-29 19:36:42 +00:00
return newKV(dir, false, onStore, onDelete)
2022-07-26 07:35:30 +00:00
}
func (kv *KV) Primary() bool {
return kv.primary
}
func (kv *KV) MaxSeqNum() (seqNum uint64) {
2022-07-29 19:36:42 +00:00
must(kv.maxSeqNumStmt.QueryRow().Scan(&seqNum))
2022-07-26 07:35:30 +00:00
return seqNum
}
func (kv *KV) Iterate(collection string, each func(id uint64, data []byte)) {
rows, err := kv.db.Query(sqlKVIterate, collection)
must(err)
defer rows.Close()
var (
id uint64
data []byte
)
for rows.Next() {
must(rows.Scan(&id, &data))
each(id, data)
}
}
func (kv *KV) Close() {
kv.closeLock.Lock()
defer kv.closeLock.Unlock()
2022-07-29 19:36:42 +00:00
if kv.w != nil {
kv.w.Stop()
2022-07-26 07:35:30 +00:00
}
2022-07-29 19:36:42 +00:00
if kv.db != nil {
kv.db.Close()
kv.db = nil
}
2022-07-26 07:35:30 +00:00
}
func (kv *KV) Store(collection string, id uint64, data []byte) {
kv.w.Store(collection, id, data)
}
func (kv *KV) Delete(collection string, id uint64) {
kv.w.Delete(collection, id)
}
2022-07-29 19:36:42 +00:00
func (kv *KV) CleanBefore(seconds int64) {
_, err := kv.db.Exec(sqlCleanQuery, time.Now().Unix()-seconds)
2022-07-26 07:35:30 +00:00
must(err)
}