package rulecache import ( "context" "fmt" "github.com/jackc/pgx/v5" "github.com/jackc/pgx/v5/pgxpool" ) // activeRulesQuery resolves condition_source_device_id/target_device_id (FKs // into devices.id) to devices.external_id, since every other part of the // platform (MQTT, Redis, gRPC) keys devices by their external ID, not // PostgreSQL's internal bigserial ID. const activeRulesQuery = ` SELECT r.id AS rule_id, r.zone_id AS zone_id, src.external_id AS source_external_id, tgt.external_id AS target_external_id, r.condition_sensor_type AS condition_sensor_type, r.condition_operator AS condition_operator, r.condition_value AS condition_value, r.action_type AS action_type, r.action_params AS action_params FROM automation_rules r JOIN devices src ON src.id = r.condition_source_device_id JOIN devices tgt ON tgt.id = r.target_device_id WHERE r.is_active = true ` type PostgresFetcher struct { pool *pgxpool.Pool } func NewPostgresFetcher(pool *pgxpool.Pool) *PostgresFetcher { return &PostgresFetcher{pool: pool} } func (f *PostgresFetcher) FetchActiveRules(ctx context.Context) ([]Row, error) { dbRows, err := f.pool.Query(ctx, activeRulesQuery) if err != nil { return nil, fmt.Errorf("query active rules: %w", err) } rows, err := pgx.CollectRows(dbRows, pgx.RowToStructByName[Row]) if err != nil { return nil, fmt.Errorf("scan active rules: %w", err) } return rows, nil }