@@ -2,6 +2,7 @@ package main
22
33import (
44 "database/sql"
5+ "fmt"
56 "time"
67
78 _ "github.com/mattn/go-sqlite3"
@@ -44,11 +45,23 @@ type ResolverStats struct {
4445}
4546
4647func NewDB (path string ) (* DB , error ) {
47- db , err := sql .Open ("sqlite3" , path + "?_journal_mode=WAL&_busy_timeout=5000" )
48+ db , err := sql .Open ("sqlite3" , path + "?_journal_mode=WAL&_busy_timeout=5000&_synchronous=NORMAL " )
4849 if err != nil {
4950 return nil , err
5051 }
5152
53+ // Use a single connection to avoid WAL snapshot isolation issues.
54+ // With multiple connections, readers can see stale data because each
55+ // connection may hold an old snapshot of the WAL. A single connection
56+ // ensures all reads see the latest committed writes.
57+ db .SetMaxOpenConns (1 )
58+
59+ // Verify connection works
60+ if err := db .Ping (); err != nil {
61+ db .Close ()
62+ return nil , fmt .Errorf ("failed to ping database: %w" , err )
63+ }
64+
5265 if err := createTables (db ); err != nil {
5366 db .Close ()
5467 return nil , err
@@ -111,11 +124,19 @@ func (d *DB) UpsertResolver(name, typ, description, sourceFile string) (int64, e
111124}
112125
113126func (d * DB ) RecordTest (resolverID int64 , stamp string , success bool , rttMs int64 , errMsg string ) error {
114- _ , err := d .db .Exec (`
127+ result , err := d .db .Exec (`
115128 INSERT INTO test_results (resolver_id, stamp, success, rtt_ms, error)
116129 VALUES (?, ?, ?, ?, ?)
117130 ` , resolverID , stamp , success , rttMs , errMsg )
118- return err
131+ if err != nil {
132+ return err
133+ }
134+ // Verify the insert actually happened
135+ rows , _ := result .RowsAffected ()
136+ if rows == 0 {
137+ return fmt .Errorf ("no rows inserted for resolver %d" , resolverID )
138+ }
139+ return nil
119140}
120141
121142func (d * DB ) GetAllStats () ([]ResolverStats , error ) {
@@ -251,3 +272,18 @@ func (d *DB) RemoveStaleResolvers(noSuccessSince time.Duration) ([]string, error
251272
252273 return names , nil
253274}
275+
276+ // GetTestCount returns the total number of test results and the timestamp of the most recent one
277+ func (d * DB ) GetTestCount () (count int64 , lastTest time.Time , err error ) {
278+ var lastTestStr sql.NullString
279+ err = d .db .QueryRow (`
280+ SELECT COUNT(*), MAX(tested_at) FROM test_results
281+ ` ).Scan (& count , & lastTestStr )
282+ if err != nil {
283+ return 0 , time.Time {}, err
284+ }
285+ if lastTestStr .Valid {
286+ lastTest , _ = time .Parse ("2006-01-02 15:04:05" , lastTestStr .String )
287+ }
288+ return count , lastTest , nil
289+ }
0 commit comments