timeout

package
v1.5.5 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jun 24, 2026 License: Apache-2.0 Imports: 6 Imported by: 0

Documentation

Overview

Package timeout provides request timeout middleware for celeris.

New returns a celeris.HandlerFunc that wraps each request's context with a deadline. If the downstream handler does not complete within the configured duration, the context is cancelled and a configurable error response is returned.

Key exported symbols:

Cooperative mode (default, Preemptive: false): the handler runs in the request goroutine with the context deadline set. Handlers must observe c.Context().Done() to respect the cancellation. No goroutine or buffer overhead.

Preemptive mode (Preemptive: true): the handler runs in a spawned goroutine with the response buffered. When the deadline expires the middleware waits for the goroutine to exit, discards the buffered response, and invokes the error handler. Handlers MUST exit promptly on context cancellation to avoid blocking the connection. Incompatible with streaming (StreamWriter).

Documentation

Full guides and examples: https://goceleris.dev/docs/middleware-traffic

Index

Examples

Constants

This section is empty.

Variables

View Source
var ErrServiceUnavailable = celeris.ErrServiceUnavailable

ErrServiceUnavailable is returned when the request timeout is exceeded. ErrServiceUnavailable aliases celeris.ErrServiceUnavailable so callers can match across timeout/circuitbreaker/ratelimit with errors.Is.

Functions

func New

func New(config ...Config) celeris.HandlerFunc

New creates a timeout middleware with the given config.

Example
package main

import (
	"github.com/goceleris/celeris/middleware/timeout"
)

func main() {
	// Zero-config: 5-second cooperative timeout.
	_ = timeout.New()
}
Example (CustomErrorHandler)
package main

import (
	"time"

	"github.com/goceleris/celeris"

	"github.com/goceleris/celeris/middleware/timeout"
)

func main() {
	// Custom error handler that receives the timeout cause.
	_ = timeout.New(timeout.Config{
		Timeout: 10 * time.Second,
		ErrorHandler: func(c *celeris.Context, err error) error {
			return c.JSON(503, map[string]string{"error": err.Error()})
		},
	})
}
Example (Preemptive)
package main

import (
	"time"

	"github.com/goceleris/celeris/middleware/timeout"
)

func main() {
	// Preemptive timeout: returns 503 even if handler is blocked.
	// Handlers MUST check c.Context().Done() for prompt cancellation.
	_ = timeout.New(timeout.Config{
		Timeout:    3 * time.Second,
		Preemptive: true,
	})
}

Types

type Config

type Config struct {
	// Skip defines a function to skip this middleware for certain requests.
	Skip func(c *celeris.Context) bool

	// Timeout is the request timeout duration. Default: 5s.
	// Used as the fallback when TimeoutFunc is nil or returns zero.
	Timeout time.Duration

	// TimeoutFunc computes a per-request timeout duration. When non-nil,
	// its return value is used instead of the static Timeout. If it
	// returns zero or a negative duration, the static Timeout is used
	// as a fallback.
	//
	// TimeoutFunc is called before BufferResponse in preemptive mode,
	// so it runs on the request goroutine (not the handler goroutine).
	TimeoutFunc func(c *celeris.Context) time.Duration

	// ErrorHandler handles timeout errors. The err parameter is
	// context.DeadlineExceeded for a deadline timeout, the matched
	// TimeoutErrors entry for a semantic timeout, or a panic-wrapped error
	// for a recovered panic. Default: returns 503 Service Unavailable.
	ErrorHandler func(c *celeris.Context, err error) error

	// SkipPaths lists paths to skip (exact match).
	SkipPaths []string

	// Preemptive enables preemptive timeout mode. When true, the handler
	// runs in a goroutine and the response is buffered. If the handler
	// does not complete within the timeout, the middleware waits for the
	// goroutine to finish, discards the buffered response, and returns
	// the error handler result. Handlers MUST respect context cancellation
	// (select on c.Context().Done()) to avoid blocking the response.
	//
	// Preemptive mode is incompatible with StreamWriter: buffered mode
	// captures the full response in memory, defeating streaming and
	// potentially causing OOM on large payloads. Use non-preemptive
	// mode (the default) for streaming endpoints.
	//
	// Cost: preemptive mode allocates a goroutine and a context.WithTimeout
	// per request — measurable at very high RPS (~1-3% throughput on
	// the reference benchmark suite). Reach for it only when you
	// genuinely need to interrupt CPU-bound or blocking handlers; the
	// non-preemptive default uses a single context.WithTimeout and lets
	// handlers cooperatively check c.Context().Done().
	Preemptive bool

	// TimeoutErrors lists errors that should be treated as timeouts even
	// if the deadline has not been reached. When the handler returns an
	// error matching any entry via errors.Is, the ErrorHandler is invoked
	// as though the request timed out. This is useful for treating
	// upstream timeout errors (e.g. database query timeout) as request
	// timeouts.
	TimeoutErrors []error
}

Config defines the timeout middleware configuration.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL