From a33ef47a39d0fbaee08150e842f3841b63bf8686 Mon Sep 17 00:00:00 2001 From: Hugo Nijhuis Date: Sat, 10 Jan 2026 16:41:40 +0100 Subject: [PATCH] Fix type assertion bug in handleClusterMessage JSON unmarshal produces map[string]interface{}, not concrete types. Added ModelPayload and MessagePayload concrete types that implement RuntimeModel and RuntimeMessage interfaces respectively. The handleClusterMessage now re-marshals and unmarshals the payload to convert from map[string]interface{} to the proper concrete type. Co-Authored-By: Claude Opus 4.5 --- cluster/distributed.go | 25 ++++++++++++++++++------- cluster/types.go | 26 ++++++++++++++++++++++++++ 2 files changed, 44 insertions(+), 7 deletions(-) diff --git a/cluster/distributed.go b/cluster/distributed.go index 63b605e..6e9eb4f 100644 --- a/cluster/distributed.go +++ b/cluster/distributed.go @@ -177,18 +177,29 @@ func (dvm *DistributedVM) handleClusterMessage(msg *nats.Msg) { switch clusterMsg.Type { case "load_model": // Handle model loading from other nodes - // Note: Payload comes as interface{} from JSON, need type assertion - // In practice, this would deserialize to the proper model type - if model, ok := clusterMsg.Payload.(RuntimeModel); ok { - dvm.localRuntime.LoadModel(model) + // Re-marshal and unmarshal to convert map[string]interface{} to concrete type + payloadBytes, err := json.Marshal(clusterMsg.Payload) + if err != nil { + return } + var model ModelPayload + if err := json.Unmarshal(payloadBytes, &model); err != nil { + return + } + dvm.localRuntime.LoadModel(&model) case "route_message": // Handle message routing from other nodes - // Note: Similar type handling needed here - if message, ok := clusterMsg.Payload.(RuntimeMessage); ok { - dvm.localRuntime.SendMessage(message) + // Re-marshal and unmarshal to convert map[string]interface{} to concrete type + payloadBytes, err := json.Marshal(clusterMsg.Payload) + if err != nil { + return } + var message MessagePayload + if err := json.Unmarshal(payloadBytes, &message); err != nil { + return + } + dvm.localRuntime.SendMessage(&message) case "rebalance": // Handle shard rebalancing requests diff --git a/cluster/types.go b/cluster/types.go index d2fc13c..881a191 100644 --- a/cluster/types.go +++ b/cluster/types.go @@ -147,3 +147,29 @@ type RuntimeMessage interface { // GetType returns the message type identifier GetType() string } + +// ModelPayload is a concrete type for JSON-unmarshaling RuntimeModel payloads. +// Use this when receiving model data over the network. +type ModelPayload struct { + ID string `json:"id"` + Name string `json:"name"` +} + +// GetID implements RuntimeModel +func (m *ModelPayload) GetID() string { return m.ID } + +// GetName implements RuntimeModel +func (m *ModelPayload) GetName() string { return m.Name } + +// MessagePayload is a concrete type for JSON-unmarshaling RuntimeMessage payloads. +// Use this when receiving message data over the network. +type MessagePayload struct { + TargetActorID string `json:"targetActorId"` + Type string `json:"type"` +} + +// GetTargetActorID implements RuntimeMessage +func (m *MessagePayload) GetTargetActorID() string { return m.TargetActorID } + +// GetType implements RuntimeMessage +func (m *MessagePayload) GetType() string { return m.Type }