// Start configures the NSQWriter and checks if the tasks topic exists. // The topic is created if it does not exist. func (self *Taskd) Start(wg *sync.WaitGroup) (err error) { self.writer = nsq.NewWriter(self.options.MsgSinkTcpAddr) topicExists, err := msg.TopicExists(self.options.MsgTopic, []string{self.options.MsgSourceHttpAddr}) if err != nil { log.Fatalf("Could not query topic existance: %s", err) } if !topicExists { err = msg.CreateTopicChannel(self.options.MsgTopic, self.options.MsgChannel, self.options.MsgSourceHttpAddr) if err != nil { log.Fatalf("Creating topic failed: %s", err) } } self.wg = wg self.wg.Add(1) return }
func (no *NsqOutput) Init(config interface{}) error { no.conf = config.(*NsqOutputConfig) no.nsqwriter = nsq.NewWriter(no.conf.Address) return nil }
// HandleMessage is required to comply with NSQReader's Handler interface. // The task structure is decoded from the message body, the parameters and method // are extracted through reflection, and finally, after execution, // the task results are packed, serialized, and published to the topic and // channel unique for this task. func (self *TaskHandler) HandleMessage(message *nsq.Message) (err error) { defer func() { if r := recover(); r != nil { log.Println("Task Handler panicked, but recovered", r) } }() if self.options.Verbose { log.Printf("Received task message %s", message.Id) } remoteTask := &Task{} err = Decode(remoteTask, message.Body) if err != nil { log.Printf("ERROR: Could not decode task from message %s: %s", message.Id, err) // publish error message to response topic return } // Obtain the Value through which to call the method and its parameters methodValue, err := getMethodValue(remoteTask) if err != nil { log.Printf("ERROR: Could not obtain method value for task %s, method %s: %s", remoteTask.ResponseTopic, remoteTask.Method, err) // publish error message to response topic return } methodParams, err := getMethodParams(remoteTask) if err != nil { log.Printf("ERROR: Could not obtain method parameters for task %s, method %s: %s", remoteTask.ResponseTopic, remoteTask.Method, err) // publish error message to response topic return } // Execute; this can panic hence the deferred recover at top results := methodValue.Call(methodParams) // Pack the results and return them - any actual // method error (that is, an error in the logical execution // of the method, as opposed to the call) will be part of these // The client is responsible for handling that. taskResult := &TaskResult{NewMethodState: remoteTask.MethodState, Method: remoteTask.Method, Returns: make([]interface{}, len(results))} for idx := range results { taskResult.Returns[idx] = results[idx].Interface() } resultBody, err := EncodeResult(taskResult) if err != nil { log.Printf("ERROR: Could not encode results for publishing to task %s, method %s: %s", remoteTask.ResponseTopic, remoteTask.Method, err) // publish error message to response topic return } // Dispatch result: // Open up a writer using the options // Write the result // Close the writer. resultWriter := nsq.NewWriter(self.options.MsgSinkTcpAddr) frameType, _, err := resultWriter.Publish(remoteTask.ResponseTopic, resultBody) if err != nil || frameType == nsq.FrameTypeError { log.Printf("ERROR: Could not publish results of task %s, method %s: %s", remoteTask.ResponseTopic, remoteTask.Method, err) return } return }