Beispiel #1
0
// 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
}
Beispiel #2
0
func (no *NsqOutput) Init(config interface{}) error {
	no.conf = config.(*NsqOutputConfig)
	no.nsqwriter = nsq.NewWriter(no.conf.Address)
	return nil
}
Beispiel #3
0
// 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
}