Request-Reply Handlers

Handlers are typically implemented in Go and compiled into the binary for best performance.

Other programming languages are supported through NATS Request-Reply. A remote service can be written in any language and called out to over NATS.

Review Routing, Handlers, Concurrency, and Retry first for background. Remote handlers map directly onto the same model.

Registering with the router

client, _ := asyncjobs.NewClient(asyncjobs.NatsConn(nc), asyncjobs.BindWorkQueue("EMAIL"))

router := asyncjobs.NewTaskRouter()
router.RequestReply("email:new", client)

client.Run(router)

This registers with the router for tasks of type email:new. Tasks of that type are dispatched via NATS Request-Reply.

When all handlers in a deployment use request-reply, the Docker-based runner achieves the same outcome without any Go code.

Protocol

A lightweight JSON-plus-headers protocol communicates with the remote service. The protocol supports returning errors, including the ErrTerminateTask behavior.

The service must listen on CHORIA_AJ.H.T.email:new, typically in a NATS queue group, replacing email:new with the configured task type. A handler registered with task type "" handles all tasks, and the service listens on CHORIA.AJ.H.T.catchall.

Tasks

A request for a task handler carries these headers:

HeaderValue
AJ-Content-Typeapplication/x-asyncjobs-task+json
AJ-Handler-Deadline2009-11-10T23:00:00Z

The content type is identical for all tasks. The deadline is a UTC timestamp by which the remote service must complete handling to avoid a timeout.

The body is a JSON-encoded Task.

Responses from the service may set these headers:

HeaderDescription
AJ-ErrorIndicates an error was encountered; the value is set as the task error and the task is retried later
AJ-TerminateTerminates the task via ErrTerminateTask; the value becomes additional text in the error. No further retries are performed

The body of the response is stored on the task unmodified.

Demonstration

The nats CLI tool shows this in action:

$ nats reply CHORIA_AJ.H.T.email:new 'success' --context AJC
18:33:32 [#1] Received on subject "CHORIA_AJ.H.T.email:new":
18:33:33 AJ-Content-Type: application/x-asyncjobs-task+json
18:33:33 AJ-Handler-Deadline: 2022-02-09T17:34:31Z

{"id":"24smZHaWnjuP371iglxeQWK7nOi","type":"email:new","queue":"DEFAULT","payload":"InsuLi4ufSI=","state":"active","created":"2022-02-09T17:28:41.943198067Z","tried":"2022-02-09T17:33:33.005041134Z","tries":5}

The CLI received the job with the two headers set and the expected payload, responded with success, and the task completed.

$ ajc task view 24smZHaWnjuP371iglxeQWK7nOi --json
{
  "id": "24smZHaWnjuP371iglxeQWK7nOi",
  "type": "email:new",
  "queue": "DEFAULT",
  "payload": "InsuLi4ufSI=",
  "result": {
    "payload": "dGVzdA==",
    "completed": "2022-02-09T17:33:33.00755251Z"
  },
  "state": "complete",
  "created": "2022-02-09T17:28:41.943198067Z",
  "tried": "2022-02-09T17:33:33.007552104Z",
  "tries": 5
}