func (t *tracker) CLGNames(CLG systemspec.CLG, networkPayload objectspec.NetworkPayload) error { destinationName := CLG.GetName() sourceIDs := networkPayload.GetSources() errors := make(chan error, len(sourceIDs)) wg := sync.WaitGroup{} for _, s := range sourceIDs { wg.Add(1) go func(s string) { behaviourNameKey := key.NewNetworkKey("behaviour-id:%s:behaviour-name", s) name, err := t.Storage().General().Get(behaviourNameKey) if err != nil { errors <- maskAny(err) } else { // The errors channel is capable of buffering one error for each source // ID. The else clause is necessary to queue only one possible error for // each source ID. So in case the name lookup was successful, we are // able to actually persist the single CLG name connection. behaviourNameKey := key.NewNetworkKey("behaviour-name:%s:o:tracker:behaviour-names", name) err := t.Storage().General().PushToSet(behaviourNameKey, destinationName) if err != nil { errors <- maskAny(err) } } wg.Done() }(string(s)) } wg.Wait() select { case err := <-errors: if err != nil { return maskAny(err) } default: // Nothing do here. No error occurred. All good. } return nil }
func (n *network) InputHandler(CLG systemspec.CLG, textInput objectspec.TextInput) error { // In case the text request defines the echo flag, we overwrite the given CLG // directly to the output CLG. This will cause the created network payload to // be forwarded to the output CLG without indirection. Note that this should // only be used for testing purposes to bypass more complex neural network // activities to directly respond with the received input. if textInput.GetEcho() { var ok bool CLG, ok = n.CLGs["output"] if !ok { return maskAnyf(clgNotFoundError, "name: %s", "output") } } // Create new IDs for the new CLG tree and the input CLG. clgTreeID, err := n.Service().ID().New() if err != nil { return maskAny(err) } behaviourID, err := n.Service().ID().New() if err != nil { return maskAny(err) } // Create a new context and adapt it using the information of the current scope. ctx := context.MustNew() ctx.SetBehaviourID(string(behaviourID)) ctx.SetCLGName(CLG.GetName()) ctx.SetCLGTreeID(string(clgTreeID)) ctx.SetExpectation(textInput.GetExpectation()) ctx.SetSessionID(textInput.GetSessionID()) // We transform the received text request to a network payload to have a // conventional data structure within the neural network. newNetworkPayloadConfig := networkpayload.DefaultConfig() newNetworkPayloadConfig.Args = []reflect.Value{reflect.ValueOf(textInput.GetInput())} newNetworkPayloadConfig.Context = ctx newNetworkPayloadConfig.Destination = behaviourID newNetworkPayloadConfig.Sources = []string{n.GetID()} newNetworkPayload, err := networkpayload.New(newNetworkPayloadConfig) if err != nil { return maskAny(err) } // Write the new CLG tree ID to reference the input CLG ID and add the CLG // tree ID to the new context. firstBehaviourIDKey := key.NewNetworkKey("clg-tree-id:%s:first-behaviour-id", clgTreeID) err = n.Storage().General().Set(firstBehaviourIDKey, string(behaviourID)) if err != nil { return maskAny(err) } // Write the transformed network payload to the queue. eventKey := key.NewNetworkKey("event:network-payload") b, err := json.Marshal(newNetworkPayload) if err != nil { return maskAny(err) } err = n.Storage().General().PushToList(eventKey, string(b)) if err != nil { return maskAny(err) } return nil }