Documentation
¶
Overview ¶
Package memcached is celeris's native Memcached driver, speaking the text and binary wire protocols directly on the celeris event loop.
NewClient returns a Client, a pooled single-node handle whose typed API covers storage (Set, Add, Replace, Append, Prepend, CAS and their *Bytes variants), retrieval (Get, GetBytes, GetMulti, GetMultiBytes, Gets for the CAS token), arithmetic (Incr, Decr), key ops (Delete, Touch), and server ops (Flush, FlushAfter, Stats, Version, Ping). ClusterClient, built with NewClusterClient, mirrors the same command surface but shards keys across several nodes via a libmemcached-compatible ketama ring with passive failure detection and background health probing.
Behavior is tuned with Option values passed to NewClient: WithProtocol (ProtocolText default, ProtocolBinary opt-in), WithEngine to colocate socket I/O on a celeris.Server's worker threads, WithMaxOpen, WithMaxIdlePerWorker, WithTimeout, WithDialTimeout, WithMaxLifetime, WithMaxIdleTime, and WithHealthCheckInterval. Addresses may carry an optional "memcache://" or "memcached://" scheme prefix.
Misses and precondition failures surface as the sentinels ErrCacheMiss, ErrNotStored, and ErrCASConflict; other client-side faults as ErrClosed, ErrProtocol, ErrPoolExhausted, ErrMalformedKey, ErrInvalidCAS, and (for clusters) ErrNoNodes. Other server-side replies arrive as *MemcachedError.
TLS, SASL authentication, and server-side compression are not supported; deploy over a trusted network and compress large values client-side. ClusterClient topology is static — to add or remove nodes, rebuild the client or front the fleet with a proxy such as mcrouter.
client, err := memcached.NewClient("localhost:11211")
if err != nil {
log.Fatal(err)
}
defer client.Close()
if err := client.Set(ctx, "key", "value", time.Minute); err != nil {
log.Fatal(err)
}
v, err := client.Get(ctx, "key")
Documentation ¶
Full guides and examples: https://goceleris.dev/docs/data-stores
Index ¶
- Variables
- func WithWorker(ctx context.Context, workerID int) context.Context
- type CASItem
- type Client
- func (c *Client) Add(ctx context.Context, key string, value any, ttl time.Duration) error
- func (c *Client) AddBytes(ctx context.Context, key string, value []byte, ttl time.Duration) error
- func (c *Client) Append(ctx context.Context, key, value string) error
- func (c *Client) CAS(ctx context.Context, key string, value any, casID uint64, ttl time.Duration) (bool, error)
- func (c *Client) CASBytes(ctx context.Context, key string, value []byte, casID uint64, ttl time.Duration) (bool, error)
- func (c *Client) Close() error
- func (c *Client) Decr(ctx context.Context, key string, delta uint64) (uint64, error)
- func (c *Client) Delete(ctx context.Context, key string) error
- func (c *Client) Flush(ctx context.Context) error
- func (c *Client) FlushAfter(ctx context.Context, delay time.Duration) error
- func (c *Client) Get(ctx context.Context, key string) (string, error)
- func (c *Client) GetBytes(ctx context.Context, key string) ([]byte, error)
- func (c *Client) GetMulti(ctx context.Context, keys ...string) (map[string]string, error)
- func (c *Client) GetMultiBytes(ctx context.Context, keys ...string) (map[string][]byte, error)
- func (c *Client) Gets(ctx context.Context, key string) (CASItem, error)
- func (c *Client) IdleConnWorkers() []int
- func (c *Client) Incr(ctx context.Context, key string, delta uint64) (uint64, error)
- func (c *Client) Ping(ctx context.Context) error
- func (c *Client) PoolStats() async.PoolStats
- func (c *Client) Prepend(ctx context.Context, key, value string) error
- func (c *Client) Protocol() Protocol
- func (c *Client) Replace(ctx context.Context, key string, value any, ttl time.Duration) error
- func (c *Client) ReplaceBytes(ctx context.Context, key string, value []byte, ttl time.Duration) error
- func (c *Client) Set(ctx context.Context, key string, value any, ttl time.Duration) error
- func (c *Client) SetBytes(ctx context.Context, key string, value []byte, ttl time.Duration) error
- func (c *Client) Stats(ctx context.Context) (map[string]string, error)
- func (c *Client) Touch(ctx context.Context, key string, ttl time.Duration) error
- func (c *Client) Version(ctx context.Context) (string, error)
- type ClusterClient
- func (c *ClusterClient) Add(ctx context.Context, key string, value any, ttl time.Duration) error
- func (c *ClusterClient) AddBytes(ctx context.Context, key string, value []byte, ttl time.Duration) error
- func (c *ClusterClient) Addrs() []string
- func (c *ClusterClient) Append(ctx context.Context, key, value string) error
- func (c *ClusterClient) CAS(ctx context.Context, key string, value any, casID uint64, ttl time.Duration) (bool, error)
- func (c *ClusterClient) CASBytes(ctx context.Context, key string, value []byte, casID uint64, ttl time.Duration) (bool, error)
- func (c *ClusterClient) Close() error
- func (c *ClusterClient) Decr(ctx context.Context, key string, delta uint64) (uint64, error)
- func (c *ClusterClient) Delete(ctx context.Context, key string) error
- func (c *ClusterClient) Flush(ctx context.Context) error
- func (c *ClusterClient) FlushAfter(ctx context.Context, delay time.Duration) error
- func (c *ClusterClient) Get(ctx context.Context, key string) (string, error)
- func (c *ClusterClient) GetBytes(ctx context.Context, key string) ([]byte, error)
- func (c *ClusterClient) GetMulti(ctx context.Context, keys ...string) (map[string]string, error)
- func (c *ClusterClient) GetMultiBytes(ctx context.Context, keys ...string) (map[string][]byte, error)
- func (c *ClusterClient) Gets(ctx context.Context, key string) (CASItem, error)
- func (c *ClusterClient) Incr(ctx context.Context, key string, delta uint64) (uint64, error)
- func (c *ClusterClient) NodeFor(key string) string
- func (c *ClusterClient) NodeHealth() map[string]bool
- func (c *ClusterClient) NodeStatsMap() map[string]NodeStats
- func (c *ClusterClient) Ping(ctx context.Context) error
- func (c *ClusterClient) Prepend(ctx context.Context, key, value string) error
- func (c *ClusterClient) Replace(ctx context.Context, key string, value any, ttl time.Duration) error
- func (c *ClusterClient) ReplaceBytes(ctx context.Context, key string, value []byte, ttl time.Duration) error
- func (c *ClusterClient) Set(ctx context.Context, key string, value any, ttl time.Duration) error
- func (c *ClusterClient) SetBytes(ctx context.Context, key string, value []byte, ttl time.Duration) error
- func (c *ClusterClient) Stats(ctx context.Context) (map[string]map[string]string, error)
- func (c *ClusterClient) Touch(ctx context.Context, key string, ttl time.Duration) error
- func (c *ClusterClient) Version(ctx context.Context) (map[string]string, error)
- type ClusterConfig
- type Config
- type MemcachedError
- type NodeStats
- type Option
- func WithDialTimeout(d time.Duration) Option
- func WithEngine(sp eventloop.ServerProvider) Option
- func WithHealthCheckInterval(d time.Duration) Option
- func WithMaxIdlePerWorker(n int) Option
- func WithMaxIdleTime(d time.Duration) Option
- func WithMaxLifetime(d time.Duration) Option
- func WithMaxOpen(n int) Option
- func WithProtocol(p Protocol) Option
- func WithTimeout(d time.Duration) Option
- type Protocol
Examples ¶
Constants ¶
This section is empty.
Variables ¶
var ErrCASConflict = errors.New("celeris-memcached: CAS conflict")
ErrCASConflict is returned by CAS when the server's stored CAS token no longer matches the caller-supplied one (concurrent modification).
var ErrCacheMiss = errors.New("celeris-memcached: cache miss")
ErrCacheMiss is returned by Get/GetBytes/Touch/CAS when the requested key does not exist on the server. Matches the "NOT_FOUND\r\n" text reply and the StatusKeyNotFound binary status.
var ErrClosed = errors.New("celeris-memcached: client closed")
ErrClosed is returned when a command is issued against a closed Client.
var ErrInvalidCAS = errors.New("celeris-memcached: CAS token must be non-zero (did you call Gets first?)")
ErrInvalidCAS is returned by Client.CAS when casID=0 is passed. Memcached treats a CAS value of 0 as "don't check", which would silently turn the CAS call into an unconditional Set. A legitimate CAS token returned by Gets is never 0, so casID=0 always indicates a caller bug (forgot to call Gets first, copied the token wrong, etc.). Fail loudly rather than silently degrade.
var ErrMalformedKey = errors.New("celeris-memcached: malformed key")
ErrMalformedKey is returned before wire contact when a key violates the text-protocol constraints (empty, too long, or contains whitespace/control bytes). The binary protocol has no such restrictions, but the client rejects the same set uniformly so a caller can switch dialects without changing their key-hygiene assumptions.
var ErrNoNodes = errors.New("celeris-memcached: cluster has no nodes")
ErrNoNodes is returned when a ClusterClient has no live nodes configured (typically because every ClusterConfig.Addrs entry was empty or all seed dials failed).
var ErrNotStored = errors.New("celeris-memcached: item not stored")
ErrNotStored is returned by Add/Replace/Append/Prepend when the server declines to store the value — Add finds the key already present, Replace / Append / Prepend find it missing, or the Append/Prepend target is a counter rather than a string.
var ErrPoolExhausted = errors.New("celeris-memcached: pool exhausted")
ErrPoolExhausted is returned when no connection is available and none can be dialed within MaxOpen.
var ErrProtocol = errors.New("celeris-memcached: protocol error")
ErrProtocol is returned when the server reply cannot be decoded.
Functions ¶
Types ¶
type CASItem ¶
CASItem is the key + value + CAS token triple returned by Client.Gets.
type Client ¶
type Client struct {
// contains filtered or unexported fields
}
Client is the high-level handle users interact with. It owns a pool of connections and hands out per-command round trips.
func NewClient ¶
NewClient dials a pool at addr using the given options. Connections are established lazily on first command.
When opened without WithEngine(srv), the client uses direct net.TCPConn I/O on the caller's goroutine — no event-loop indirection. This matches github.com/bradfitz/gomemcache in shape (Go's netpoll parks the goroutine on EPOLLIN transparently) and closes the foreign-HTTP gap vs gomc on the MSR1 bench from ~17% to within noise.
When opened WithEngine, the mini-loop sync path (WriteAndPollBusy) is used so DB I/O colocates with the celeris HTTP engine's worker.
addr may optionally include a "memcache://" or "memcached://" scheme prefix; the prefix is stripped and the remaining "host:port" is used verbatim. TLS is not supported in v1.4.0.
Example ¶
ExampleNewClient shows the basic Set/Get loop. The client is lazy: the first command triggers the TCP dial.
package main
import (
"context"
"fmt"
"log"
"time"
"github.com/goceleris/celeris/driver/memcached"
)
func main() {
client, err := memcached.NewClient("localhost:11211")
if err != nil {
log.Fatal(err)
}
defer func() { _ = client.Close() }()
ctx, cancel := context.WithTimeout(context.Background(), 2*time.Second)
defer cancel()
if err := client.Set(ctx, "greeting", "hello, world", time.Minute); err != nil {
log.Fatal(err)
}
v, err := client.Get(ctx, "greeting")
if err != nil {
log.Fatal(err)
}
fmt.Println(v)
}
Output:
func (*Client) Add ¶
Add stores value at key only if the key does not already exist. Returns ErrNotStored when the key is present.
func (*Client) AddBytes ¶ added in v1.4.1
AddBytes is the allocation-lean variant of Client.Add. See Client.SetBytes.
func (*Client) Append ¶
Append appends value to the existing value at key. Returns ErrNotStored when the key is missing.
func (*Client) CAS ¶
func (c *Client) CAS(ctx context.Context, key string, value any, casID uint64, ttl time.Duration) (bool, error)
CAS performs a compare-and-swap update: the store succeeds only if the server's current CAS token matches casID. Returns (false, ErrCASConflict) on mismatch, (false, ErrCacheMiss) if the key is missing, and (true, nil) on success.
Example ¶
ExampleClient_CAS performs an optimistic read-modify-write.
package main
import (
"context"
"errors"
"fmt"
"log"
"time"
"github.com/goceleris/celeris/driver/memcached"
)
func main() {
client, _ := memcached.NewClient("localhost:11211")
defer func() { _ = client.Close() }()
ctx := context.Background()
item, err := client.Gets(ctx, "counter")
if err != nil {
log.Fatal(err)
}
newValue := string(item.Value) + "!"
ok, err := client.CAS(ctx, "counter", newValue, item.CAS, time.Hour)
if err != nil && !errors.Is(err, memcached.ErrCASConflict) {
log.Fatal(err)
}
fmt.Println("stored:", ok)
}
Output:
func (*Client) CASBytes ¶ added in v1.4.1
func (c *Client) CASBytes(ctx context.Context, key string, value []byte, casID uint64, ttl time.Duration) (bool, error)
CASBytes is the allocation-lean variant of Client.CAS. Skips the `any` boxing + asBytes type switch for callers that already have []byte.
func (*Client) Decr ¶
Decr atomically decrements the integer value at key by delta and returns the new value. The memcached server clamps the result at 0 (it does not wrap to MAX_UINT).
func (*Client) Delete ¶
Delete removes key from the cache. Returns ErrCacheMiss if the key did not exist.
func (*Client) FlushAfter ¶
FlushAfter schedules a flush to take effect after delay. Implemented as a relative exptime argument to flush_all / OpFlush extras.
func (*Client) Get ¶
Get fetches the string value at key. Returns ErrCacheMiss when the key is missing.
Example ¶
ExampleClient_Get illustrates handling the cache-miss sentinel.
package main
import (
"context"
"errors"
"fmt"
"log"
"github.com/goceleris/celeris/driver/memcached"
)
func main() {
client, _ := memcached.NewClient("localhost:11211")
defer func() { _ = client.Close() }()
ctx := context.Background()
v, err := client.Get(ctx, "session:42")
switch {
case errors.Is(err, memcached.ErrCacheMiss):
fmt.Println("miss")
case err != nil:
log.Fatal(err)
default:
fmt.Println(v)
}
}
Output:
func (*Client) GetBytes ¶
GetBytes is the []byte variant of Client.Get. The returned slice is a fresh copy that the caller owns.
func (*Client) GetMulti ¶
GetMulti fetches multiple keys in one round trip. Missing keys are omitted from the returned map. Each value is a fresh copy owned by the caller.
Example ¶
ExampleClient_GetMulti fetches several keys in one round trip (text protocol) or sequential GETs (binary protocol).
package main
import (
"context"
"fmt"
"log"
"github.com/goceleris/celeris/driver/memcached"
)
func main() {
client, _ := memcached.NewClient("localhost:11211")
defer func() { _ = client.Close() }()
ctx := context.Background()
out, err := client.GetMulti(ctx, "user:1", "user:2", "user:3")
if err != nil {
log.Fatal(err)
}
for k, v := range out {
fmt.Println(k, "=", v)
}
}
Output:
func (*Client) GetMultiBytes ¶
GetMultiBytes is the []byte variant of Client.GetMulti.
func (*Client) Gets ¶
Gets fetches a value along with its CAS token. The returned item's CAS field can be passed to Client.CAS to perform an atomic update.
func (*Client) IdleConnWorkers ¶
IdleConnWorkers returns the Worker() IDs of every currently-idle connection. Intended for tests and introspection asserting that per-CPU affinity is actually honored by the dial path.
func (*Client) Incr ¶
Incr atomically increments the integer value at key by delta and returns the new value. The server returns ErrCacheMiss if the key is missing (use Set first to initialize) or a MemcachedError if the existing value is not a decimal integer.
func (*Client) Ping ¶
Ping issues a VERSION (cheaper than a full stats call) and discards the reply. Useful as a liveness probe.
func (*Client) PoolStats ¶
PoolStats returns driver pool occupancy. Named PoolStats rather than Stats so it doesn't collide with the server-side Client.Stats command that queries the memcached server's own statistics map.
func (*Client) Prepend ¶
Prepend prepends value to the existing value at key. Returns ErrNotStored when the key is missing.
func (*Client) Replace ¶
Replace stores value at key only if the key already exists. Returns ErrNotStored when the key is missing.
func (*Client) ReplaceBytes ¶ added in v1.4.1
func (c *Client) ReplaceBytes(ctx context.Context, key string, value []byte, ttl time.Duration) error
ReplaceBytes is the allocation-lean variant of Client.Replace.
func (*Client) Set ¶
Set stores value at key, overwriting any existing value.
Example ¶
ExampleClient_Set stores a value with a 10-minute TTL.
package main
import (
"context"
"log"
"time"
"github.com/goceleris/celeris/driver/memcached"
)
func main() {
client, _ := memcached.NewClient("localhost:11211")
defer func() { _ = client.Close() }()
ctx := context.Background()
if err := client.Set(ctx, "counter", "0", 10*time.Minute); err != nil {
log.Fatal(err)
}
}
Output:
func (*Client) SetBytes ¶ added in v1.4.1
SetBytes is the allocation-lean variant of Client.Set for callers that already have the value as bytes. Skips the `any` interface boxing and the asBytes type switch — see the ratelimit/memcachedstore bench gap.
func (*Client) Touch ¶
Touch updates the expiration of key without fetching the value. Returns ErrCacheMiss if the key is missing.
type ClusterClient ¶
type ClusterClient struct {
// contains filtered or unexported fields
}
ClusterClient talks to a fixed set of memcached servers, routing each key through a consistent-hash ring so addition/removal of a single server only re-homes ~1/N of the key space. Memcached has no cluster protocol: topology is strictly static from the client's point of view (add a node → build a new ClusterClient).
The ring uses the ketama algorithm: each node owns virtualNodesPerWeight × weight ring points, placed at MD5("addr-vnode") boundaries (4 points per 16-byte digest). Lookup hashes the user key with the same MD5-first-four-little-endian form so celeris is drop-in compatible with libmemcached and any ketama-adjacent client (dalli, gomemcache/ketama, mcrouter, twemproxy): a mixed-client fleet all agree on which node owns which key.
func NewClusterClient ¶
func NewClusterClient(cfg ClusterConfig) (*ClusterClient, error)
NewClusterClient builds a ring across the given memcached endpoints. Each address becomes its own Client with its own pool. If any seed address fails to dial the whole construction is aborted and every already-opened node is closed, so no goroutine or FD leaks on partial failure.
Topology is static for the lifetime of the client: there is no background refresh loop. Memcached nodes do not gossip. To add or remove a node, tear the client down and build a new one.
func (*ClusterClient) AddBytes ¶ added in v1.4.1
func (c *ClusterClient) AddBytes(ctx context.Context, key string, value []byte, ttl time.Duration) error
AddBytes is the allocation-lean variant of ClusterClient.Add.
func (*ClusterClient) Addrs ¶
func (c *ClusterClient) Addrs() []string
Addrs returns the configured address list in the original Addrs order. Useful for diagnostics and tests; the returned slice is a copy.
func (*ClusterClient) Append ¶
func (c *ClusterClient) Append(ctx context.Context, key, value string) error
Append forwards to the ring owner of key.
func (*ClusterClient) CAS ¶
func (c *ClusterClient) CAS(ctx context.Context, key string, value any, casID uint64, ttl time.Duration) (bool, error)
CAS forwards to the ring owner of key.
func (*ClusterClient) CASBytes ¶ added in v1.4.1
func (c *ClusterClient) CASBytes(ctx context.Context, key string, value []byte, casID uint64, ttl time.Duration) (bool, error)
CASBytes is the allocation-lean variant of ClusterClient.CAS.
func (*ClusterClient) Close ¶
func (c *ClusterClient) Close() error
Close tears down every node's connection pool. Safe to call multiple times.
func (*ClusterClient) Delete ¶
func (c *ClusterClient) Delete(ctx context.Context, key string) error
Delete forwards to the ring owner of key.
func (*ClusterClient) Flush ¶
func (c *ClusterClient) Flush(ctx context.Context) error
Flush fans a Flush to every node in parallel. Returns the first error encountered; on success the whole cluster has been wiped.
func (*ClusterClient) FlushAfter ¶
FlushAfter schedules a delayed flush on every node. Each node starts its own local timer; the actual flushes will not be perfectly synchronized across nodes (memcached has no cluster-wide clock).
func (*ClusterClient) GetMulti ¶
GetMulti partitions keys by their ring owner, fans out one GetMulti per node in parallel, and merges the per-node results into a single map. If any sub-call returns an error the first such error is returned; partial results from the other nodes are discarded — same failure semantics as the single-server Client.GetMulti.
Missing keys are omitted (standard memcached semantics). The output map is owned by the caller.
func (*ClusterClient) GetMultiBytes ¶
func (c *ClusterClient) GetMultiBytes(ctx context.Context, keys ...string) (map[string][]byte, error)
GetMultiBytes is the []byte variant of ClusterClient.GetMulti.
func (*ClusterClient) NodeFor ¶
func (c *ClusterClient) NodeFor(key string) string
NodeFor returns the addr of the node that key maps to. Exposed as a stable API so callers can pre-compute routing, emit debug output, or shard keyed work outside the driver (e.g. "rebalance everything on node X before draining it"). Returns "" if the client has no nodes (closed or empty).
func (*ClusterClient) NodeHealth ¶ added in v1.4.1
func (c *ClusterClient) NodeHealth() map[string]bool
NodeHealth returns a snapshot of each node's failing flag keyed by address. Callers hold a copy; the map is safe to mutate.
func (*ClusterClient) NodeStatsMap ¶ added in v1.4.1
func (c *ClusterClient) NodeStatsMap() map[string]NodeStats
NodeStatsMap returns a snapshot of every node's NodeStats. Useful for dashboards and readiness probes that want to distinguish "down" nodes from healthy ones without peeking at atomics directly.
func (*ClusterClient) Ping ¶
func (c *ClusterClient) Ping(ctx context.Context) error
Ping pings every node in parallel. Returns the first error encountered.
func (*ClusterClient) Prepend ¶
func (c *ClusterClient) Prepend(ctx context.Context, key, value string) error
Prepend forwards to the ring owner of key.
func (*ClusterClient) Replace ¶
func (c *ClusterClient) Replace(ctx context.Context, key string, value any, ttl time.Duration) error
Replace forwards to the ring owner of key.
func (*ClusterClient) ReplaceBytes ¶ added in v1.4.1
func (c *ClusterClient) ReplaceBytes(ctx context.Context, key string, value []byte, ttl time.Duration) error
ReplaceBytes is the allocation-lean variant of ClusterClient.Replace.
func (*ClusterClient) SetBytes ¶ added in v1.4.1
func (c *ClusterClient) SetBytes(ctx context.Context, key string, value []byte, ttl time.Duration) error
SetBytes is the allocation-lean variant of ClusterClient.Set.
type ClusterConfig ¶
type ClusterConfig struct {
// Addrs is the list of memcached endpoints in "host:port" form to shard
// across. At least one address is required.
Addrs []string
// Weights optionally assigns a relative weight to each address, indexed
// by position in Addrs. A nil or empty slice means equal weight. A node
// with weight 2 owns twice as many ring points as a node with weight 1.
// Length must either be 0 or exactly equal to len(Addrs).
Weights []uint32
// Protocol selects the wire dialect used by every node client. Same
// semantics as [Config.Protocol]; default text.
Protocol Protocol
// MaxOpen caps the per-node connection pool. Same semantics as
// [Config.MaxOpen]; zero means NumWorkers * 4 per node.
MaxOpen int
// Timeout is the advisory per-op deadline forwarded to each node client.
Timeout time.Duration
// DialTimeout is the TCP dial timeout forwarded to each node client.
DialTimeout time.Duration
// Engine hooks the cluster into a running celeris.Server's event loop.
// If nil, a standalone loop is resolved for each node client.
Engine eventloop.ServerProvider
// FailureThreshold is the number of consecutive infrastructure-level
// errors (dial failures, I/O errors, protocol corruption) that must
// be observed on a node before it is marked as failing and skipped
// by pickNode. Default: 2. A single transient blip must not reroute
// traffic; two consecutive errors is the libmemcached default.
//
// Protocol errors (ErrCacheMiss, ErrNotStored, ErrCASConflict,
// *MemcachedError) do NOT count toward the threshold — they are
// server responses to valid requests.
FailureThreshold uint32
// HealthProbeInterval is how often a background goroutine probes
// nodes marked as failing and clears the flag on success. Default:
// 5 seconds. Set to 0 to disable the background probe (passive
// healing on successful ops still applies).
HealthProbeInterval time.Duration
// MaxFailoverHops bounds the clockwise walk when the ring-assigned
// node is failing. Default: len(Addrs). Successor scans are O(n)
// in the number of nodes; this cap exists purely as a safety net
// against pathological inputs.
MaxFailoverHops int
}
ClusterConfig configures a multi-server Memcached client driven by a ketama consistent-hash ring. Memcached servers do not gossip topology, so the Addrs list is authoritative and static for the lifetime of the client.
type Config ¶
type Config struct {
// Addr is the TCP endpoint in "host:port" form.
Addr string
// Protocol selects text vs binary at dial time. Default is text.
Protocol Protocol
// MaxOpen is the total connection cap across all workers. Zero means
// NumWorkers * 4.
MaxOpen int
// MaxIdlePerWorker bounds each worker's idle list; default 2.
MaxIdlePerWorker int
// DialTimeout is the TCP dial timeout; default 5s.
DialTimeout time.Duration
// Timeout is the advisory per-op deadline used when the caller's context
// carries no deadline. Default 3s.
Timeout time.Duration
// MaxLifetime is the max age of a pooled conn; default 30m.
MaxLifetime time.Duration
// MaxIdleTime is the max idle duration before eviction; default 5m.
MaxIdleTime time.Duration
// HealthCheckInterval is the background health-check sweep interval.
// Default 30s; a negative value disables the sweep.
HealthCheckInterval time.Duration
// Engine hooks the driver into a running celeris.Server's event loop.
// If nil, a standalone loop is resolved on [NewClient].
Engine eventloop.ServerProvider
}
Config controls a Client. Use Option functions to set fields; the zero value is not directly usable.
type MemcachedError ¶
MemcachedError wraps a server-side error reply.
For text protocol it carries the Kind tag ("ERROR", "CLIENT_ERROR", "SERVER_ERROR") and the accompanying message. For binary protocol it carries the raw Status code and the response body (usually a human message).
func (*MemcachedError) Error ¶
func (e *MemcachedError) Error() string
Error implements the error interface.
type NodeStats ¶ added in v1.4.1
type NodeStats struct {
Failing bool
ConsecFails int32
LastFailAt time.Time // zero when the node has never been marked failing
}
NodeStats captures the health metadata the cluster tracks per node. Used by diagnostic/monitoring code via [ClusterClient.NodeStats].
type Option ¶
type Option func(*Config)
Option mutates a Config during NewClient.
func WithDialTimeout ¶
WithDialTimeout sets the TCP dial timeout.
func WithEngine ¶
func WithEngine(sp eventloop.ServerProvider) Option
WithEngine hooks the driver into a celeris.Server's event loop.
func WithHealthCheckInterval ¶
WithHealthCheckInterval sets the background health-check sweep interval. Default 30s; pass a negative value to disable.
func WithMaxIdlePerWorker ¶
WithMaxIdlePerWorker bounds each worker's idle list.
func WithMaxIdleTime ¶
WithMaxIdleTime sets the pooled conn idle eviction.
func WithMaxLifetime ¶
WithMaxLifetime sets the pooled conn lifetime.
func WithProtocol ¶
WithProtocol selects the wire dialect. Default is text.
func WithTimeout ¶
WithTimeout sets the default per-op deadline when the caller's ctx has none.
type Protocol ¶
type Protocol uint8
Protocol selects the memcached wire dialect spoken by a Client. Every memcached deployment supports text; binary was deprecated upstream but remains broadly available and is sometimes preferred for its CAS semantics and fixed-size packet framing. Text is the default.