func BrokerStart(verbose bool) { broker, _ := NewBroker(verbose) broker.Bind("tcp://*:55555") poller := zmq.NewPoller() poller.Add(broker.socket, zmq.POLLIN) // Get and process messages forever or until interrupted for { polled, err := poller.Poll(HEARTBEAT_INTERVAL) if err != nil { break // Interrupted } // Process next input message, if any if len(polled) > 0 { msg, err := broker.socket.RecvMessage(0) if err != nil { break // Interrupted } if broker.verbose { log.Printf("I: received message: %q\n", msg) } sender, msg := pgtlib.PopStr(msg) header, msg := pgtlib.PopStr(msg) switch header { case pgtlib.C_CLIENT: broker.ClientMsg(sender, msg) case pgtlib.W_WORKER: broker.WorkerMsg(sender, msg) default: log.Printf("E: invalid message (sender=%s, header=%s): %q\n", sender, header, msg) } } // Disconnect and delete any expired workers // Send heartbeats to idle workers if needed if time.Now().After(broker.heartbeat_at) { broker.Purge() for _, worker := range broker.waiting { worker.Send(pgtlib.W_HEARTBEAT, []string{}) } broker.heartbeat_at = time.Now().Add(HEARTBEAT_INTERVAL) } } }
func (broker *Broker) ClientMsg(sender string, msg []string) { // Service name + body if len(msg) < 2 { // heartbeat return } _, msg = pgtlib.PopStr(msg) service_frame, msg := pgtlib.PopStr(msg) service := broker.ServiceRequire(service_frame) // Set reply return identity to client sender m := []string{sender, ""} msg = append(m, msg...) // If we got a MMI service request, process that internally if len(service_frame) >= 4 && service_frame[:4] == "mmi." { var return_code string if service_frame == "mmi.service" { name := msg[len(msg)-1] service, ok := broker.services[name] if ok && len(service.waiting) > 0 { return_code = "200" } else { return_code = "404" } } else { return_code = "501" } msg[len(msg)-1] = return_code // Remove & save client return envelope and insert the // protocol header and service name, then rewrap envelope. broker.socket.SendMessage("", "", pgtlib.C_CLIENT, service_frame, msg) } else { // Else dispatch the message to the requested service service.Dispatch(msg) } }
func (broker *Broker) WorkerMsg(sender string, msg []string) { // At least, command if len(msg) == 0 { panic("len(msg) == 0") } command, msg := pgtlib.PopStr(msg) id_string := fmt.Sprintf("%q", sender) _, worker_ready := broker.workers[id_string] worker := broker.WorkerRequire(sender) switch command { case pgtlib.W_READY: if worker_ready { // Not first command in session worker.Delete(true) } else if len(sender) >= 4 /* Reserved service name */ && sender[:4] == "mmi." { worker.Delete(true) } else { // Attach worker to service and mark as idle worker.service = broker.ServiceRequire(msg[0]) worker.Waiting() } case pgtlib.W_REPLY: if worker_ready { // Remove & save client return envelope and insert the // protocol header and service name, then rewrap envelope. broker.socket.SendMessage(msg[0], pgtlib.C_CLIENT, command, "", msg[2], msg[3], msg[4]) worker.Waiting() } else { worker.Delete(true) } case pgtlib.W_HEARTBEAT: if worker_ready { worker.expiry = time.Now().Add(HEARTBEAT_EXPIRY) } else { worker.Delete(true) } case pgtlib.W_DISCONNECT: worker.Delete(false) default: log.Printf("E: invalid input message %q\n", msg) } }