Relay Transport

The Relay transport bridges go-relay job queues to go-module-router handlers, providing full DI injection and go-signal event emission with zero boilerplate.

Creating the Transport

import (
    "github.com/mirkobrombin/go-module-router/v2/pkg/transport/relay"
    relaymanager "github.com/mirkobrombin/go-relay/v2/pkg/manager"
)

r := relaymanager.New()
t := relay.New(r)

Defining Handlers

Use core.Pattern with a relay:"topic" tag. Additional fields tagged with relay:"key" are populated from the job payload. Untagged fields are resolved via DI.

type SendNotification struct {
    Meta    core.Pattern `relay:"notifications.send"`
    UserID  int          `relay:"user_id"`
    Message string       `relay:"message"`
    DB      *sql.DB      // injected by DI
}

func (h *SendNotification) Handle(ctx context.Context) (any, error) {
    // process job
    return nil, nil
}

Registering Handlers

t.Provide("DB", db)
t.Register(&SendNotification{})

Starting the Worker

ctx, cancel := context.WithCancel(context.Background())
defer cancel()

if err := t.Start(ctx); err != nil {
    log.Fatal(err)
}

Start blocks until the context is cancelled, consuming jobs from the broker.

Enqueueing Jobs

Enqueue from anywhere in your application using go-relay’s Enqueue:

relaymanager.Enqueue(ctx, r, "notifications.send", map[string]any{
    "user_id": 42,
    "message": "Hello!",
})

Event Bus Integration

The Relay transport integrates with go-signal. After each successful job execution, the handler instance is emitted asynchronously on the bus.

By default, the transport uses bus.Default(). Subscribe anywhere:

import "github.com/mirkobrombin/go-signal/v2/pkg/bus"

bus.Subscribe(nil, func(ctx context.Context, e *SendNotification) error {
    fmt.Println("Notification sent to user", e.UserID)
    return nil
})

Provide a custom bus at construction time:

customBus := bus.New(bus.WithStrategy(bus.BestEffort))
t := relay.New(r, relay.WithBus(customBus))

Logger

t := relay.New(r, relay.WithLogger(logger.NewSlog(slog.Default())))

Use Cases

  • Background Workers: Process async jobs from a queue
  • Event-Driven Microservices: React to domain events
  • Scheduled Tasks: Consume periodic job payloads
  • Fan-out Processing: Multiple handlers on the same relay broker