Documentation
¶
Overview ¶
Package ghost is a distributed, sharded counter cache for short-lived numeric state. It has no application-specific keys or policies.
Callers assign numeric namespaces and choose whether a namespace fails closed or uses local fallback when its owner is unavailable. Local counters expire and disappear at zero. Entry, queue, frame, in-flight and outbound limits protect the process from overload.
Cluster mode assigns virtual buckets to a primary and asynchronous backup. Counter batches use persistent TCP connections and a compact binary format. Operation IDs deduplicate retries. A receipt retains its original owner so settlement releases the same counter after a bucket transfer.
Asynchronous replication is not durable: an abrupt primary failure can lose operations not yet delivered. memberlist supplies discovery and health information only; it is not a consensus protocol.
Use cases ¶
A high-throughput service can use Ghost for temporary reservations that should be visible before an external event confirms them. One namespace may accept local fallback for approximate values, while another requires strict owner access for values that must not be approximated. Confirmed state belongs in a durable store chosen by the application.
Why not always use a database? ¶
A durable counter read or write pays for a network round trip and storage work. A local Ghost operation is only a sharded map access. A remote Ghost operation still pays network latency, but uses a small counter-specific batch protocol and does not wait for a durable write. It is not a database replacement and does not provide the same durability.
Index ¶
- Variables
- func Keys[Key ~uint64](keys []Key) []uint64
- func NodeID(name string) uint64
- type Batch
- type Cluster
- func (c *Cluster) Close() error
- func (c *Cluster) GetBroadcasts(int, int) [][]byte
- func (c *Cluster) LocalState(bool) []byte
- func (c *Cluster) MergeRemoteState([]byte, bool)
- func (c *Cluster) NodeMeta(int) []byte
- func (c *Cluster) NotifyJoin(*memberlist.Node)
- func (c *Cluster) NotifyLeave(*memberlist.Node)
- func (c *Cluster) NotifyMsg([]byte)
- func (c *Cluster) NotifyUpdate(*memberlist.Node)
- func (c *Cluster) String() string
- type ClusterConfig
- type Config
- type FailurePolicy
- type Ghost
- type Namespace
- type NamespaceConfig
- type Operation
- type Reservation
- type Service
- func (s *Service) AcceptPolicy(ns Namespace, primary, backup uint64, epoch uint64, bucket uint32) bool
- func (s *Service) Add(key uint64, delta float64)
- func (s *Service) Addr() string
- func (s *Service) Bucket(key uint64) uint32
- func (s *Service) Close() error
- func (s *Service) Enabled() bool
- func (s *Service) Get(key uint64) float64
- func (s *Service) Load(ns Namespace, keys []uint64, dst []float64) error
- func (s *Service) LoadBatch(ns Namespace, keys []uint64, dst []float64, scratch *Batch) error
- func (s *Service) Reserve(ns Namespace, ops []Operation) ([]Reservation, error)
- func (s *Service) ReserveBatch(ns Namespace, ops []Operation, receipts []Reservation, scratch *Batch) error
- func (s *Service) ReserveInto(ns Namespace, ops []Operation, receipts []Reservation) error
- func (s *Service) SetPeers(peers map[uint64]string)
- func (s *Service) SetPolicy(ns Namespace, primary, backup uint64, epoch uint64, bucket uint32)
- func (s *Service) Settle(reservations []Reservation) error
- func (s *Service) StartCluster(nodes map[uint64]string) error
- func (s *Service) Stats() Stats
- func (s *Service) Sweep(now time.Time, maxPerShard int) int
- func (s *Service) Topology(ns Namespace) []TopologyBucket
- func (s *Service) TransferBucket(ns Namespace, bucket uint32, target uint64, epoch uint64) error
- type Stats
- type TopologyBucket
Constants ¶
This section is empty.
Variables ¶
Functions ¶
Types ¶
type Batch ¶
type Batch struct {
// contains filtered or unexported fields
}
Reservation identifies the exact owner of a hold. Settle uses this route, not the current owner after a rebalance. Batch is reusable routing scratch. It must not be shared concurrently.
type Cluster ¶
type Cluster struct {
// contains filtered or unexported fields
}
func StartClusterService ¶
func StartClusterService(service *Service, cfg ClusterConfig) (*Cluster, error)
func (*Cluster) LocalState ¶
func (*Cluster) MergeRemoteState ¶
func (*Cluster) NotifyJoin ¶
func (c *Cluster) NotifyJoin(*memberlist.Node)
func (*Cluster) NotifyLeave ¶
func (c *Cluster) NotifyLeave(*memberlist.Node)
func (*Cluster) NotifyUpdate ¶
func (c *Cluster) NotifyUpdate(*memberlist.Node)
type ClusterConfig ¶
type FailurePolicy ¶
type FailurePolicy uint8
FailurePolicy controls behavior when the ns owner is unavailable.
const ( FailClosed FailurePolicy = iota LocalFallback )
type Ghost ¶
type Ghost struct {
// contains filtered or unexported fields
}
Ghost is a sharded in-process counter. A negative delta never creates a key.
func (*Ghost) Apply ¶
Apply applies each individual operation. A full store returns ErrFull for new keys without changing them; existing keys remain updateable.
type Namespace ¶
type Namespace uint8
Namespace identifies an independent counter space owned by the caller.
const DefaultNamespace Namespace = 1
DefaultNamespace is used by the simple Add/Get compatibility helpers.
type NamespaceConfig ¶
type NamespaceConfig struct {
MaxEntries int
TTL time.Duration
Failure FailurePolicy
}
NamespaceConfig configures storage and availability for one ns.
type Reservation ¶
type Service ¶
type Service struct {
// contains filtered or unexported fields
}
func NewService ¶
func (*Service) AcceptPolicy ¶
func (*Service) Reserve ¶
func (s *Service) Reserve(ns Namespace, ops []Operation) ([]Reservation, error)
Reserve returns one receipt per input operation. A FailClosed namespace returns an error instead of accepting an unconfirmed reservation.
func (*Service) ReserveBatch ¶
func (s *Service) ReserveBatch(ns Namespace, ops []Operation, receipts []Reservation, scratch *Batch) error
ReserveBatch is ReserveInto with caller-owned routing scratch.
func (*Service) ReserveInto ¶
func (s *Service) ReserveInto(ns Namespace, ops []Operation, receipts []Reservation) error
ReserveInto fills caller-owned receipts without allocating on a local path.
func (*Service) SetPeers ¶
SetPeers updates static peer addresses without changing bucket ownership. Dynamic membership manages this map through Cluster.
func (*Service) Settle ¶
func (s *Service) Settle(reservations []Reservation) error
Settle releases exactly the node/operation Reserve confirmed. An old owner accepts an old epoch release so a transfer never strands the hold.
func (*Service) Topology ¶
func (s *Service) Topology(ns Namespace) []TopologyBucket