2025-08-22 10:03:34 +08:00

81 lines
2.1 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package selftest
import (
"context"
"database/sql"
"fmt"
"time"
"weatherstation/internal/database"
)
// Run 执行启动前自检
// 1) 数据库可用 2) 关键表存在 3) 基础查询可执行
func Run(ctx context.Context) error {
db := database.GetDB()
if err := pingDB(ctx, db); err != nil {
return fmt.Errorf("数据库连通性失败: %w", err)
}
if err := ensureTables(ctx, db); err != nil {
return fmt.Errorf("关键表缺失: %w", err)
}
if err := basicQuery(ctx, db); err != nil {
return fmt.Errorf("基础查询失败: %w", err)
}
return nil
}
func pingDB(ctx context.Context, db *sql.DB) error {
ctx, cancel := context.WithTimeout(ctx, 3*time.Second)
defer cancel()
return db.PingContext(ctx)
}
func ensureTables(ctx context.Context, db *sql.DB) error {
required := []string{
"public.stations",
"public.rs485_weather_data",
"public.rs485_weather_10min",
"public.forecast_hourly",
}
for _, t := range required {
var exists bool
if err := db.QueryRowContext(ctx, "SELECT to_regclass($1) IS NOT NULL", t).Scan(&exists); err != nil {
return err
}
if !exists {
return fmt.Errorf("缺少表: %s", t)
}
}
return nil
}
func basicQuery(ctx context.Context, db *sql.DB) error {
// 若无站点则跳过后续测试
var stationID string
_ = db.QueryRowContext(ctx, "SELECT station_id FROM stations LIMIT 1").Scan(&stationID)
// 10分钟表可被查询允许为空
var cnt int
if err := db.QueryRowContext(ctx, "SELECT COUNT(*) FROM rs485_weather_10min").Scan(&cnt); err != nil {
return err
}
// 若有站点,做一次安全时间窗聚合验证(不要求有数据,只要语句可执行)
if stationID != "" {
from := time.Now().Add(-2 * time.Hour).Truncate(time.Hour)
to := time.Now().Truncate(time.Hour)
_, err := db.QueryContext(ctx,
`WITH base AS (
SELECT * FROM rs485_weather_10min WHERE station_id=$1 AND bucket_start >= $2 AND bucket_start <= $3
), g AS (
SELECT date_trunc('hour', bucket_start) AS grp, SUM(sample_count) AS n_sum FROM base GROUP BY 1
) SELECT COUNT(*) FROM g`, stationID, from, to,
)
if err != nil {
return err
}
}
return nil
}