Documentation
¶
Index ¶
- Variables
- func RunAdapter(ctx context.Context, adapter FrameworkAdapter, opts RuntimeOptions) error
- type AccountQueue
- type AdmissionController
- type AdmissionDecision
- type AdmissionLimits
- type AdmissionRejectedError
- type Aquifer
- func (a *Aquifer) AdmissionSnapshot() map[string]any
- func (a *Aquifer) Enqueue(req JobRequest) (EnqueueResult, error)
- func (a *Aquifer) GetJob(id string) (*Job, error)
- func (a *Aquifer) HandleL8Challenge(req L8ChallengeReq) (*L8ChallengeResp, error)
- func (a *Aquifer) Health() map[string]any
- func (a *Aquifer) L8Metadata(host string) L8Meta
- func (a *Aquifer) MaxBodyBytes() int64
- func (a *Aquifer) RetryAfterSeconds() int
- func (a *Aquifer) SubscribeJob(id string) (*Job, <-chan SSEEvent, func(), error)
- type Broker
- type Config
- type EnqueueResult
- type FrameworkAdapter
- type HTTPAdapter
- type Job
- type JobRequest
- type L8ChallengeReq
- type L8ChallengeResp
- type L8Meta
- type L8Registry
- type MCPStdioAdapter
- type MetricsAdapter
- type NoopMetricsAdapter
- func (NoopMetricsAdapter) FlowRate(upstream string, rps float64)
- func (NoopMetricsAdapter) JobCompleted(userID, upstream string, durationMs int64)
- func (NoopMetricsAdapter) JobDispatched(userID, upstream string)
- func (NoopMetricsAdapter) JobFailed(userID, upstream string, reason string)
- func (NoopMetricsAdapter) JobQueued(userID, upstream string)
- func (NoopMetricsAdapter) QueueDepth(upstream string, depth int)
- func (NoopMetricsAdapter) WebhookDelivered(url string, attempt int)
- func (NoopMetricsAdapter) WebhookFailed(url string, attempts int)
- type RateConfig
- type Registry
- type Runtime
- type RuntimeOptions
- type SSEEvent
- type Server
- type Status
- type Store
- func (s *Store) CheckOrInsert(job *Job) (string, bool)
- func (s *Store) Counts() StoreCounts
- func (s *Store) DeleteJob(jobID string)
- func (s *Store) GetJob(jobID string) *Job
- func (s *Store) GetQueuedJobs() []*Job
- func (s *Store) MarkInFlight(jobID string)
- func (s *Store) Path() string
- func (s *Store) RecoverInFlight(queueKey string) []*Job
- func (s *Store) SetQueueKey(jobID, queueKey string)
- func (s *Store) UpdateStatus(jobID string, status Status)
- type StoreCounts
- type URLWorker
Constants ¶
This section is empty.
Variables ¶
var ErrJobNotFound = errors.New("job not found")
Functions ¶
func RunAdapter ¶
func RunAdapter(ctx context.Context, adapter FrameworkAdapter, opts RuntimeOptions) error
Types ¶
type AccountQueue ¶
type AccountQueue struct {
// contains filtered or unexported fields
}
func NewAccountQueue ¶
func NewAccountQueue(key, upstream string, rps float64, maxConc int, store *Store, broker *Broker, l8 *L8Registry, metrics MetricsAdapter, onIdle func(string)) *AccountQueue
func (*AccountQueue) Enqueue ¶
func (q *AccountQueue) Enqueue(job *Job)
func (*AccountQueue) RPS ¶
func (q *AccountQueue) RPS() float64
type AdmissionController ¶ added in v0.3.0
type AdmissionController struct {
// contains filtered or unexported fields
}
AdmissionController evaluates memory and DB size limits at request time. Body size is enforced separately at the transport layer via http.MaxBytesReader, since that has to happen before the body is even read.
func NewAdmissionController ¶ added in v0.3.0
func NewAdmissionController(limits AdmissionLimits, dbPath string) *AdmissionController
func (*AdmissionController) AnyLimitConfigured ¶ added in v0.3.0
func (c *AdmissionController) AnyLimitConfigured() bool
AnyLimitConfigured reports whether at least one admission limit is actually active, as opposed to merely whether a controller instance exists (the runtime always constructs one, even with everything at zero).
func (*AdmissionController) Check ¶ added in v0.3.0
func (c *AdmissionController) Check() AdmissionDecision
func (*AdmissionController) MaxBodyBytes ¶ added in v0.3.0
func (c *AdmissionController) MaxBodyBytes() int64
func (*AdmissionController) RetryAfterSeconds ¶ added in v0.3.0
func (c *AdmissionController) RetryAfterSeconds() int
func (*AdmissionController) Snapshot ¶ added in v0.3.0
func (c *AdmissionController) Snapshot() map[string]any
Snapshot reports current admission pressure for /health, independent of whether any request is currently being rejected.
type AdmissionDecision ¶ added in v0.3.0
type AdmissionDecision struct {
Allowed bool
Reason string // "memory" or "db_size"
Limit int64
Current int64
}
AdmissionDecision is the result of an admission check on a new (non-duplicate) job.
type AdmissionLimits ¶ added in v0.3.0
type AdmissionLimits struct {
MemoryLimitMB int64 // AQUIFER_MEMORY_LIMIT_MB
MaxBodyBytes int64 // AQUIFER_MAX_BODY_BYTES
DBMaxBytes int64 // AQUIFER_DB_MAX_BYTES
RetryAfterSeconds int // AQUIFER_RETRY_AFTER_SECONDS
}
AdmissionLimits are operator-configured ceilings that protect Aquifer itself from the traffic it's meant to be absorbing. All limits are opt-in: a zero value disables that particular check, preserving today's unbounded behavior for anyone who hasn't configured them.
func LoadAdmissionLimits ¶ added in v0.3.0
func LoadAdmissionLimits() AdmissionLimits
LoadAdmissionLimits reads the AQUIFER_* admission env vars. Missing or unparsable values fall back to disabled (0) for the size limits and 5 seconds for retry-after.
type AdmissionRejectedError ¶ added in v0.3.0
type AdmissionRejectedError struct {
Decision AdmissionDecision
}
AdmissionRejectedError is returned by Aquifer.Enqueue when a genuinely new job is rejected due to memory or DB size pressure. Callers (the HTTP server) type-assert on this to build a 429 with Retry-After.
func (*AdmissionRejectedError) Error ¶ added in v0.3.0
func (e *AdmissionRejectedError) Error() string
type Aquifer ¶
type Aquifer struct {
// contains filtered or unexported fields
}
func NewAquifer ¶
func NewAquifer(store *Store, registry *Registry, broker *Broker, l8 *L8Registry, admission *AdmissionController) *Aquifer
func (*Aquifer) AdmissionSnapshot ¶ added in v0.3.0
AdmissionSnapshot reports current admission pressure for /health. Returns enabled:false if admission control isn't configured.
func (*Aquifer) Enqueue ¶
func (a *Aquifer) Enqueue(req JobRequest) (EnqueueResult, error)
func (*Aquifer) HandleL8Challenge ¶
func (a *Aquifer) HandleL8Challenge(req L8ChallengeReq) (*L8ChallengeResp, error)
func (*Aquifer) L8Metadata ¶
func (*Aquifer) MaxBodyBytes ¶ added in v0.3.0
MaxBodyBytes returns the configured request body ceiling, or 0 if unconfigured (unlimited).
func (*Aquifer) RetryAfterSeconds ¶ added in v0.3.0
RetryAfterSeconds returns the configured Retry-After value for 429 responses, defaulting to 5 seconds if admission control isn't configured.
type Broker ¶
type Broker struct {
// contains filtered or unexported fields
}
Broker is the pub/sub layer for SSE streams. Each job gets its own set of subscriber channels.
type Config ¶
type Config struct {
Defaults RateConfig `yaml:"defaults"`
Upstreams map[string]RateConfig `yaml:"upstreams"`
}
func LoadConfig ¶
func (*Config) ForURL ¶
func (c *Config) ForURL(rawURL string) RateConfig
type EnqueueResult ¶
type FrameworkAdapter ¶
type HTTPAdapter ¶
type HTTPAdapter struct {
// contains filtered or unexported fields
}
func NewHTTPAdapter ¶
func NewHTTPAdapter(addr string) *HTTPAdapter
func (*HTTPAdapter) Name ¶
func (a *HTTPAdapter) Name() string
type Job ¶
type Job struct {
ID string `json:"id"`
UserID string `json:"user_id"`
IdempotentKey string `json:"idempotent_key"`
URL string `json:"url"`
Method string `json:"method"`
Headers map[string]string `json:"headers,omitempty"`
Body string `json:"body,omitempty"`
WebhookURL string `json:"webhook_url"`
Status Status `json:"status"`
CreatedAt int64 `json:"created_at"`
}
func NewJob ¶
func NewJob(r *JobRequest) *Job
type JobRequest ¶
type JobRequest struct {
UserID string `json:"user_id"`
IdempotentKey string `json:"idempotent_key"`
URL string `json:"url"`
Method string `json:"method"`
Headers map[string]string `json:"headers,omitempty"`
Body string `json:"body,omitempty"`
WebhookURL string `json:"webhook_url"`
// AccountQueueMode is never read from the request body — it's set by the
// HTTP adapter from the X-Aqueduct-Account-Queue / X-Aquifer-Account-Queue
// request header, the only source of truth for this setting. Empty means
// "no opinion, leave the upstream's current mode unchanged."
AccountQueueMode string `json:"-"`
}
func (*JobRequest) Validate ¶
func (r *JobRequest) Validate() string
type L8ChallengeReq ¶
type L8ChallengeResp ¶
type L8Meta ¶
type L8Meta struct {
ProtocolVersion string `json:"protocol_version"`
ServiceName string `json:"service_name"`
PublicKey string `json:"public_key"`
ChallengeEndpoint string `json:"challenge_endpoint"`
SupportedAlgos []string `json:"supported_algorithms"`
Capabilities []string `json:"capabilities"`
SpecURL string `json:"spec_url"`
}
type L8Registry ¶
type L8Registry struct {
PubB64 string // exported so server can embed in responses
// contains filtered or unexported fields
}
func NewL8Registry ¶
func NewL8Registry(keyPath, trustDir string) *L8Registry
func (*L8Registry) EnsureTrust ¶
func (r *L8Registry) EnsureTrust(webhookURL string)
EnsureTrust runs the L8 handshake with the webhook domain if not already trusted. Silently does nothing if the receiver doesn't support L8 — delivery still proceeds unsigned.
func (*L8Registry) HandleChallenge ¶
func (r *L8Registry) HandleChallenge(req L8ChallengeReq) (*L8ChallengeResp, error)
HandleChallenge verifies the sender's ownership proof and returns Aquifer's signed response.
func (*L8Registry) IsTrusted ¶
func (r *L8Registry) IsTrusted(webhookURL string) bool
IsTrusted returns true if the L8 handshake has been completed for this webhook domain.
func (*L8Registry) Meta ¶
func (r *L8Registry) Meta(host string) L8Meta
func (*L8Registry) SignHeaders ¶
func (r *L8Registry) SignHeaders(body []byte) map[string]string
SignHeaders returns X-L8-* headers to attach to an outgoing webhook delivery.
type MCPStdioAdapter ¶
type MCPStdioAdapter struct {
// contains filtered or unexported fields
}
func NewMCPStdioAdapter ¶
func NewMCPStdioAdapter(in io.Reader, out io.Writer) *MCPStdioAdapter
func (*MCPStdioAdapter) Name ¶
func (a *MCPStdioAdapter) Name() string
type MetricsAdapter ¶
type MetricsAdapter interface {
JobQueued(userID, upstream string)
JobDispatched(userID, upstream string)
JobCompleted(userID, upstream string, durationMs int64)
JobFailed(userID, upstream string, reason string)
WebhookDelivered(url string, attempt int)
WebhookFailed(url string, attempts int)
QueueDepth(upstream string, depth int)
FlowRate(upstream string, rps float64)
}
type NoopMetricsAdapter ¶
type NoopMetricsAdapter struct{}
func (NoopMetricsAdapter) FlowRate ¶
func (NoopMetricsAdapter) FlowRate(upstream string, rps float64)
func (NoopMetricsAdapter) JobCompleted ¶
func (NoopMetricsAdapter) JobCompleted(userID, upstream string, durationMs int64)
func (NoopMetricsAdapter) JobDispatched ¶
func (NoopMetricsAdapter) JobDispatched(userID, upstream string)
func (NoopMetricsAdapter) JobFailed ¶
func (NoopMetricsAdapter) JobFailed(userID, upstream string, reason string)
func (NoopMetricsAdapter) JobQueued ¶
func (NoopMetricsAdapter) JobQueued(userID, upstream string)
func (NoopMetricsAdapter) QueueDepth ¶
func (NoopMetricsAdapter) QueueDepth(upstream string, depth int)
func (NoopMetricsAdapter) WebhookDelivered ¶
func (NoopMetricsAdapter) WebhookDelivered(url string, attempt int)
func (NoopMetricsAdapter) WebhookFailed ¶
func (NoopMetricsAdapter) WebhookFailed(url string, attempts int)
type RateConfig ¶
type Registry ¶
type Registry struct {
// contains filtered or unexported fields
}
func NewRegistry ¶
func NewRegistry(store *Store, cfg *Config, broker *Broker, l8 *L8Registry, metrics MetricsAdapter) *Registry
func (*Registry) Enqueue ¶
Enqueue queues a job on the URLWorker for its upstream domain. accountQueueHeader is the raw X-Aqueduct-Account-Queue/X-Aquifer-Account-Queue value from the originating HTTP request, or "" if this job has no live request behind it (e.g. recovered from disk at startup). An empty value leaves the worker's current account-queue mode unchanged rather than forcing it off — the mode is shared per upstream domain, so one request that doesn't care about it shouldn't be able to flip it off for every other concurrent tenant relying on it being on.
func (*Registry) JobDispatched ¶
func (r *Registry) JobDispatched()
type Runtime ¶
type Runtime struct {
Aquifer *Aquifer
Store *Store
Broker *Broker
Registry *Registry
L8 *L8Registry
Config *Config
Admission *AdmissionController
}
func NewRuntime ¶
func NewRuntime(opts RuntimeOptions) *Runtime
func (*Runtime) RecoverQueuedJobs ¶
type RuntimeOptions ¶
type RuntimeOptions struct {
DBPath string
ConfigPath string
Config *Config
L8KeyPath string
L8TrustDir string
Metrics MetricsAdapter
AdmissionLimits *AdmissionLimits
}
type Store ¶
type Store struct {
// contains filtered or unexported fields
}
func (*Store) Counts ¶
func (s *Store) Counts() StoreCounts
func (*Store) DeleteJob ¶ added in v0.3.0
DeleteJob removes a job row outright. Used when a freshly-inserted, non-duplicate job is rejected by admission control — CheckOrInsert already wrote the row before duplicate status was known, so a rejected job must be deleted here or it would sit as a ghost "queued" row that never dispatches.
func (*Store) GetQueuedJobs ¶
func (*Store) MarkInFlight ¶
func (*Store) RecoverInFlight ¶
func (*Store) SetQueueKey ¶
func (*Store) UpdateStatus ¶
type StoreCounts ¶
type URLWorker ¶
type URLWorker struct {
// contains filtered or unexported fields
}
func NewURLWorker ¶
func NewURLWorker(domain string, rps float64, maxConc int, store *Store, broker *Broker, l8 *L8Registry, metrics MetricsAdapter, onIdle func(string)) *URLWorker