feat: persist events across commit boundaries

This commit is contained in:
2026-08-31 09:35:20 +00:00
parent 43dcd56313
commit 583b539f86
7 changed files with 722 additions and 14 deletions
+35 -7
View File
@@ -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