// SendResponse sends a message back to return identites of the received message. func (receipt *MsgReceipt) SendResponse(socket *zmq.Socket, msg ComposedMsg) { socket.SendMultipart(receipt.Identities, zmq.SNDMORE) socket.Send([]byte("<IDS|MSG>"), zmq.SNDMORE) socket.SendMultipart(msg.ToWireMsg(receipt.Sockets.Key), 0) logger.Println("<--", msg.Header.Msg_type) logger.Printf("%+v\n", msg.Content) }
// Publishes stored events to event listeners. // // Pops previously stored messages off a channel and published them to a // ZeroMQ socket. func publishAllSavedEvents(toPublish chan eventstore.StoredEvent, evpub zmq.Socket) { msg := make(zMsg, 3) for stored := range toPublish { msg[0] = stored.Event.Stream msg[1] = stored.Id msg[2] = stored.Event.Data if err := evpub.SendMultipart(msg, 0); err != nil { log.Println(err) } } }
// SendResponse sends a message back to return identites of the received message. func (receipt *MsgReceipt) SendResponse(socket *zmq.Socket, msg ComposedMsg) { socket.SendMultipart(receipt.Identities, zmq.SNDMORE) socket.Send([]byte("<IDS|MSG>"), zmq.SNDMORE) msgParts, err := msg.ToWireMsg(receipt.Sockets.Key) if err != nil { log.Fatalln(err) } socket.SendMultipart(msgParts, 0) logger.Println("<--", msg.Header.MsgType) logger.Printf("%+v\n", msg.Content) }
// A blocking function that will infinitely forward multi-part messages between two zmq.Sockets func Forward(a, b zmq.Socket) { for { parts, err := a.RecvMultipart(0) if err != nil { log.Println("Error receiving message on frontend broker", err) } err = b.SendMultipart(parts, 0) if err != nil { log.Println("Error sending message on backend broker", err) } // log.Println("Brokered message:", Stringify(parts)) } }
// The core ZeroMQ messaging loop. Handles requests and responses // asynchronously using the router socket. Every request is delegated to // a goroutine for maximum concurrency. // // `gozmq` does currently not support copy-free messages/frames. This // means that every message passing through this function needs to be // copied in-memory. If this becomes a bottleneck in the future, // multiple router sockets can be hooked to this final router to scale // message copying. // // TODO: Make this a type function of `Server` to remove a lot of // parameters. func loopServer(estore *eventstore.EventStore, evpubsock, frontend zmq.Socket, stop chan bool) { toPoll := zmq.PollItems{ zmq.PollItem{Socket: &frontend, zmq.Events: zmq.POLLIN}, } pubchan := make(chan eventstore.StoredEvent) estore.RegisterPublishedEventsChannel(pubchan) go publishAllSavedEvents(pubchan, evpubsock) defer close(pubchan) pollchan := make(chan zmqPollResult) respchan := make(chan zMsg) pollCancel := make(chan bool) defer stopPoller(pollCancel) go asyncPoll(pollchan, toPoll, pollCancel) for { select { case res := <-pollchan: if res.err != nil { log.Println("Could not poll:", res.err) } if res.err == nil && toPoll[0].REvents&zmq.POLLIN != 0 { msg, _ := toPoll[0].Socket.RecvMultipart(0) zmsg := zMsg(msg) go handleRequest(respchan, estore, zmsg) } go asyncPoll(pollchan, toPoll, pollCancel) case frames := <-respchan: if err := frontend.SendMultipart(frames, 0); err != nil { log.Println(err) } case <-stop: log.Println("Server asked to stop. Stopping...") return } } }