Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 14 additions & 6 deletions gr26/service/signal.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,12 @@ import (

// produced_at is MATERIALIZED from timestamp; created_at defaults to insert
// wall clock and acts as the ReplacingMergeTree version. Both omitted here.
const insertSignalSQL = `INSERT INTO signal (id, timestamp, vehicle_id, name, value, raw_value) VALUES (?, ?, ?, ?, ?, ?)`
const insertSignalSQL = `INSERT INTO signal (id, timestamp, vehicle_id, name, value, raw_value)`

func CreateSignals(signals []mapache.Signal) error {
if len(signals) == 0 {
return nil
}
// Stamp CreatedAt locally before any MQTT publish or CH insert so
// downstream consumers (live cache eviction, SSE Last-Event-ID) have
// a reliable wall-clock anchor independent of producer/CAN-frame clock
Expand All @@ -39,13 +42,18 @@ func CreateSignals(signals []mapache.Signal) error {
if !config.ClickhouseEnabled() {
return nil
}
ctx := database.InsertCtx(context.Background())
// One buffered block insert per call — a single round trip regardless of
// signal count, which matters with CH ~25ms away from foundry. async_insert
// (InsertCtx) doesn't apply to native block inserts, so plain ctx here.
batch, err := database.Conn.PrepareBatch(context.Background(), insertSignalSQL)
if err != nil {
return err
}
defer batch.Close()
for _, s := range signals {
if err := database.Conn.Exec(ctx, insertSignalSQL,
s.ID, int64(s.Timestamp), s.VehicleID, s.Name, s.Value, int64(s.RawValue),
); err != nil {
if err := batch.Append(s.ID, int64(s.Timestamp), s.VehicleID, s.Name, s.Value, int64(s.RawValue)); err != nil {
return err
}
}
return nil
return batch.Send()
}
Loading