up
This commit is contained in:
@@ -399,6 +399,9 @@ func (s *store) UpsertNodeInfo(record map[string]any) error {
|
|||||||
if err := s.upsertNodeInfoRecord(node); err != nil {
|
if err := s.upsertNodeInfoRecord(node); err != nil {
|
||||||
return fmt.Errorf("upsert nodeinfo %s: %w", node.NodeID, err)
|
return fmt.Errorf("upsert nodeinfo %s: %w", node.NodeID, err)
|
||||||
}
|
}
|
||||||
|
if err := s.updateMapReportFromNodeInfo(node); err != nil {
|
||||||
|
return fmt.Errorf("update map_report from nodeinfo %s: %w", node.NodeID, err)
|
||||||
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -410,6 +413,9 @@ func (s *store) UpsertMapReport(record map[string]any) error {
|
|||||||
if err := s.upsertMapReportRecord(report); err != nil {
|
if err := s.upsertMapReportRecord(report); err != nil {
|
||||||
return fmt.Errorf("upsert map_report %s: %w", report.NodeID, err)
|
return fmt.Errorf("upsert map_report %s: %w", report.NodeID, err)
|
||||||
}
|
}
|
||||||
|
if err := s.updateNodeInfoFromMapReport(report); err != nil {
|
||||||
|
return fmt.Errorf("update nodeinfo from map_report %s: %w", report.NodeID, err)
|
||||||
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -432,6 +438,11 @@ func (s *store) upsertNodeInfoRecord(node *nodeInfoRecord) error {
|
|||||||
|
|
||||||
func (s *store) upsertMapReportRecord(report *mapReportRecord) error {
|
func (s *store) upsertMapReportRecord(report *mapReportRecord) error {
|
||||||
return s.db.Transaction(func(tx *gorm.DB) error {
|
return s.db.Transaction(func(tx *gorm.DB) error {
|
||||||
|
return s.upsertMapReportRecordTx(tx, report)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *store) upsertMapReportRecordTx(tx *gorm.DB, report *mapReportRecord) error {
|
||||||
var existing mapReportRecord
|
var existing mapReportRecord
|
||||||
err := tx.Where("node_id = ?", report.NodeID).Take(&existing).Error
|
err := tx.Where("node_id = ?", report.NodeID).Take(&existing).Error
|
||||||
if errors.Is(err, gorm.ErrRecordNotFound) {
|
if errors.Is(err, gorm.ErrRecordNotFound) {
|
||||||
@@ -444,7 +455,6 @@ func (s *store) upsertMapReportRecord(report *mapReportRecord) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
return s.updateMapReportRecord(tx, report)
|
return s.updateMapReportRecord(tx, report)
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *store) updateNodeInfoRecord(tx *gorm.DB, node *nodeInfoRecord) error {
|
func (s *store) updateNodeInfoRecord(tx *gorm.DB, node *nodeInfoRecord) error {
|
||||||
@@ -457,6 +467,30 @@ func (s *store) updateMapReportRecord(tx *gorm.DB, report *mapReportRecord) erro
|
|||||||
return tx.Model(&mapReportRecord{}).Where("node_id = ?", report.NodeID).Updates(updates).Error
|
return tx.Model(&mapReportRecord{}).Where("node_id = ?", report.NodeID).Updates(updates).Error
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *store) updateMapReportFromNodeInfo(node *nodeInfoRecord) error {
|
||||||
|
updates := map[string]any{
|
||||||
|
"node_num": node.NodeNum,
|
||||||
|
"updated_at": time.Now(),
|
||||||
|
}
|
||||||
|
addStringUpdate(updates, "long_name", node.LongName)
|
||||||
|
addStringUpdate(updates, "short_name", node.ShortName)
|
||||||
|
addStringUpdate(updates, "hw_model", node.HWModel)
|
||||||
|
addStringUpdate(updates, "role", node.Role)
|
||||||
|
return s.db.Model(&mapReportRecord{}).Where("node_id = ?", node.NodeID).Updates(updates).Error
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *store) updateNodeInfoFromMapReport(report *mapReportRecord) error {
|
||||||
|
updates := map[string]any{
|
||||||
|
"node_num": report.NodeNum,
|
||||||
|
"updated_at": time.Now(),
|
||||||
|
}
|
||||||
|
addStringUpdate(updates, "long_name", report.LongName)
|
||||||
|
addStringUpdate(updates, "short_name", report.ShortName)
|
||||||
|
addStringUpdate(updates, "hw_model", report.HWModel)
|
||||||
|
addStringUpdate(updates, "role", report.Role)
|
||||||
|
return s.db.Model(&nodeInfoRecord{}).Where("node_id = ?", report.NodeID).Updates(updates).Error
|
||||||
|
}
|
||||||
|
|
||||||
func nodeInfoUpdates(node *nodeInfoRecord) map[string]any {
|
func nodeInfoUpdates(node *nodeInfoRecord) map[string]any {
|
||||||
updates := map[string]any{
|
updates := map[string]any{
|
||||||
"node_num": node.NodeNum,
|
"node_num": node.NodeNum,
|
||||||
@@ -511,10 +545,42 @@ func (s *store) InsertPosition(record map[string]any, clientInfo mqttClientInfo)
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if err := s.db.Create(position).Error; err != nil {
|
return s.db.Transaction(func(tx *gorm.DB) error {
|
||||||
|
if err := tx.Create(position).Error; err != nil {
|
||||||
return fmt.Errorf("insert position from %s: %w", position.FromID, err)
|
return fmt.Errorf("insert position from %s: %w", position.FromID, err)
|
||||||
}
|
}
|
||||||
|
if err := s.upsertMapReportFromPosition(tx, position); err != nil {
|
||||||
|
return fmt.Errorf("upsert map_report from position %s: %w", position.FromID, err)
|
||||||
|
}
|
||||||
return nil
|
return nil
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *store) upsertMapReportFromPosition(tx *gorm.DB, position *positionRecord) error {
|
||||||
|
report := &mapReportRecord{
|
||||||
|
NodeID: position.FromID,
|
||||||
|
NodeNum: position.FromNum,
|
||||||
|
Latitude: position.Latitude,
|
||||||
|
Longitude: position.Longitude,
|
||||||
|
Altitude: position.Altitude,
|
||||||
|
PositionPrecision: position.PrecisionBits,
|
||||||
|
ContentJSON: position.ContentJSON,
|
||||||
|
}
|
||||||
|
|
||||||
|
var existing mapReportRecord
|
||||||
|
err := tx.Where("node_id = ?", position.FromID).Take(&existing).Error
|
||||||
|
if errors.Is(err, gorm.ErrRecordNotFound) {
|
||||||
|
return tx.Create(report).Error
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
updates := map[string]any{"node_num": position.FromNum, "updated_at": time.Now()}
|
||||||
|
addFloat64Update(updates, "latitude", position.Latitude)
|
||||||
|
addFloat64Update(updates, "longitude", position.Longitude)
|
||||||
|
addInt64Update(updates, "altitude", position.Altitude)
|
||||||
|
addInt64Update(updates, "position_precision", position.PrecisionBits)
|
||||||
|
return tx.Model(&mapReportRecord{}).Where("node_id = ?", position.FromID).Updates(updates).Error
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *store) InsertTelemetry(record map[string]any, clientInfo mqttClientInfo) error {
|
func (s *store) InsertTelemetry(record map[string]any, clientInfo mqttClientInfo) error {
|
||||||
|
|||||||
+132
-2
@@ -121,8 +121,8 @@ func TestNodeInfoAndMapReportAreStoredSeparately(t *testing.T) {
|
|||||||
if err := rawTestDB(t, st).QueryRow("SELECT long_name, user_id, public_key FROM nodeinfo WHERE node_id = ?", "!12345678").Scan(&nodeLongName, &userID, &publicKey); err != nil {
|
if err := rawTestDB(t, st).QueryRow("SELECT long_name, user_id, public_key FROM nodeinfo WHERE node_id = ?", "!12345678").Scan(&nodeLongName, &userID, &publicKey); err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
if nodeLongName != "node name" || userID != "!12345678" || publicKey != "abcd" {
|
if nodeLongName != "map name" || userID != "!12345678" || publicKey != "abcd" {
|
||||||
t.Fatalf("nodeinfo row = %q/%q/%q, want node fields", nodeLongName, userID, publicKey)
|
t.Fatalf("nodeinfo row = %q/%q/%q, want synced map name plus node-only fields", nodeLongName, userID, publicKey)
|
||||||
}
|
}
|
||||||
|
|
||||||
var mapLongName, firmware string
|
var mapLongName, firmware string
|
||||||
@@ -135,6 +135,89 @@ func TestNodeInfoAndMapReportAreStoredSeparately(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestUpsertNodeInfoUpdatesExistingMapReportFields(t *testing.T) {
|
||||||
|
st := openTestStore(t)
|
||||||
|
defer st.Close()
|
||||||
|
|
||||||
|
if err := st.UpsertMapReport(mapReportTestRecord("map name")); err != nil {
|
||||||
|
t.Fatalf("UpsertMapReport() error = %v", err)
|
||||||
|
}
|
||||||
|
node := nodeInfoTestRecord("node name")
|
||||||
|
node["short_name"] = "nod"
|
||||||
|
node["hw_model"] = "NODE_HW"
|
||||||
|
node["role"] = "CLIENT"
|
||||||
|
if err := st.UpsertNodeInfo(node); err != nil {
|
||||||
|
t.Fatalf("UpsertNodeInfo() error = %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
var longName, shortName, hwModel, role, firmware string
|
||||||
|
var latitude float64
|
||||||
|
if err := rawTestDB(t, st).QueryRow("SELECT long_name, short_name, hw_model, role, firmware_version, latitude FROM map_report WHERE node_id = ?", "!12345678").Scan(&longName, &shortName, &hwModel, &role, &firmware, &latitude); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
if longName != "node name" || shortName != "nod" || hwModel != "NODE_HW" || role != "CLIENT" || firmware != "1.2.3" || latitude != 42.5 {
|
||||||
|
t.Fatalf("map_report row = %q/%q/%q/%q firmware %q lat %v, want node fields plus existing map fields", longName, shortName, hwModel, role, firmware, latitude)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestUpsertNodeInfoDoesNotCreateMapReport(t *testing.T) {
|
||||||
|
st := openTestStore(t)
|
||||||
|
defer st.Close()
|
||||||
|
|
||||||
|
if err := st.UpsertNodeInfo(nodeInfoTestRecord("node name")); err != nil {
|
||||||
|
t.Fatalf("UpsertNodeInfo() error = %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
var count int
|
||||||
|
if err := rawTestDB(t, st).QueryRow("SELECT COUNT(*) FROM map_report WHERE node_id = ?", "!12345678").Scan(&count); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
if count != 0 {
|
||||||
|
t.Fatalf("map_report count = %d, want 0", count)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestUpsertMapReportUpdatesExistingNodeInfoFields(t *testing.T) {
|
||||||
|
st := openTestStore(t)
|
||||||
|
defer st.Close()
|
||||||
|
|
||||||
|
if err := st.UpsertNodeInfo(nodeInfoTestRecord("node name")); err != nil {
|
||||||
|
t.Fatalf("UpsertNodeInfo() error = %v", err)
|
||||||
|
}
|
||||||
|
report := mapReportTestRecord("map name")
|
||||||
|
report["short_name"] = "map"
|
||||||
|
report["hw_model"] = "MAP_HW"
|
||||||
|
report["role"] = "CLIENT_MUTE"
|
||||||
|
if err := st.UpsertMapReport(report); err != nil {
|
||||||
|
t.Fatalf("UpsertMapReport() error = %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
var longName, shortName, hwModel, role, userID, publicKey string
|
||||||
|
if err := rawTestDB(t, st).QueryRow("SELECT long_name, short_name, hw_model, role, user_id, public_key FROM nodeinfo WHERE node_id = ?", "!12345678").Scan(&longName, &shortName, &hwModel, &role, &userID, &publicKey); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
if longName != "map name" || shortName != "map" || hwModel != "MAP_HW" || role != "CLIENT_MUTE" || userID != "!12345678" || publicKey != "abcd" {
|
||||||
|
t.Fatalf("nodeinfo row = %q/%q/%q/%q user %q key %q, want map fields plus existing node-only fields", longName, shortName, hwModel, role, userID, publicKey)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestUpsertMapReportDoesNotCreateNodeInfo(t *testing.T) {
|
||||||
|
st := openTestStore(t)
|
||||||
|
defer st.Close()
|
||||||
|
|
||||||
|
if err := st.UpsertMapReport(mapReportTestRecord("map name")); err != nil {
|
||||||
|
t.Fatalf("UpsertMapReport() error = %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
var count int
|
||||||
|
if err := rawTestDB(t, st).QueryRow("SELECT COUNT(*) FROM nodeinfo WHERE node_id = ?", "!12345678").Scan(&count); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
if count != 0 {
|
||||||
|
t.Fatalf("nodeinfo count = %d, want 0", count)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func TestDeleteNodeDeletesNodeInfoAndMapReport(t *testing.T) {
|
func TestDeleteNodeDeletesNodeInfoAndMapReport(t *testing.T) {
|
||||||
st := openTestStore(t)
|
st := openTestStore(t)
|
||||||
defer st.Close()
|
defer st.Close()
|
||||||
@@ -556,6 +639,53 @@ func TestInsertPositionAppendsRows(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestInsertPositionCreatesMapReportWhenMissing(t *testing.T) {
|
||||||
|
st := openTestStore(t)
|
||||||
|
defer st.Close()
|
||||||
|
|
||||||
|
if err := st.InsertPosition(positionTestRecord(), mqttClientInfo{}); err != nil {
|
||||||
|
t.Fatalf("InsertPosition() error = %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
var nodeID string
|
||||||
|
var nodeNum int64
|
||||||
|
var latitude, longitude float64
|
||||||
|
var altitude, precision int64
|
||||||
|
if err := rawTestDB(t, st).QueryRow("SELECT node_id, node_num, latitude, longitude, altitude, position_precision FROM map_report WHERE node_id = ?", "!12345678").Scan(&nodeID, &nodeNum, &latitude, &longitude, &altitude, &precision); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
if nodeID != "!12345678" || nodeNum != 0x12345678 || latitude != 42.5 || longitude != -83.1 || altitude != 200 || precision != 16 {
|
||||||
|
t.Fatalf("map_report from position = %q/%d lat %v lon %v alt %v precision %v", nodeID, nodeNum, latitude, longitude, altitude, precision)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestInsertPositionUpdatesExistingMapReportCoordinates(t *testing.T) {
|
||||||
|
st := openTestStore(t)
|
||||||
|
defer st.Close()
|
||||||
|
|
||||||
|
if err := st.UpsertMapReport(mapReportTestRecord("map name")); err != nil {
|
||||||
|
t.Fatalf("UpsertMapReport() error = %v", err)
|
||||||
|
}
|
||||||
|
position := positionTestRecord()
|
||||||
|
position["latitude"] = 30.25
|
||||||
|
position["longitude"] = 120.75
|
||||||
|
position["altitude"] = int32(88)
|
||||||
|
position["precision_bits"] = uint32(10)
|
||||||
|
if err := st.InsertPosition(position, mqttClientInfo{}); err != nil {
|
||||||
|
t.Fatalf("InsertPosition() error = %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
var longName string
|
||||||
|
var latitude, longitude float64
|
||||||
|
var altitude, precision int64
|
||||||
|
if err := rawTestDB(t, st).QueryRow("SELECT long_name, latitude, longitude, altitude, position_precision FROM map_report WHERE node_id = ?", "!12345678").Scan(&longName, &latitude, &longitude, &altitude, &precision); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
if longName != "map name" || latitude != 30.25 || longitude != 120.75 || altitude != 88 || precision != 10 {
|
||||||
|
t.Fatalf("map_report after position = %q lat %v lon %v alt %v precision %v", longName, latitude, longitude, altitude, precision)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func TestInsertTelemetryAppendsRowsAndStoresMetricsJSON(t *testing.T) {
|
func TestInsertTelemetryAppendsRowsAndStoresMetricsJSON(t *testing.T) {
|
||||||
st := openTestStore(t)
|
st := openTestStore(t)
|
||||||
defer st.Close()
|
defer st.Close()
|
||||||
|
|||||||
Reference in New Issue
Block a user