spool

package
v0.7.0 Latest Latest
Warning

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

Go to latest
Published: Nov 9, 2026 License: Apache-2.0 Imports: 11 Imported by: 0

Documentation

Overview

Package spool shares one in-flight HTTP response between concurrent requests, which stream it while it is still being produced.

Index

Constants

This section is empty.

Variables

View Source
var ErrNotShared = errors.New("response not shared")

ErrNotShared reports that a response cannot be served from the spool. Nothing has been written to the client, so the caller must serve the request itself.

View Source
var ErrUncommitted = errors.New("spool fill returned without committing its cache write")

ErrUncommitted reports a fill that stored a cache write and returned without calling Writer.Commit, which would otherwise lose the entry silently.

Functions

This section is empty.

Types

type Config

type Config struct {
	Dir         string        `hcl:"dir,optional" help:"Directory for spool files." default:"${CACHEW_STATE}/spools"`
	FillTimeout time.Duration `hcl:"fill-timeout,optional" help:"Maximum duration of a single shared fill. 0 disables the limit." default:"30m"`
	ErrorWindow time.Duration `` /* 165-byte string literal not displayed */
}

Config configures the spool Registry.

type FillFunc

type FillFunc func(ctx context.Context, w *Writer) error

FillFunc produces the shared response into w. ctx keeps the starting request's values but not its cancellation; it ends at Registry.Close or FillTimeout.

type Group

type Group struct {
	// contains filtered or unexported fields
}

Group coalesces fills by key.

func (*Group) Close

func (g *Group) Close()

Close drops every response in the group. Requests already streaming one finish undisturbed; later Serve calls return ErrNotShared.

func (*Group) Serve

func (g *Group) Serve(w http.ResponseWriter, req *http.Request, key string, fill FillFunc) (Result, error)

Serve answers req with the shared response for key. On ErrNotShared nothing was written; any other error means a truncated body and the caller must abort.

type Provider

type Provider func() (*Registry, error)

Provider lazily constructs the process-wide Registry.

func NewProvider

func NewProvider(ctx context.Context, config Config, onReleaseError func(error)) Provider

NewProvider returns a Registry singleton provider function.

type Registry

type Registry struct {
	// contains filtered or unexported fields
}

Registry owns every in-flight fill in the process. Fills run detached from the requests that started them, so Close is the only way to cancel them.

func New

func New(ctx context.Context, config Config, onReleaseError func(error)) (*Registry, error)

New creates a Registry and removes stale spool files; ctx's cancellation is ignored, use Close. onReleaseError receives cleanup failures from any goroutine and must not call the Registry.

func (*Registry) Close

func (r *Registry) Close()

Close cancels in-flight fills and waits for them to return. Call it after the HTTP server has drained, because a cancelled fill truncates its response.

func (*Registry) NewGroup

func (r *Registry) NewGroup(retention Retention) *Group

NewGroup returns a key space whose keys never collide with another group's.

type Result

type Result struct {
	// Filled is true when this request started the fill.
	Filled bool
	// Status is the status code written to the client, or 0 if none was.
	Status int
	// Wait is how long the request waited for the response headers.
	Wait time.Duration
	// Bytes is the number of body bytes written to the client.
	Bytes int64
}

Result describes how Serve answered a request.

type Retention

type Retention int

Retention controls whether a Group keeps a successful response after its fill ends.

const (
	// ReleaseCompleted drops a successful response when its fill ends, for
	// callers that cache it so later requests hit the cache instead.
	ReleaseCompleted Retention = iota
	// RetainCompleted keeps successful responses until the Group is closed, for
	// callers with nowhere else to serve them from.
	RetainCompleted
)

type Writer

type Writer struct {
	// contains filtered or unexported fields
}

Writer receives a fill's response so existing forwarding code can write into it. It must only be used by the fill it was passed to.

func (*Writer) Commit

func (w *Writer) Commit() error

Commit stores the body in the cache and returns any cache failure, including an abandoned write. Call it after the last Write; it is a no-op without Store.

func (*Writer) Flush

func (w *Writer) Flush()

Flush is a no-op: readers see each Write as soon as it returns.

func (*Writer) Header

func (w *Writer) Header() http.Header

func (*Writer) Store

func (w *Writer) Store(cw cache.Writer) error

Store takes ownership of cw, committing it if the fill succeeds. It must follow a 2xx WriteHeader and precede the first Write.

func (*Writer) Write

func (w *Writer) Write(p []byte) (int, error)

Write appends p to the response. A cache failure fails the response only when readers follow the cache write; otherwise the cache write is abandoned.

func (*Writer) WriteHeader

func (w *Writer) WriteHeader(status int)

WriteHeader publishes status and a snapshot of the headers to readers. Informational statuses are not forwarded.

Jump to

Keyboard shortcuts

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