serverless

package
v0.2.1 Latest Latest
Warning

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

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

Documentation

Overview

Package serverless is the seam between Celerity handlers and a provider's serverless platform.

In a containerised deployment the Celerity runtime routes the event and hands the handler something already in the SDK's vocabulary. In a serverless deployment the platform does that job in its own shapes instead, and an adapter translates.

A provider implements two things, an EventMapper and Adapter.Start. Everything with a rule in it, resolving which handler this function is, caching it across warm invocations, running the layer pipeline, and deciding what an unroutable event means, lives here and is inherited rather than reimplemented per provider.

Index

Constants

View Source
const (
	HandlerIDEnvVar  = "CELERITY_HANDLER_ID"
	HandlerTagEnvVar = "CELERITY_HANDLER_TAG"
)

Environment variables a Celerity deployment sets on each function, naming the one handler that function serves.

Variables

View Source
var ErrNoHandler = errors.New("celerity: no handler for event")

ErrNoHandler is returned when an event reaches a function that serves no handler for it.

Functions

func Register

func Register(adapter Adapter)

Register adds an adapter to the set considered at startup.

It is called from an adapter package's init function and panics on a duplicate name, which can only mean two adapters claiming one platform.

func Registered

func Registered() []string

Registered returns every linked adapter, by name and sorted.

The handler manifest reports this, so that a deployment targeting a platform the binary has no adapter for is caught when the application is built rather than when it is first invoked.

func Serve

func Serve(ctx context.Context, adapter Adapter, resolver Resolver) error

Serve builds the invoker for an adapter and hands control to the provider's event loop. It does not return until the process is shutting down.

func WebSocketSenderFrom

func WebSocketSenderFrom(ctx context.Context) (handler.WebSocketSender, bool)

WebSocketSenderFrom returns the sender for this invocation, if there is one.

Handlers reach it through celerity.WebSocketSenderFrom, which also covers the runtime's IPC side channel.

func WithWebSocketSender

func WithWebSocketSender(ctx context.Context, s handler.WebSocketSender) context.Context

WithWebSocketSender returns a context carrying the sender for this invocation.

Adapters do not call this directly; NewInvoker does it when the adapter implements WebSocketSenderProvider.

Types

type Adapter

type Adapter interface {
	// Name identifies the adapter in logs and errors, such as "aws-lambda".
	Name() string
	// Detect reports whether this process is running on the adapter's platform,
	// which every serverless runtime makes knowable from the environment.
	//
	// It is what makes selecting an adapter an import rather than a decision the
	// application has to encode, and it is why one binary can carry adapters for
	// several platforms.
	Detect() bool
	Mapper() EventMapper
	// Start hands control to the provider's own event loop, which calls invoke
	// once per invocation and does not return until the process is shutting
	// down.
	Start(ctx context.Context, invoke Invoker) error
}

Adapter is a provider's mapper together with its process entry point.

func Detected

func Detected() (Adapter, bool)

Detected returns the adapter whose platform this process is running on.

Several adapters may be linked into one binary, which is what lets a single artefact target more than one platform; at most one of them detects its own environment.

type EventMapper

type EventMapper interface {
	// Detect reports which source a payload came from, so a function that is
	// not told what it serves can still route.
	Detect(payload []byte) (handler.Kind, error)

	ToRequest(payload []byte) (*handler.Request, error)
	FromResponse(res *handler.Response) (any, error)

	ToWebSocketMessage(payload []byte) (*handler.WebSocketMessage, error)

	ToConsumerBatch(payload []byte, tag string) (*handler.ConsumerBatch, error)
	FromBatchResult(res *handler.BatchResult) (any, error)

	ToScheduleTrigger(payload []byte, tag string) (*handler.ScheduleTrigger, error)

	ToCustomInvoke(payload []byte) (*handler.CustomInvoke, error)
	FromCustomResult(res *handler.CustomInvokeResult) (any, error)
}

EventMapper converts between a provider's event shapes and the SDK's.

A mapper only translates. It resolves nothing and decides nothing, so an unroutable event or a failing handler is never its concern.

type Handler

type Handler struct {
	Tag  string
	Name string
	Kind handler.Kind
	// Invoke runs the full pipeline: application layers, then group, then
	// handler, with guards ahead of them.
	Invoke layer.Next
}

Handler is a resolved handler an adapter invokes, with its layers already applied.

type Invoker

type Invoker func(ctx context.Context, payload []byte) (any, error)

Invoker handles one raw provider payload.

The payload is the provider's own encoded event, and the returned value is whatever that provider's runtime expects to serialise back.

func NewInvoker

func NewInvoker(adapter Adapter, resolver Resolver) Invoker

NewInvoker builds the invoker an adapter's event loop calls once per invocation.

Resolution happens on the first invocation and is cached for the life of the execution environment, so a warm invocation does no lookup.

type MissingAdapterError

type MissingAdapterError struct {
	// Linked names the adapters that are compiled in, which is commonly empty
	// and is the useful half of the message when it is not.
	Linked []string
}

MissingAdapterError reports that the process is running under a serverless platform that no linked adapter serves.

It names the import that would fix it, because the fix is always an import and guessing which one is not the developer's job.

func (*MissingAdapterError) Error

func (e *MissingAdapterError) Error() string

type ReceiptAcknowledger

type ReceiptAcknowledger interface {
	// AcknowledgeReceipt tells the client its message arrived, where the message
	// asked to be told and the transport leaves that to the SDK.
	//
	// Called before the handler runs, and for a message that reaches no handler
	// at all: the client asked whether its message arrived, and it did.
	AcknowledgeReceipt(ctx context.Context, msg *handler.WebSocketMessage) error
}

ReceiptAcknowledger is implemented by adapters whose transport leaves acknowledging a client's WebSocket message to the SDK.

The WebSocket Runtime Protocol has a message that asked to be acknowledged acknowledged on receipt, which is what lets a client stop its resend timer without waiting on however long the work takes. The Celerity runtime does that itself, so this is empty there; a managed gateway does not, so the adapter does it and an application implements none of it.

It is a separate interface rather than a method on Adapter for the reason WebSocketSenderProvider is: an adapter for a platform this does not apply to is not forced to stub it.

type Resolver

type Resolver interface {
	// ByName resolves a handler by blueprint resource name or published name,
	// which is what CELERITY_HANDLER_ID carries.
	ByName(name string) (*Handler, bool)
	// ByTag resolves a handler by its handler tag.
	ByTag(tag string) (*Handler, bool)
	// Only returns the single handler of a kind, when there is exactly one.
	// A Celerity deployment gives each handler its own function, so this is the
	// ordinary case and it resolves a function that was told nothing.
	Only(kind handler.Kind) (*Handler, bool)
}

Resolver finds the handler a payload should reach.

It is an interface so that this package does not depend on the celerity package, which depends on it.

type WebSocketSenderProvider

type WebSocketSenderProvider interface {
	// WebSocketSender builds a sender for the connection the payload came from,
	// since the endpoint to push to is commonly carried by the event itself.
	WebSocketSender(ctx context.Context, payload []byte) (handler.WebSocketSender, error)
}

WebSocketSenderProvider is implemented by adapters that can push to a WebSocket connection, such as through the API Gateway Management API.

It is a separate interface rather than a method on Adapter so that an adapter for a platform without WebSocket support is not forced to stub it.

Directories

Path Synopsis
aws module

Jump to

Keyboard shortcuts

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