stores

package
v0.3.1 Latest Latest
Warning

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

Go to latest
Published: Jul 7, 2026 License: Apache-2.0 Imports: 1 Imported by: 0

Documentation

Overview

Package stores holds mcpkit's generic storage seams — backend-agnostic interfaces (plus in-memory defaults) that library features call through so a deployment can swap in Redis, SQL, or a custom backend. See STORAGE_SEAMS.md.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type CountQuotaRequest

type CountQuotaRequest struct {
	Principal string
	Key       string
}

CountQuotaRequest reads the current count for (Principal, Key) without mutating state. Used by inspection paths (admin frontends, debugging); not on the Reserve / Release hot path.

type CountQuotaResponse

type CountQuotaResponse struct {
	Count int
}

CountQuotaResponse carries the current count. Implementations MAY approximate Count for performance under high contention — callers use it for inspection, never for correctness-critical comparisons.

type QuotaStore

type QuotaStore interface {
	ReserveQuota(ctx context.Context, req ReserveQuotaRequest) (ReserveQuotaResponse, error)
	ReleaseQuota(ctx context.Context, req ReleaseQuotaRequest) (ReleaseQuotaResponse, error)
	CountQuota(ctx context.Context, req CountQuotaRequest) (CountQuotaResponse, error)
}

QuotaStore is the storage seam behind a per-(Principal, Key) reservation counter. The shape is generic: Principal identifies who is reserving, Key names the thing being rate-limited (an event type, a tool name, a method — whatever the caller buckets on). The default in-memory implementation (NewInMemoryQuotaStore) keeps counts in a plain map; alternative implementations (Redis, SQL) plug in behind the same interface.

API shape follows the gRPC-style convention pinned in STORAGE_SEAMS.md:

Method(ctx context.Context, req XRequest) (XResponse, error)

ctx threads cancellation, deadlines, and trace context. Application-level state (Granted, Count) lives on the response — error is reserved for storage-layer failures (connection drops, transaction conflicts).

Concurrency contract: the atomicity unit is "compare current count against Max and conditionally increment" — a one-shot compare-and-set that maps cleanly onto Postgres `ON CONFLICT DO UPDATE … WHERE count < $max` and Redis `EVAL` scripts. The in-memory implementation does NOT take internal locks; it assumes the caller serializes access (the events Quota wrapper calls under its own mutex). Implementations shared across callers must take their own locks or use transaction semantics.

func NewInMemoryQuotaStore

func NewInMemoryQuotaStore() QuotaStore

NewInMemoryQuotaStore returns the default in-memory storage implementation — a plain map with no internal locking. Suitable for single-process deployments and the default when no store is configured. Multi-replica deployments plug in a shared backend.

type ReleaseQuotaRequest

type ReleaseQuotaRequest struct {
	Principal string
	Key       string
}

ReleaseQuotaRequest returns one slot for (Principal, Key). The store decrements the count if it is currently > 0, otherwise no-ops (release-at-zero is a benign no-op, not an error). Pair 1:1 with ReserveQuota.

type ReleaseQuotaResponse

type ReleaseQuotaResponse struct{}

ReleaseQuotaResponse is empty today; reserved for future fields.

type ReserveQuotaRequest

type ReserveQuotaRequest struct {
	Principal string
	// Key names the bucket being rate-limited (event type, tool, method, ...).
	Key string
	// Max is the cap the caller read from its config. Must be > 0; callers
	// short-circuit uncapped keys and never call the store with Max <= 0.
	Max int
}

ReserveQuotaRequest asks the store to claim one slot for (Principal, Key) only if the current count is strictly less than Max. Implementations MUST perform the check + increment atomically with respect to concurrent Reserve / Release calls for the same key.

type ReserveQuotaResponse

type ReserveQuotaResponse struct {
	Granted bool
	Count   int
}

ReserveQuotaResponse carries the reservation outcome. Granted is true iff the slot was claimed; Count is the current count after reservation (when Granted) or the count that blocked reservation (when not).

Jump to

Keyboard shortcuts

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