Skip to main content

Go SDK

The Go SDK for writing TaskDaemon handlers.

Installation

go get github.com/taskdaemon/handler-go

Basic Usage

package main

import (
    "fmt"
    taskdaemon "github.com/taskdaemon/handler-go"
)

func main() {
    taskdaemon.Run(func(task taskdaemon.Task) taskdaemon.Result {
        name, _ := task.TaskData["name"].(string)
        if name == "" {
            name = "World"
        }
        return taskdaemon.Success(map[string]any{
            "message": fmt.Sprintf("Hello, %s!", name),
        })
    })
}

Task Struct

type Task struct {
    TaskID   string                 `json:"task_id"`
    TaskType string                 `json:"task_type"`
    TaskData map[string]interface{} `json:"task_data"`
    Attempt  int                    `json:"attempt"`  // Current attempt (starts at 0)
}

Result Functions

// Success with result
return taskdaemon.Success(map[string]any{"result": "value"})

// Non-retryable error
return taskdaemon.Error("invalid input", false)

// Retryable error
return taskdaemon.Error("service unavailable", true)
The Result struct:
type Result struct {
    Status    string      `json:"status"`
    Result    interface{} `json:"result,omitempty"`
    Error     string      `json:"error,omitempty"`
    Retryable bool        `json:"retryable,omitempty"`
}

Complete Example

package main

import (
    "bytes"
    "encoding/base64"
    "image"
    "image/png"
    "net/http"

    "github.com/nfnt/resize"
    taskdaemon "github.com/taskdaemon/handler-go"
)

func main() {
    taskdaemon.Run(resizeImage)
}

func resizeImage(task taskdaemon.Task) taskdaemon.Result {
    url, _ := task.TaskData["image_url"].(string)
    width, _ := task.TaskData["width"].(float64)
    height, _ := task.TaskData["height"].(float64)

    // Download
    resp, err := http.Get(url)
    if err != nil {
        return taskdaemon.Error(err.Error(), true)  // Retryable
    }
    defer resp.Body.Close()

    // Decode
    img, _, err := image.Decode(resp.Body)
    if err != nil {
        return taskdaemon.Error(err.Error(), false)
    }

    // Resize
    resized := resize.Resize(uint(width), uint(height), img, resize.Lanczos3)

    // Encode
    var buf bytes.Buffer
    if err := png.Encode(&buf, resized); err != nil {
        return taskdaemon.Error(err.Error(), false)
    }

    b64 := base64.StdEncoding.EncodeToString(buf.Bytes())

    return taskdaemon.Success(map[string]any{
        "data":   b64,
        "size":   []int{int(width), int(height)},
        "format": "png",
    })
}

Error Handling

JSON parsing errors are automatically handled:
taskdaemon.Run(func(task taskdaemon.Task) taskdaemon.Result {
    // If JSON parsing fails, an error result is automatically returned
    // Your handler only receives valid tasks
    return taskdaemon.Success(task.TaskData)
})

Dockerfile

FROM golang:1.21-alpine AS builder
WORKDIR /app
COPY go.mod go.sum ./
RUN go mod download
COPY . .
RUN CGO_ENABLED=0 go build -o handler .

FROM alpine:latest
RUN apk --no-cache add ca-certificates
COPY --from=builder /app/handler /handler
CMD ["/handler"]
For a smaller image with static linking:
FROM golang:1.21-alpine AS builder
WORKDIR /app
COPY go.mod go.sum ./
RUN go mod download
COPY . .
RUN CGO_ENABLED=0 GOOS=linux go build -a -ldflags '-extldflags "-static"' -o handler .

FROM scratch
COPY --from=builder /app/handler /handler
COPY --from=builder /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/
CMD ["/handler"]

Handler Configuration

[handlers.resize]
image = "go-handler:latest"
instances = 4
timeout = 30