|
|
@@ -246,6 +246,7 @@ func UpdateBroadcastState(values map[string]interface{}) error {
|
|
|
if err := recursiveUpdate(field, val); err != nil {
|
|
|
mu.Unlock()
|
|
|
return fmt.Errorf("error updating field %s: %v", key, err)
|
|
|
+ return err
|
|
|
}
|
|
|
}
|
|
|
mu.Unlock()
|
|
|
@@ -255,54 +256,41 @@ func UpdateBroadcastState(values map[string]interface{}) error {
|
|
|
|
|
|
// this allows us to insert stuff into nested structs/keys and not overwrite the existing contents
|
|
|
func recursiveUpdate(dst, src reflect.Value) error {
|
|
|
- // Check if neither dst nor src are maps or structs (e.g., both are primitive types)
|
|
|
- if dst.Kind() != reflect.Map && dst.Kind() != reflect.Struct &&
|
|
|
- src.Kind() != reflect.Map && src.Kind() != reflect.Struct {
|
|
|
- if dst.Type() != src.Type() {
|
|
|
- return fmt.Errorf("type mismatch: expected %s, got %s", dst.Type(), src.Type())
|
|
|
- }
|
|
|
- dst.Set(src)
|
|
|
- return nil
|
|
|
- }
|
|
|
+ if !dst.CanSet() {
|
|
|
+ return fmt.Errorf("field (type: %s, kind: %s) is not settable", dst.Type(), dst.Kind())
|
|
|
+ }
|
|
|
// If dst is a struct and src is a map, handle them field by field
|
|
|
- if dst.Kind() == reflect.Map && src.Kind() == reflect.Map {
|
|
|
- if dst.IsNil() {
|
|
|
- dst.Set(reflect.MakeMap(dst.Type()))
|
|
|
- }
|
|
|
+ if dst.Kind() == reflect.Struct && src.Kind() == reflect.Map {
|
|
|
for _, key := range src.MapKeys() {
|
|
|
- dstVal := dst.MapIndex(key)
|
|
|
- // If the value in the map is a struct, create a new instance for modification
|
|
|
- if dstVal.Kind() == reflect.Struct {
|
|
|
- tmpVal := reflect.New(dstVal.Type()).Elem()
|
|
|
- tmpVal.Set(dstVal)
|
|
|
- dstVal = tmpVal
|
|
|
+ dstField := dst.FieldByName(key.String())
|
|
|
+ if !dstField.IsValid() {
|
|
|
+ return fmt.Errorf("field %s does not exist in the struct", key.String())
|
|
|
+ }
|
|
|
+ // Initialize the map if it's nil and we're trying to set a map
|
|
|
+ if dstField.Kind() == reflect.Map && dstField.IsNil() && src.MapIndex(key).Kind() == reflect.Map {
|
|
|
+ dstField.Set(reflect.MakeMap(dstField.Type()))
|
|
|
+ }
|
|
|
+ if !dstField.CanSet() {
|
|
|
+ return fmt.Errorf("field %s is not settable in the struct", key.String())
|
|
|
}
|
|
|
srcVal := src.MapIndex(key)
|
|
|
if srcVal.Kind() == reflect.Interface {
|
|
|
srcVal = srcVal.Elem()
|
|
|
}
|
|
|
- if err := recursiveUpdate(dstVal, srcVal); err != nil {
|
|
|
+ if err := recursiveUpdate(dstField, srcVal); err != nil {
|
|
|
return err
|
|
|
}
|
|
|
- // If the value in the map was a struct, update the map with the modified struct
|
|
|
- if dstVal.Kind() == reflect.Struct {
|
|
|
- dst.SetMapIndex(key, dstVal)
|
|
|
- }
|
|
|
}
|
|
|
return nil
|
|
|
}
|
|
|
// If both dst and src are maps, handle them recursively
|
|
|
if dst.Kind() == reflect.Map && src.Kind() == reflect.Map {
|
|
|
- if dst.IsNil() {
|
|
|
- dst.Set(reflect.MakeMap(dst.Type()))
|
|
|
- }
|
|
|
for _, key := range src.MapKeys() {
|
|
|
srcVal := src.MapIndex(key)
|
|
|
// If the key doesn't exist in dst, initialize it
|
|
|
dstVal := dst.MapIndex(key)
|
|
|
if !dstVal.IsValid() {
|
|
|
dstVal = reflect.New(dst.Type().Elem()).Elem()
|
|
|
- dst.SetMapIndex(key, dstVal) // Set the new value directly into the map
|
|
|
}
|
|
|
// Recursive call to handle potential nested maps or structs
|
|
|
if err := recursiveUpdate(dstVal, srcVal); err != nil {
|
|
|
@@ -390,18 +378,17 @@ func shipStatusLoop() {
|
|
|
piers := conf.Piers
|
|
|
updates, err := constructPierInfo(piers)
|
|
|
if err != nil {
|
|
|
- errmsg := fmt.Sprintf("Unable to build pier info: %v",err)
|
|
|
+ errmsg := fmt.Sprintf("Unable to build pier info: %v", err)
|
|
|
config.Logger.Warn(errmsg)
|
|
|
+ continue
|
|
|
}
|
|
|
- // update broadcastState
|
|
|
- err = UpdateBroadcastState(map[string]interface{}{
|
|
|
- "Urbits": updates,
|
|
|
- })
|
|
|
- if err != nil {
|
|
|
- errmsg := fmt.Sprintf("Unable to update ship state: %v", err)
|
|
|
- config.Logger.Error(errmsg)
|
|
|
+ mu.Lock() // Locking the mutex
|
|
|
+ for key, urbit := range updates {
|
|
|
+ broadcastState.Urbits[key] = urbit
|
|
|
}
|
|
|
+ mu.Unlock() // Unlocking the mutex
|
|
|
+ BroadcastToClients()
|
|
|
config.Logger.Info("ship bstate updated")
|
|
|
}
|
|
|
}
|
|
|
-}
|
|
|
+}
|