feat(go): flatten mysql realtime snapshots
This commit is contained in:
@@ -98,7 +98,7 @@ func TestSnapshotWriterEnsuresSchemaAndUpsertsCoreSnapshot(t *testing.T) {
|
||||
if got, want := upsert.args[4], "1.2.3.4:32960"; got != want {
|
||||
t.Fatalf("peer arg = %#v, want %q", got, want)
|
||||
}
|
||||
if got := upsert.args[5]; !strings.Contains(got.(string), `"data_units"`) {
|
||||
if got := upsert.args[5]; !strings.Contains(got.(string), `"gb32960.vehicle.soc_percent":"90"`) {
|
||||
t.Fatalf("parsed json arg = %#v", got)
|
||||
}
|
||||
if len(upsert.args) != 9 {
|
||||
@@ -225,7 +225,12 @@ func TestSnapshotWriterMergesGB32960ParsedJSONAcrossSplitRealtimeFrames(t *testi
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
jsonDataUnitsArg{types: []string{"0x01", "0x30"}},
|
||||
jsonFlatFieldsArg{fields: map[string]string{
|
||||
"gb32960.vehicle.soc_percent": "88",
|
||||
"gb32960.vehicle.type": "0x01",
|
||||
"gb32960.gd_fc_stack.stack_count": "1",
|
||||
"gb32960.gd_fc_stack.type": "0x30",
|
||||
}},
|
||||
sqlmock.AnyArg(),
|
||||
sqlmock.AnyArg(),
|
||||
sqlmock.AnyArg(),
|
||||
@@ -271,7 +276,17 @@ func TestSnapshotWriterCollapsesGB32960StackFragmentsWhenMergingParsedJSON(t *te
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
jsonGDFCStackSummaryArg{},
|
||||
jsonFlatFieldsArg{
|
||||
fields: map[string]string{
|
||||
"gb32960.gd_fc_stack.stack_water_outlet_temp_c": "63",
|
||||
},
|
||||
forbidden: []string{
|
||||
"gb32960.gd_fc_stack.frame_cell_start",
|
||||
"gb32960.gd_fc_stack.frame_cell_count",
|
||||
"gb32960.gd_fc_stack.frame_max_cell_voltage_v",
|
||||
"gb32960.gd_fc_stack.frame_min_cell_voltage_v",
|
||||
},
|
||||
},
|
||||
sqlmock.AnyArg(),
|
||||
sqlmock.AnyArg(),
|
||||
sqlmock.AnyArg(),
|
||||
@@ -697,13 +712,12 @@ func (r *recordingPlateResolver) PlateByVIN(_ context.Context, vin string) (stri
|
||||
return r.plate, r.err
|
||||
}
|
||||
|
||||
type jsonDataUnitsArg struct {
|
||||
types []string
|
||||
type jsonFlatFieldsArg struct {
|
||||
fields map[string]string
|
||||
forbidden []string
|
||||
}
|
||||
|
||||
type jsonGDFCStackSummaryArg struct{}
|
||||
|
||||
func (jsonGDFCStackSummaryArg) Match(value driver.Value) bool {
|
||||
func (a jsonFlatFieldsArg) Match(value driver.Value) bool {
|
||||
text, ok := value.(string)
|
||||
if !ok {
|
||||
return false
|
||||
@@ -712,62 +726,13 @@ func (jsonGDFCStackSummaryArg) Match(value driver.Value) bool {
|
||||
if err := json.Unmarshal([]byte(text), &parsed); err != nil {
|
||||
return false
|
||||
}
|
||||
units, ok := parsed["data_units"].([]any)
|
||||
if !ok {
|
||||
return false
|
||||
}
|
||||
for _, unit := range units {
|
||||
unitMap, ok := unit.(map[string]any)
|
||||
if !ok || unitMap["name"] != "gd_fc_stack" {
|
||||
continue
|
||||
}
|
||||
valueMap, ok := unitMap["value"].(map[string]any)
|
||||
if !ok {
|
||||
for field, want := range a.fields {
|
||||
if got, ok := parsed[field].(string); !ok || got != want {
|
||||
return false
|
||||
}
|
||||
summaries, ok := valueMap["summaries"].([]any)
|
||||
if !ok || len(summaries) != 1 {
|
||||
return false
|
||||
}
|
||||
summary, ok := summaries[0].(map[string]any)
|
||||
if !ok {
|
||||
return false
|
||||
}
|
||||
for _, fragmentOnly := range []string{"frame_cell_start", "frame_cell_count", "frame_max_cell_voltage_v", "frame_min_cell_voltage_v"} {
|
||||
if _, ok := summary[fragmentOnly]; ok {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return summary["stack_water_outlet_temp_c"] == float64(63)
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (a jsonDataUnitsArg) Match(value driver.Value) bool {
|
||||
text, ok := value.(string)
|
||||
if !ok {
|
||||
return false
|
||||
}
|
||||
var parsed map[string]any
|
||||
if err := json.Unmarshal([]byte(text), &parsed); err != nil {
|
||||
return false
|
||||
}
|
||||
units, ok := parsed["data_units"].([]any)
|
||||
if !ok {
|
||||
return false
|
||||
}
|
||||
seen := map[string]bool{}
|
||||
for _, unit := range units {
|
||||
unitMap, ok := unit.(map[string]any)
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
if unitType, ok := unitMap["type"].(string); ok {
|
||||
seen[unitType] = true
|
||||
}
|
||||
}
|
||||
for _, unitType := range a.types {
|
||||
if !seen[unitType] {
|
||||
for _, field := range a.forbidden {
|
||||
if _, ok := parsed[field]; ok {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user