feat: persist events across commit boundaries
This commit is contained in:
@@ -22,14 +22,21 @@ var (
|
||||
)
|
||||
|
||||
type Options struct {
|
||||
DataDir string
|
||||
BusyTimeout time.Duration
|
||||
DataDir string
|
||||
BusyTimeout time.Duration
|
||||
SegmentTargetSize uint64
|
||||
FaultInjector FaultInjector
|
||||
}
|
||||
|
||||
type Store struct {
|
||||
db *sql.DB
|
||||
unlock func() error
|
||||
mu sync.Mutex
|
||||
db *sql.DB
|
||||
unlock func() error
|
||||
dataDir string
|
||||
segmentTarget uint64
|
||||
faultInjector FaultInjector
|
||||
activeSegments map[[16]byte]*activeSegment
|
||||
mu sync.Mutex
|
||||
writeMu sync.Mutex
|
||||
}
|
||||
|
||||
func Open(ctx context.Context, options Options) (*Store, error) {
|
||||
@@ -39,6 +46,12 @@ func Open(ctx context.Context, options Options) (*Store, error) {
|
||||
if options.BusyTimeout <= 0 {
|
||||
return nil, fmt.Errorf("busy timeout must be positive")
|
||||
}
|
||||
if options.SegmentTargetSize == 0 {
|
||||
options.SegmentTargetSize = 256 << 10
|
||||
}
|
||||
if options.SegmentTargetSize > DefaultSegmentLimit {
|
||||
return nil, fmt.Errorf("segment target exceeds hard record limit")
|
||||
}
|
||||
if err := ensurePrivateDirectory(options.DataDir); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -73,7 +86,10 @@ func Open(ctx context.Context, options Options) (*Store, error) {
|
||||
}
|
||||
db.SetMaxOpenConns(1)
|
||||
db.SetMaxIdleConns(1)
|
||||
store := &Store{db: db, unlock: unlock}
|
||||
store := &Store{
|
||||
db: db, unlock: unlock, dataDir: options.DataDir, segmentTarget: options.SegmentTargetSize,
|
||||
faultInjector: options.FaultInjector, activeSegments: make(map[[16]byte]*activeSegment),
|
||||
}
|
||||
if err := db.PingContext(ctx); err != nil {
|
||||
_ = store.Close()
|
||||
return nil, fmt.Errorf("open SQLite: %w", err)
|
||||
@@ -85,15 +101,27 @@ func Open(ctx context.Context, options Options) (*Store, error) {
|
||||
return store, nil
|
||||
}
|
||||
|
||||
func (store *Store) DB() *sql.DB { return store.db }
|
||||
func (store *Store) DB() *sql.DB {
|
||||
store.mu.Lock()
|
||||
defer store.mu.Unlock()
|
||||
return store.db
|
||||
}
|
||||
|
||||
func (store *Store) Close() error {
|
||||
if store == nil {
|
||||
return nil
|
||||
}
|
||||
store.writeMu.Lock()
|
||||
defer store.writeMu.Unlock()
|
||||
store.mu.Lock()
|
||||
defer store.mu.Unlock()
|
||||
var result error
|
||||
for owner, active := range store.activeSegments {
|
||||
if err := active.segment.Close(); result == nil && err != nil {
|
||||
result = err
|
||||
}
|
||||
delete(store.activeSegments, owner)
|
||||
}
|
||||
if store.db != nil {
|
||||
result = store.db.Close()
|
||||
store.db = nil
|
||||
|
||||
Reference in New Issue
Block a user