How danielvegamyhre/minicache works
Purpose and Entry Points
Minicache is a Go distributed in-memory cache: each node owns an LRU store, while clients route keys with consistent hashing. Nodes dynamically form a cluster, elect a leader, and expose both HTTP and gRPC APIs.
The executable entry point is main.go, which parses node/runtime flags, creates a cache server, starts gRPC and HTTP listeners, registers with the cluster, initiates election/heartbeat monitoring, and handles shutdown. Programmatic server bootstrap is in server/server.go; consumer client entry points are in client/client.go.
Local Storage Layer
Each cache node contains a thread-safe, bounded O(1) LRU cache for key/value storage and eviction:
• lru/lru.go
• server/server.go
This is node-local storage; the system does not describe replication or durable persistence. Therefore a membership/ring change can remap future requests but does not imply data migration.
Client Routing and Membership Watcher
The client owns the consistent-hash ring and selects a target node for every Get/Put. It initializes from configured genesis nodes, obtains current cluster state from the leader, and watches for membership changes to add/remove ring members:
• client/client.go
• ring/ring.go
• configs/nodes-local-with-mTLS.json
This is the principal request-routing boundary: client-to-node traffic reaches only the node selected for a key, using either HTTP or gRPC.
Node Service Interfaces
A cache server hosts both public request protocols and the inter-node control RPCs used for registration, state propagation, heartbeat, and election:
• server/server.go
• pb/cache_service.proto
• pb/cache_service_grpc.pb.go
Protocol contracts are defined in protobuf and generated Go bindings under pb/. HTTP is a parallel interface on the server rather than a separate application tier.
Cluster Membership and Discovery
Nodes begin from a JSON genesis-node configuration. A dynamically started node contacts configured initial nodes to register; receiving nodes update their in-memory membership and propagate the updated list through the cluster:
• server/cluster.go
• node/node.go
• configs/nodes-docker-with-mTLS.json
Genesis configuration is a bootstrap dependency, not a fixed cluster-size limit: once a reachable genesis node accepts registration, arbitrary additional nodes can join.
Leader Election and Failure Handling
The cluster uses the Bully algorithm to elect a leader. The leader tracks node reachability through heartbeats and provides active membership to clients; followers monitor leader heartbeat and trigger a new election on failure:
• server/election.go
• server/cluster.go
• server/server.go
Control-plane availability depends on successful election and leader monitoring. Client rings are eventually refreshed from the leader’s cluster view.
Runtime, Deployment, and Security
The primary runtime is Go with concurrent goroutines for serving, monitoring, and shutdown coordination. Nodes can run locally or as Docker Compose services:
• Dockerfile.server
• docker-compose.yml
• Dockerfile.client
TLS can be disabled, enabled, or configured for mutual TLS between clients/nodes and servers. Certificates and SAN generation inputs are repository-managed:
• certs/gen.sh
• certs/client-ext.cnf
• certs/server-ext.cnf
Main entry points: cluster.go Membership manager · server.go Cache server · client.go Cache client · docker-compose.yml Docker Compose
Components 16
Client Routing
- Cache client · Routes each Get/Put to its selected node.
client/client.go - Consistent hash ring · Maps keys to active cache nodes.
ring/ring.go - Local genesis nodes
configs/nodes-local-with-mTLS.json
Cache Node
- Cache server · Hosts cache APIs and node lifecycle.
server/server.go - Local LRU store · Thread-safe bounded O(1) key/value storage.
lru/lru.go - Protocol contracts · Defines cache and cluster RPCs.
pb/cache_service.proto - gRPC bindings
pb/cache_service_grpc.pb.go
Cluster Control Plane
- Membership manager · Registers nodes and propagates active membership.
server/cluster.go - Node model
node/node.go - Bully election · Elects a leader and monitors leader failure.
server/election.go
Runtime & Deployment
- Node executable · Parses flags and starts node services.
main.go - Docker genesis nodes
configs/nodes-docker-with-mTLS.json - Docker Compose · Runs multi-node local deployment.
docker-compose.yml - Server image
Dockerfile.server - Client image
Dockerfile.client - TLS certificate setup · Generates certificates and SAN inputs for TLS or mTLS.
certs/gen.sh
Connections 18
- Node executable → Cache server: bootstraps
- Cache server → Local LRU store: reads and writes
- Protocol contracts → gRPC bindings: generates
- gRPC bindings → Cache server: implements gRPC API
- Cache client → Consistent hash ring: selects node by key
- Cache client → Cache server: Get/Put via HTTP or gRPC · Requests go only to the selected node.
- Local genesis nodes → Cache client: initializes discovery
- Docker genesis nodes → Membership manager: supplies initial contacts
- Cache server → Membership manager: registers and serves control RPCs
- Membership manager → Node model: tracks members
- Membership manager → Bully election: membership for election
- Bully election → Membership manager: leader heartbeats and failure detection
- Membership manager → Cache client: leader provides state updates · Client eventually refreshes ring membership.
- Membership manager → Consistent hash ring: add/remove members
- Docker Compose → Server image: builds server nodes
- Docker Compose → Client image: builds client runtime
- TLS certificate setup → Cache server: secures client and node traffic
- TLS certificate setup → Cache client: enables TLS or mTLS