all time calculations done within database
All checks were successful
pedestrian-simulator / build (push) Successful in 1m0s

This commit is contained in:
2026-01-11 21:07:37 -07:00
parent 6e5fe90d29
commit 89816a5a8c
2 changed files with 30 additions and 28 deletions

View File

@@ -6,7 +6,6 @@ import (
"log" "log"
"net/url" "net/url"
"os" "os"
"time"
_ "github.com/go-sql-driver/mysql" _ "github.com/go-sql-driver/mysql"
) )
@@ -25,13 +24,15 @@ func InitDB() {
return return
} }
log.Printf("[DB] Using timezone: %s (Local=%s)", os.Getenv("TZ"), time.Local.String()) // Use TZ env var if set, otherwise fallback to Local
// Default to UTC if TZ is empty, otherwise use the encoded TZ name location := "Local"
tzParam := "UTC" tz := os.Getenv("TZ")
if os.Getenv("TZ") != "" {
tzParam = url.QueryEscape("'" + os.Getenv("TZ") + "'") dsn := fmt.Sprintf("%s:%s@tcp(%s:%s)/%s?parseTime=true&loc=%s", user, pass, host, port, name, location)
if tz != "" {
dsn += fmt.Sprintf("&time_zone='%s'", url.QueryEscape(tz))
} }
dsn := fmt.Sprintf("%s:%s@tcp(%s:%s)/%s?parseTime=true&loc=Local&time_zone=%s", user, pass, host, port, name, tzParam)
var err error var err error
db, err = sql.Open("mysql", dsn) db, err = sql.Open("mysql", dsn)
if err != nil { if err != nil {
@@ -42,21 +43,7 @@ func InitDB() {
log.Fatalf("Error connecting to database: %v", err) log.Fatalf("Error connecting to database: %v", err)
} }
log.Println("Connected to MariaDB successfully") log.Printf("[DB] Connected to MariaDB successfully (using loc=%s, tz=%s)", location, tz)
// Verify and enforce timezones
var dbNow, dbTZ string
err = db.QueryRow("SELECT NOW(), @@session.time_zone").Scan(&dbNow, &dbTZ)
if err == nil {
log.Printf("[DB] Before setting: NOW()=%s, session.time_zone=%s", dbNow, dbTZ)
}
if _, err := db.Exec("SET time_zone = SYSTEM"); err != nil {
log.Printf("[DB] Warning: Failed to set session time_zone to SYSTEM: %v", err)
} else {
db.QueryRow("SELECT NOW(), @@session.time_zone").Scan(&dbNow, &dbTZ)
log.Printf("[DB] After setting: NOW()=%s, session.time_zone=%s", dbNow, dbTZ)
}
createTables() createTables()
} }
@@ -108,8 +95,8 @@ func createTables() {
start_day_initial_steps INT, start_day_initial_steps INT,
previous_total_steps INT, previous_total_steps INT,
target_total_steps INT, target_total_steps INT,
last_sync_time DATETIME, last_sync_time TIMESTAMP NULL,
next_sync_time DATETIME, next_sync_time TIMESTAMP NULL,
FOREIGN KEY (user_id) REFERENCES users(fitbit_user_id) ON DELETE CASCADE FOREIGN KEY (user_id) REFERENCES users(fitbit_user_id) ON DELETE CASCADE
)`, )`,
`CREATE TABLE IF NOT EXISTS daily_steps ( `CREATE TABLE IF NOT EXISTS daily_steps (
@@ -126,5 +113,10 @@ func createTables() {
log.Fatalf("Error creating table: %v\nQuery: %s", err, query) log.Fatalf("Error creating table: %v\nQuery: %s", err, query)
} }
} }
// Migrations: Ensure trips table uses TIMESTAMP for sync times (breaking change for DATETIME -> TIMESTAMP)
db.Exec("ALTER TABLE trips MODIFY last_sync_time TIMESTAMP NULL")
db.Exec("ALTER TABLE trips MODIFY next_sync_time TIMESTAMP NULL")
log.Println("Database tables initialized") log.Println("Database tables initialized")
} }

View File

@@ -93,10 +93,6 @@ func (sm *StepManager) SaveTripState() {
} }
func (sm *StepManager) saveTripStateLocked() { func (sm *StepManager) saveTripStateLocked() {
fmt.Printf("[StepManager] Saving trip state for %s: StartTime=%v (%s), LastSync=%v (%s)\n",
sm.userID, sm.tripState.StartTime, sm.tripState.StartTime.Location(),
sm.lastSyncTime, sm.lastSyncTime.Location())
_, err := db.Exec(` _, err := db.Exec(`
INSERT INTO trips (user_id, start_date, start_time, start_day_initial_steps, previous_total_steps, target_total_steps, last_sync_time, next_sync_time) INSERT INTO trips (user_id, start_date, start_time, start_day_initial_steps, previous_total_steps, target_total_steps, last_sync_time, next_sync_time)
VALUES (?, ?, ?, ?, ?, ?, ?, ?) VALUES (?, ?, ?, ?, ?, ?, ?, ?)
@@ -248,6 +244,20 @@ func (sm *StepManager) performSync(interval time.Duration) {
sm.lastSyncTime = time.Now() sm.lastSyncTime = time.Now()
sm.nextSyncTime = time.Now().Add(interval) sm.nextSyncTime = time.Now().Add(interval)
// Save final state with explicit NOW() for last_sync_time to ensure DB consistency
// next_sync_time is also calculated in SQL relative to the same NOW()
_, err = db.Exec(`
UPDATE trips SET
last_sync_time = NOW(),
next_sync_time = DATE_ADD(NOW(), INTERVAL ? SECOND),
previous_total_steps = ?,
target_total_steps = ?
WHERE user_id = ?
`, interval.Seconds(), sm.previousTotalSteps, sm.targetTotalSteps, sm.userID)
if err != nil {
fmt.Printf("Error saving sync completion: %v\n", err)
}
fmt.Printf("Sync Complete. Total Trip Steps: %d\n", sm.targetTotalSteps) fmt.Printf("Sync Complete. Total Trip Steps: %d\n", sm.targetTotalSteps)
} }