ExRingRing follows Clean Architecture principles with a strict separation of concerns across three layers:
Layer Overview
lib/ex_ring_ring/
├── domain/ # Core business logic
│ ├── entities/ Ring, Node
│ ├── value_objects/ HashConfig, VirtualNode
│ └── services/ HashRing (behaviour), HashAlgorithm (behaviour)
├── application/ # Use cases
│ ├── services/ HashRingService
│ └── use_cases/ CreateRing, AddNodes, RemoveNodes, FindNode, CollectNodes
└── infrastructure/ # Concrete implementations
├── hash_algorithms/ MD5, SHA, SHA256, CRC32, PHash2
└── hash_ring/ Static, Dynamic, BaseDomain Layer
The domain layer contains pure business logic with no external dependencies.
Entities
ExRingRing.Domain.Entities.Ring— The hash ring. A struct containing:impl_module— The behaviour module implementing ring logic (Static or Dynamic)impl_state— The internal state of that implementationconfig— AHashConfigvalue object
ExRingRing.Domain.Entities.Node— A physical node on the ring:key— Used for hashing and identificationdata— Arbitrary user payload (server address, connection info, etc.)weight— Controls virtual node count (0 = phantom/standby)
Value Objects
HashConfig— Immutable configuration holding algorithm, virtual node count, max hash byte size, and computed hash mask.VirtualNode— A point on the ring circle linking a hash value to a physical node.
Domain Services (Behaviours)
ExRingRing.Domain.Services.HashRing— Behaviour defining the contract for ring implementations:make/2,add_nodes/2,remove_nodes/2,get_nodes/1,fold/4,get_non_phantom_node_count/1,hash/2.ExRingRing.Domain.Services.HashAlgorithm— Behaviour defining hash algorithm contract:hash/1,hash_byte_size/0,algorithm_name/0.
Application Layer
Orchestrates domain logic for specific use cases. Each use case is a module with a single execute or call function.
CreateRing— Builds a ring from nodes or keys with configuration optionsAddNodes— Adds one or more nodes to an existing ringRemoveNodes— Removes one or more nodes by keyFindNode— Finds the node responsible for an itemCollectNodes— Collects N distinct nodes for replication
HashRingService is the application service that delegates to use cases. The main ExRingRing module delegates to this service.
Infrastructure Layer
Concrete implementations of domain behaviours.
Hash Ring Implementations
All implementations live under ExRingRing.Infrastructure.HashRing and share a common Base module for state management (node tracking, hash calculation, phantom score).
Static— Uses a sorted tuple of virtual nodes. Fast O(log N) lookups, O(N log N) modifications.Dynamic— Uses a:gb_treesbalanced tree. O(log N) modifications, slightly slower lookups.
Hash Algorithms
| Module | Algorithm | Bytes |
|---|---|---|
MD5 | MD5 | 16 |
SHA | SHA-1 | 20 |
SHA256 | SHA-256 | 32 |
CRC32 | CRC32 | 4 |
PHash2 | Erlang phash2 | 4 |
The HashAlgorithms registry module resolves algorithm names to their implementations.
Data Flow
User Code
│
▼
ExRingRing (public API)
│
▼
HashRingService (application service)
│
├── CreateRing ──────────► HashConfig (config)
│ │
│ ▼
│ Static | Dynamic (impl)
│ │
│ ▼
│ Ring entity
│
├── AddNodes ────────────► Ring.update_state
├── RemoveNodes ─────────► Ring.update_state
├── FindNode ────────────► impl.fold
└── CollectNodes ────────► impl.fold