Documentation
¶
Overview ¶
Package queueservice composes explicit queue producers and workers with the service lifecycle and the existing correlation queue semantics.
Producer resources remain concrete and caller-visible. A non-nil Shutdown transfers close ownership; shared resources omit it. Service shutdown first rejects new publishes, waits for active publishes within the service context, and only then closes an owned transport. PublishWithAcceptance exposes definite rejection, confirmed acceptance, and ambiguous acceptance; the adapter never retries an application publish.
LifecycleWorker adapts typed startup, readiness, blocking run, handler, and shutdown callbacks into one service plan. Worker retains the smaller *queue.Queue convenience boundary. Both paths stop intake, join admitted work within the service context, and release the concrete transport only after the drain. NewHandler creates a new request ID for every delivery. TrustedMetadata must be enabled only after authenticating the immediate queue boundary. Callback failures preserve their causes without formatting their text, and callback panics are returned without retaining their values.
Index ¶
- Constants
- Variables
- type CallbackError
- type CallbackOperation
- type CallbackPanicError
- type Check
- type CloseAdmission
- type Handler
- type HandlerOptions
- type LifecycleWorker
- type LifecycleWorkerOptions
- type OptionsError
- type Producer
- func (producer *Producer[R]) Component() service.Component
- func (producer *Producer[R]) Publish(ctx context.Context, message core.QueuedMessage, options ...job.AllowOption) (correlation.Values, error)
- func (producer *Producer[R]) PublishWithAcceptance(ctx context.Context, message core.QueuedMessage, options ...job.AllowOption) (correlation.Values, PublishAcceptance, error)
- func (producer *Producer[R]) Readiness() (service.ReadinessCheck, bool)
- func (producer *Producer[R]) Resource() R
- type ProducerOptions
- type Publish
- type PublishAcceptance
- type PublishError
- type PublishWithAcceptance
- type Run
- type Shutdown
- type Startup
- type StartupError
- type Worker
- type WorkerOptions
Examples ¶
Constants ¶
const MaxNameBytes = 128
MaxNameBytes bounds component, task, and readiness identifiers.
Variables ¶
var ( // ErrInvalidOptions identifies invalid adapter construction. ErrInvalidOptions = errors.New("invalid queue service options") ErrUnavailable = errors.New("queue service adapter unavailable") // ErrMissingCorrelation reports a publish without an explicit parent // workflow. Callers beginning new work must start it with their factory. ErrMissingCorrelation = errors.New("queue service producer correlation missing") // ErrCallbackPanic reports a recovered application callback panic. ErrCallbackPanic = errors.New("queue service callback panicked") // ErrPublishOutcomeUnknown reports a publish that may have reached the // backend and therefore must not be retried blindly. ErrPublishOutcomeUnknown = errors.New("queue service publish outcome unknown") // ErrInvalidPublishAcceptance reports a callback result outside the public // acceptance contract. ErrInvalidPublishAcceptance = errors.New("queue service publish acceptance invalid") // ErrWorkerExited reports a worker run callback that returned successfully // before its context was canceled. ErrWorkerExited = errors.New("queue service worker exited unexpectedly") )
Functions ¶
This section is empty.
Types ¶
type CallbackError ¶
type CallbackError struct {
// Operation identifies the callback boundary.
Operation CallbackOperation
// Err is the original callback failure.
Err error
}
CallbackError preserves a callback failure for errors.Is and errors.As without formatting potentially sensitive backend or application text.
func (*CallbackError) Error ¶
func (err *CallbackError) Error() string
Error returns a secret-safe callback failure.
func (*CallbackError) Unwrap ¶
func (err *CallbackError) Unwrap() error
Unwrap preserves the callback cause for errors.Is and errors.As.
type CallbackOperation ¶
type CallbackOperation uint8
CallbackOperation identifies one application callback boundary.
const ( // CallbackStartup identifies resource validation during service start. CallbackStartup CallbackOperation = 1 // CallbackReadiness identifies an opt-in dependency readiness check. CallbackReadiness CallbackOperation = 2 // CallbackPublish identifies concrete producer publication. CallbackPublish CallbackOperation = 3 // CallbackHandler identifies application task handling. CallbackHandler CallbackOperation = 4 // CallbackRun identifies supervised worker intake. CallbackRun CallbackOperation = 5 // CallbackShutdown identifies transferred resource cleanup. CallbackShutdown CallbackOperation = 6 // CallbackAdmission identifies synchronous worker intake closure. CallbackAdmission CallbackOperation = 7 )
type CallbackPanicError ¶
type CallbackPanicError struct {
// Operation identifies the callback boundary.
Operation CallbackOperation
}
CallbackPanicError identifies a recovered callback without retaining or formatting the panic value.
func (*CallbackPanicError) Error ¶
func (err *CallbackPanicError) Error() string
Error returns a secret-safe callback failure.
func (*CallbackPanicError) Unwrap ¶
func (err *CallbackPanicError) Unwrap() error
Unwrap exposes the stable panic classification.
type CloseAdmission ¶
CloseAdmission synchronously and idempotently stops new worker intake. It must return promptly and must not wait for admitted handlers to finish.
type Handler ¶
type Handler func(context.Context, core.TaskMessage) error
Handler is the queue worker handler signature.
func NewHandler ¶
func NewHandler(options HandlerOptions) (Handler, error)
NewHandler wraps application work with the existing queue receive boundary.
type HandlerOptions ¶
type HandlerOptions struct {
// Correlation creates a new request ID for every delivery attempt.
Correlation *correlation.Factory
// CorrelationOptions configure the existing queue propagation adapter.
CorrelationOptions queuecorrelation.Options
// TrustedMetadata preserves inbound correlation only when explicitly true.
TrustedMetadata bool
// TracePropagator explicitly extracts caller-owned telemetry context when
// configured. Nil disables trace propagation.
TracePropagator propagation.TextMapPropagator
// Handler performs application-owned work.
Handler Handler
}
HandlerOptions configure a correlation-aware delivery boundary.
type LifecycleWorker ¶
type LifecycleWorker[R any] struct { // contains filtered or unexported fields }
LifecycleWorker retains a concrete worker and explicit lifecycle callbacks.
func NewLifecycleWorker ¶
func NewLifecycleWorker[R any]( options LifecycleWorkerOptions[R], ) (*LifecycleWorker[R], error)
NewLifecycleWorker validates and constructs an inert typed worker adapter.
Example ¶
package main
import (
"context"
"errors"
"fmt"
"time"
"github.com/faustbrian/go-correlation"
"github.com/faustbrian/go-queue/core"
"github.com/faustbrian/go-queue/queueservice"
)
type typedWorkerResource struct{}
type typedDelivery string
func (delivery typedDelivery) Bytes() []byte { return []byte(delivery) }
func (delivery typedDelivery) Payload() []byte { return []byte(delivery) }
func main() {
factory, _ := correlation.NewFactory(correlation.FactoryOptions{})
worker, err := queueservice.NewLifecycleWorker(
queueservice.LifecycleWorkerOptions[*typedWorkerResource]{
Name: "orders-worker",
Resource: &typedWorkerResource{},
Correlation: factory,
Handler: func(_ context.Context, task core.TaskMessage) error {
fmt.Println(string(task.Payload()))
return nil
},
Run: func(
ctx context.Context,
_ *typedWorkerResource,
handler queueservice.Handler,
) error {
return handler(ctx, typedDelivery("delivery"))
},
Shutdown: func(context.Context, *typedWorkerResource) error {
return nil
},
},
)
if err != nil {
return
}
plan := worker.Plan()
if err = plan.Components[0].Start(context.Background()); err != nil {
return
}
if err = plan.Tasks[0].Run(context.Background()); !errors.Is(err, queueservice.ErrWorkerExited) {
return
}
stopContext, cancel := context.WithTimeout(context.Background(), time.Second)
defer cancel()
if err = plan.Components[0].Stop(stopContext); err != nil {
return
}
}
Output: delivery
func (*LifecycleWorker[R]) Plan ¶
func (worker *LifecycleWorker[R]) Plan() service.Plan
Plan returns the worker component, supervised run task, and optional readiness check under one stable identity.
func (*LifecycleWorker[R]) Resource ¶
func (worker *LifecycleWorker[R]) Resource() R
Resource returns the exact caller-provided worker resource.
type LifecycleWorkerOptions ¶
type LifecycleWorkerOptions[R any] struct { // Name is the secret-safe component, task, and readiness name. Name string // Resource is the caller-constructed concrete worker. Resource R // Correlation creates a new request ID for every delivery attempt. Correlation *correlation.Factory // CorrelationOptions configure the existing queue propagation adapter. CorrelationOptions queuecorrelation.Options // TrustedMetadata preserves inbound correlation only when explicitly true. TrustedMetadata bool // TracePropagator explicitly extracts caller-owned telemetry context when // configured. Nil disables trace propagation. TracePropagator propagation.TextMapPropagator // Handler performs application-owned work. Handler Handler // Startup optionally validates Resource before intake can run. Startup Startup[R] // Readiness optionally checks Resource after successful startup. Readiness Check[R] // CloseAdmission stops backend intake when service drain begins. The adapter // independently rejects handler calls after the callback starts. CloseAdmission CloseAdmission[R] // Run starts intake and joins admitted handlers before returning. Run Run[R] // Shutdown stops remaining transport work and closes Resource exactly once. Shutdown Shutdown[R] }
LifecycleWorkerOptions configure one typed, supervised worker lifecycle.
type OptionsError ¶
type OptionsError struct {
// Field identifies the rejected option.
Field string
// Reason describes the safe failure category.
Reason string
}
OptionsError identifies one rejected option.
func (*OptionsError) Error ¶
func (err *OptionsError) Error() string
Error returns a secret-safe construction diagnostic.
func (*OptionsError) Unwrap ¶
func (err *OptionsError) Unwrap() error
Unwrap exposes the stable option classification.
type Producer ¶
type Producer[R any] struct { // contains filtered or unexported fields }
Producer retains a concrete producer and coordinates its in-flight calls.
func NewProducer ¶
func NewProducer[R any](options ProducerOptions[R]) (*Producer[R], error)
NewProducer validates and constructs an inert producer adapter.
func (*Producer[R]) Component ¶
Component returns the producer's ordered service lifecycle component.
func (*Producer[R]) Publish ¶
func (producer *Producer[R]) Publish( ctx context.Context, message core.QueuedMessage, options ...job.AllowOption, ) (correlation.Values, error)
Publish creates a message hop, attaches its carrier to cloned job metadata, and invokes the concrete producer with that child correlation in its context. Correlation values are also returned for caller-owned logging and telemetry.
func (*Producer[R]) PublishWithAcceptance ¶
func (producer *Producer[R]) PublishWithAcceptance( ctx context.Context, message core.QueuedMessage, options ...job.AllowOption, ) (correlation.Values, PublishAcceptance, error)
PublishWithAcceptance creates a message hop and reports whether the concrete backend accepted the task. The adapter performs exactly one callback call and never retries an unknown result.
type ProducerOptions ¶
type ProducerOptions[R any] struct { // Name is the secret-safe component name. Name string // Resource is the caller-constructed concrete producer. Resource R // Correlation creates message-hop identifiers. Correlation *correlation.Factory // CorrelationOptions configure the existing queue propagation adapter. CorrelationOptions queuecorrelation.Options // TracePropagator explicitly injects caller-owned telemetry context when // configured. Nil disables trace propagation. TracePropagator propagation.TextMapPropagator // Startup optionally validates Resource before admission begins. Startup Startup[R] // Readiness optionally checks Resource after successful startup. Readiness Check[R] // Publish performs one concrete, caller-bounded append. A returned error has // unknown backend acceptance. Prefer PublishWithAcceptance when the backend // can distinguish a definite rejection from an ambiguous result. Publish Publish[R] // PublishWithAcceptance performs one concrete append with an explicit // backend-acceptance result. Exactly one publish callback is required. PublishWithAcceptance PublishWithAcceptance[R] // Shutdown transfers transport close ownership when non-nil. Shutdown Shutdown[R] }
ProducerOptions configure one producer lifecycle adapter.
type Publish ¶
type Publish[R any] func( context.Context, R, core.QueuedMessage, ...job.AllowOption, ) error
Publish appends one correlation-aware message through a concrete resource.
type PublishAcceptance ¶
type PublishAcceptance uint8
PublishAcceptance reports whether a failed publish reached the backend.
const ( // PublishNotAccepted means the backend definitively did not accept the task. PublishNotAccepted PublishAcceptance = 1 // PublishAccepted means the backend definitively accepted the task. PublishAccepted PublishAcceptance = 2 // PublishUnknown means the backend may have accepted the task. Applications // must reconcile or rely on idempotency instead of retrying blindly. PublishUnknown PublishAcceptance = 3 )
type PublishError ¶
type PublishError struct {
// Acceptance describes whether the task reached the backend.
Acceptance PublishAcceptance
// Err is the original classifiable failure.
Err error
}
PublishError preserves the backend cause and acceptance classification without formatting potentially sensitive backend details.
func (*PublishError) Error ¶
func (err *PublishError) Error() string
Error returns a secret-safe publish diagnostic.
func (*PublishError) Unwrap ¶
func (err *PublishError) Unwrap() error
Unwrap preserves the backend and stable acceptance causes.
type PublishWithAcceptance ¶
type PublishWithAcceptance[R any] func( context.Context, R, core.QueuedMessage, ...job.AllowOption, ) (PublishAcceptance, error)
PublishWithAcceptance appends one task and reports whether a failure reached the backend. It must not retry application work internally.
type Run ¶
Run owns worker intake until cancellation or backend failure and must join every handler it admits before returning.
type StartupError ¶
type StartupError struct {
// Validation is the startup-check failure.
Validation error
// Cleanup is an optional transferred-resource shutdown failure.
Cleanup error
}
StartupError preserves validation and partial-cleanup failures without formatting either potentially sensitive cause.
func (*StartupError) Error ¶
func (err *StartupError) Error() string
Error returns a secret-safe startup diagnostic.
func (*StartupError) Unwrap ¶
func (err *StartupError) Unwrap() []error
Unwrap preserves both causes for errors.Is and errors.As.
type Worker ¶
type Worker struct {
// contains filtered or unexported fields
}
Worker retains one concrete queue.
func NewWorker ¶
func NewWorker(options WorkerOptions) (*Worker, error)
NewWorker validates and constructs an inert worker lifecycle adapter.
Example ¶
package main
import (
"context"
"fmt"
"time"
"github.com/faustbrian/go-correlation"
queue "github.com/faustbrian/go-queue"
"github.com/faustbrian/go-queue/core"
"github.com/faustbrian/go-queue/job"
"github.com/faustbrian/go-queue/queueservice"
"go.opentelemetry.io/otel/propagation"
)
type payload string
func (value payload) Bytes() []byte { return []byte(value) }
func main() {
ctx, cancel := context.WithTimeout(context.Background(), time.Second)
defer cancel()
factory, _ := correlation.NewFactory(correlation.FactoryOptions{})
handled := make(chan string, 1)
handler, err := queueservice.NewHandler(queueservice.HandlerOptions{
Correlation: factory,
TrustedMetadata: true,
TracePropagator: propagation.TraceContext{},
Handler: func(_ context.Context, task core.TaskMessage) error {
handled <- string(task.Payload())
return nil
},
})
if err != nil {
return
}
ring := queue.NewRing(queue.WithFn(handler))
concrete, err := queue.NewQueue(
queue.WithWorker(ring),
queue.WithWorkerCount(1),
)
if err != nil {
return
}
worker, err := queueservice.NewWorker(queueservice.WorkerOptions{
Name: "jobs-worker", Queue: concrete,
})
if err != nil {
return
}
producer, err := queueservice.NewProducer(
queueservice.ProducerOptions[*queue.Queue]{
Name: "jobs-producer", Resource: concrete, Correlation: factory,
TracePropagator: propagation.TraceContext{},
Publish: func(
_ context.Context,
resource *queue.Queue,
message core.QueuedMessage,
options ...job.AllowOption,
) error {
return resource.Queue(message, options...)
},
},
)
if err != nil {
return
}
workerComponent := worker.Component()
producerComponent := producer.Component()
if err = workerComponent.Start(ctx); err != nil {
return
}
if err = producerComponent.Start(ctx); err != nil {
return
}
parent, _ := factory.Start()
if _, err = producer.Publish(
correlation.WithValues(ctx, parent),
payload("delivery"),
); err != nil {
return
}
select {
case value := <-handled:
fmt.Println(value)
case <-ctx.Done():
return
}
if err = producerComponent.Stop(ctx); err != nil {
return
}
if err = workerComponent.Stop(ctx); err != nil {
return
}
}
Output: delivery
type WorkerOptions ¶
type WorkerOptions struct {
// Name is the secret-safe component name.
Name string
// Queue is the caller-constructed concrete queue.
Queue *queue.Queue
}
WorkerOptions configure one concrete queue worker lifecycle.