mirror of
https://github.com/EchoVault/SugarDB.git
synced 2025-10-24 00:14:08 +08:00
Re-enabled cluster nodes in docker-compose.yml.
Created flow to forward key deletion command from non-leader node to leader node. Created flow for propagating key deletion accross the entire cluster to maintain consistency of the deleted keys.
This commit is contained in:
@@ -47,216 +47,216 @@ services:
|
||||
networks:
|
||||
- testnet
|
||||
|
||||
# cluster_node_1:
|
||||
# container_name: cluster_node_1
|
||||
# build:
|
||||
# context: .
|
||||
# dockerfile: Dockerfile.dev
|
||||
# environment:
|
||||
# - PORT=7480
|
||||
# - RAFT_PORT=8000
|
||||
# - ML_PORT=7946
|
||||
# - KEY=/generic/ssl/certs/echovault/server1.key
|
||||
# - CERT=/generic/ssl/certs/echovault/server1.crt
|
||||
# - SERVER_ID=1
|
||||
# - DATA_DIR=/var/lib/echovault
|
||||
# - IN_MEMORY=false
|
||||
# - TLS=false
|
||||
# - MTLS=false
|
||||
# - BOOTSTRAP_CLUSTER=true
|
||||
# - ACL_CONFIG=/generic/config/echovault/acl.yml
|
||||
# - REQUIRE_PASS=false
|
||||
# - FORWARD_COMMAND=true
|
||||
# - SNAPSHOT_THRESHOLD=1000
|
||||
# - SNAPSHOT_INTERVAL=5m30s
|
||||
# - RESTORE_SNAPSHOT=false
|
||||
# - RESTORE_AOF=false
|
||||
# - AOF_SYNC_STRATEGY=everysec
|
||||
# - MAX_MEMORY=2000kb
|
||||
# - EVICTION_POLICY=allkeys-lfu
|
||||
# # List of server cert/key pairs
|
||||
# - CERT_KEY_PAIR_1=/generic/ssl/certs/echovault/server/server1.crt,/generic/ssl/certs/echovault/server/server1.key
|
||||
# - CERT_KEY_PAIR_2=/generic/ssl/certs/echovault/server/server2.crt,/generic/ssl/certs/echovault/server/server2.key
|
||||
# # List of client certificate authorities
|
||||
# - CLIENT_CA_1=/generic/ssl/certs/echovault/client/rootCA.crt
|
||||
# ports:
|
||||
# - "7481:7480"
|
||||
# - "7945:7946"
|
||||
# - "8000:8000"
|
||||
# volumes:
|
||||
# - ./config/acl.yml:/generic/config/echovault/acl.yml
|
||||
# - ./volumes/cluster_node_1:/var/lib/echovault
|
||||
# networks:
|
||||
# - testnet
|
||||
#
|
||||
# cluster_node_2:
|
||||
# container_name: cluster_node_2
|
||||
# build:
|
||||
# context: .
|
||||
# dockerfile: Dockerfile.dev
|
||||
# environment:
|
||||
# - PORT=7480
|
||||
# - RAFT_PORT=8000
|
||||
# - ML_PORT=7946
|
||||
# - KEY=/generic/ssl/certs/echovault/server1.key
|
||||
# - CERT=/generic/ssl/certs/echovault/server1.crt
|
||||
# - SERVER_ID=2
|
||||
# - JOIN_ADDR=cluster_node_1:7946
|
||||
# - DATA_DIR=/var/lib/echovault
|
||||
# - IN_MEMORY=false
|
||||
# - TLS=false
|
||||
# - MTLS=false
|
||||
# - BOOTSTRAP_CLUSTER=false
|
||||
# - ACL_CONFIG=/generic/config/echovault/acl.yml
|
||||
# - REQUIRE_PASS=false
|
||||
# - FORWARD_COMMAND=true
|
||||
# - SNAPSHOT_THRESHOLD=1000
|
||||
# - SNAPSHOT_INTERVAL=5m30s
|
||||
# - RESTORE_SNAPSHOT=false
|
||||
# - RESTORE_AOF=false
|
||||
# - AOF_SYNC_STRATEGY=everysec
|
||||
# - MAX_MEMORY=2000kb
|
||||
# - EVICTION_POLICY=allkeys-lfu
|
||||
# # List of server cert/key pairs
|
||||
# - CERT_KEY_PAIR_1=/generic/ssl/certs/echovault/server/server1.crt,/generic/ssl/certs/echovault/server/server1.key
|
||||
# - CERT_KEY_PAIR_2=/generic/ssl/certs/echovault/server/server2.crt,/generic/ssl/certs/echovault/server/server2.key
|
||||
# # List of client certificate authorities
|
||||
# - CLIENT_CA_1=/generic/ssl/certs/echovault/client/rootCA.crt
|
||||
# ports:
|
||||
# - "7482:7480"
|
||||
# - "7947:7946"
|
||||
# - "8001:8000"
|
||||
# volumes:
|
||||
# - ./config/acl.yml:/generic/config/echovault/acl.yml
|
||||
# - ./volumes/cluster_node_2:/var/lib/echovault
|
||||
# networks:
|
||||
# - testnet
|
||||
#
|
||||
# cluster_node_3:
|
||||
# container_name: cluster_node_3
|
||||
# build:
|
||||
# context: .
|
||||
# dockerfile: Dockerfile.dev
|
||||
# environment:
|
||||
# - PORT=7480
|
||||
# - RAFT_PORT=8000
|
||||
# - ML_PORT=7946
|
||||
# - KEY=/generic/ssl/certs/echovault/server1.key
|
||||
# - CERT=/generic/ssl/certs/echovault/server1.crt
|
||||
# - SERVER_ID=3
|
||||
# - JOIN_ADDR=cluster_node_1:7946
|
||||
# - DATA_DIR=/var/lib/echovault
|
||||
# - IN_MEMORY=false
|
||||
# - TLS=false
|
||||
# - MTLS=false
|
||||
# - BOOTSTRAP_CLUSTER=false
|
||||
# - ACL_CONFIG=/generic/config/echovault/acl.yml
|
||||
# - REQUIRE_PASS=false
|
||||
# - FORWARD_COMMAND=true
|
||||
# - SNAPSHOT_THRESHOLD=1000
|
||||
# - SNAPSHOT_INTERVAL=5m30s
|
||||
# - RESTORE_SNAPSHOT=false
|
||||
# - RESTORE_AOF=false
|
||||
# - AOF_SYNC_STRATEGY=everysec
|
||||
# - MAX_MEMORY=2000kb
|
||||
# - EVICTION_POLICY=allkeys-lfu
|
||||
# # List of server cert/key pairs
|
||||
# - CERT_KEY_PAIR_1=/generic/ssl/certs/echovault/server/server1.crt,/generic/ssl/certs/echovault/server/server1.key
|
||||
# - CERT_KEY_PAIR_2=/generic/ssl/certs/echovault/server/server2.crt,/generic/ssl/certs/echovault/server/server2.key
|
||||
# # List of client certificate authorities
|
||||
# - CLIENT_CA_1=/generic/ssl/certs/echovault/client/rootCA.crt
|
||||
# ports:
|
||||
# - "7483:7480"
|
||||
# - "7948:7946"
|
||||
# - "8002:8000"
|
||||
# volumes:
|
||||
# - ./config/acl.yml:/generic/config/echovault/acl.yml
|
||||
# - ./volumes/cluster_node_3:/var/lib/echovault
|
||||
# networks:
|
||||
# - testnet
|
||||
#
|
||||
# cluster_node_4:
|
||||
# container_name: cluster_node_4
|
||||
# build:
|
||||
# context: .
|
||||
# dockerfile: Dockerfile.dev
|
||||
# environment:
|
||||
# - PORT=7480
|
||||
# - RAFT_PORT=8000
|
||||
# - ML_PORT=7946
|
||||
# - KEY=/generic/ssl/certs/echovault/server1.key
|
||||
# - CERT=/generic/ssl/certs/echovault/server1.crt
|
||||
# - SERVER_ID=4
|
||||
# - JOIN_ADDR=cluster_node_1:7946
|
||||
# - DATA_DIR=/var/lib/echovault
|
||||
# - IN_MEMORY=false
|
||||
# - TLS=false
|
||||
# - MTLS=false
|
||||
# - BOOTSTRAP_CLUSTER=false
|
||||
# - ACL_CONFIG=/generic/config/echovault/acl.yml
|
||||
# - REQUIRE_PASS=false
|
||||
# - FORWARD_COMMAND=true
|
||||
# - SNAPSHOT_THRESHOLD=1000
|
||||
# - SNAPSHOT_INTERVAL=5m30s
|
||||
# - RESTORE_SNAPSHOT=false
|
||||
# - RESTORE_AOF=false
|
||||
# - AOF_SYNC_STRATEGY=everysec
|
||||
# - MAX_MEMORY=2000kb
|
||||
# - EVICTION_POLICY=allkeys-lfu
|
||||
# # List of server cert/key pairs
|
||||
# - CERT_KEY_PAIR_1=/generic/ssl/certs/echovault/server/server1.crt,/generic/ssl/certs/echovault/server/server1.key
|
||||
# - CERT_KEY_PAIR_2=/generic/ssl/certs/echovault/server/server2.crt,/generic/ssl/certs/echovault/server/server2.key
|
||||
# # List of client certificate authorities
|
||||
# - CLIENT_CA_1=/generic/ssl/certs/echovault/client/rootCA.crt
|
||||
# ports:
|
||||
# - "7484:7480"
|
||||
# - "7949:7946"
|
||||
# - "8003:8000"
|
||||
# volumes:
|
||||
# - ./config/acl.yml:/generic/config/echovault/acl.yml
|
||||
# - ./volumes/cluster_node_4:/var/lib/echovault
|
||||
# networks:
|
||||
# - testnet
|
||||
#
|
||||
# cluster_node_5:
|
||||
# container_name: cluster_node_5
|
||||
# build:
|
||||
# context: .
|
||||
# dockerfile: Dockerfile.dev
|
||||
# environment:
|
||||
# - PORT=7480
|
||||
# - RAFT_PORT=8000
|
||||
# - ML_PORT=7946
|
||||
# - KEY=/generic/ssl/certs/echovault/server1.key
|
||||
# - CERT=/generic/ssl/certs/echovault/server1.crt
|
||||
# - SERVER_ID=5
|
||||
# - JOIN_ADDR=cluster_node_1:7946
|
||||
# - DATA_DIR=/var/lib/echovault
|
||||
# - IN_MEMORY=false
|
||||
# - TLS=false
|
||||
# - MTLS=false
|
||||
# - BOOTSTRAP_CLUSTER=false
|
||||
# - ACL_CONFIG=/generic/config/echovault/acl.yml
|
||||
# - REQUIRE_PASS=false
|
||||
# - FORWARD_COMMAND=true
|
||||
# - SNAPSHOT_THRESHOLD=1000
|
||||
# - SNAPSHOT_INTERVAL=5m30s
|
||||
# - RESTORE_SNAPSHOT=false
|
||||
# - RESTORE_AOF=false
|
||||
# - AOF_SYNC_STRATEGY=everysec
|
||||
# - MAX_MEMORY=2000kb
|
||||
# - EVICTION_POLICY=allkeys-lfu
|
||||
# # List of server cert/key pairs
|
||||
# - CERT_KEY_PAIR_1=/generic/ssl/certs/echovault/server/server1.crt,/generic/ssl/certs/echovault/server/server1.key
|
||||
# - CERT_KEY_PAIR_2=/generic/ssl/certs/echovault/server/server2.crt,/generic/ssl/certs/echovault/server/server2.key
|
||||
# # List of client certificate authorities
|
||||
# - CLIENT_CA_1=/generic/ssl/certs/echovault/client/rootCA.crt
|
||||
# ports:
|
||||
# - "7485:7480"
|
||||
# - "7950:7946"
|
||||
# - "8004:8000"
|
||||
# volumes:
|
||||
# - ./config/acl.yml:/generic/config/echovault/acl.yml
|
||||
# - ./volumes/cluster_node_5:/var/lib/echovault
|
||||
# networks:
|
||||
# - testnet
|
||||
cluster_node_1:
|
||||
container_name: cluster_node_1
|
||||
build:
|
||||
context: .
|
||||
dockerfile: Dockerfile.dev
|
||||
environment:
|
||||
- PORT=7480
|
||||
- RAFT_PORT=8000
|
||||
- ML_PORT=7946
|
||||
- KEY=/generic/ssl/certs/echovault/server1.key
|
||||
- CERT=/generic/ssl/certs/echovault/server1.crt
|
||||
- SERVER_ID=1
|
||||
- DATA_DIR=/var/lib/echovault
|
||||
- IN_MEMORY=false
|
||||
- TLS=false
|
||||
- MTLS=false
|
||||
- BOOTSTRAP_CLUSTER=true
|
||||
- ACL_CONFIG=/generic/config/echovault/acl.yml
|
||||
- REQUIRE_PASS=false
|
||||
- FORWARD_COMMAND=true
|
||||
- SNAPSHOT_THRESHOLD=1000
|
||||
- SNAPSHOT_INTERVAL=5m30s
|
||||
- RESTORE_SNAPSHOT=false
|
||||
- RESTORE_AOF=false
|
||||
- AOF_SYNC_STRATEGY=everysec
|
||||
- MAX_MEMORY=2000kb
|
||||
- EVICTION_POLICY=allkeys-lfu
|
||||
# List of server cert/key pairs
|
||||
- CERT_KEY_PAIR_1=/generic/ssl/certs/echovault/server/server1.crt,/generic/ssl/certs/echovault/server/server1.key
|
||||
- CERT_KEY_PAIR_2=/generic/ssl/certs/echovault/server/server2.crt,/generic/ssl/certs/echovault/server/server2.key
|
||||
# List of client certificate authorities
|
||||
- CLIENT_CA_1=/generic/ssl/certs/echovault/client/rootCA.crt
|
||||
ports:
|
||||
- "7481:7480"
|
||||
- "7945:7946"
|
||||
- "8000:8000"
|
||||
volumes:
|
||||
- ./config/acl.yml:/generic/config/echovault/acl.yml
|
||||
- ./volumes/cluster_node_1:/var/lib/echovault
|
||||
networks:
|
||||
- testnet
|
||||
|
||||
cluster_node_2:
|
||||
container_name: cluster_node_2
|
||||
build:
|
||||
context: .
|
||||
dockerfile: Dockerfile.dev
|
||||
environment:
|
||||
- PORT=7480
|
||||
- RAFT_PORT=8000
|
||||
- ML_PORT=7946
|
||||
- KEY=/generic/ssl/certs/echovault/server1.key
|
||||
- CERT=/generic/ssl/certs/echovault/server1.crt
|
||||
- SERVER_ID=2
|
||||
- JOIN_ADDR=cluster_node_1:7946
|
||||
- DATA_DIR=/var/lib/echovault
|
||||
- IN_MEMORY=false
|
||||
- TLS=false
|
||||
- MTLS=false
|
||||
- BOOTSTRAP_CLUSTER=false
|
||||
- ACL_CONFIG=/generic/config/echovault/acl.yml
|
||||
- REQUIRE_PASS=false
|
||||
- FORWARD_COMMAND=true
|
||||
- SNAPSHOT_THRESHOLD=1000
|
||||
- SNAPSHOT_INTERVAL=5m30s
|
||||
- RESTORE_SNAPSHOT=false
|
||||
- RESTORE_AOF=false
|
||||
- AOF_SYNC_STRATEGY=everysec
|
||||
- MAX_MEMORY=2000kb
|
||||
- EVICTION_POLICY=allkeys-lfu
|
||||
# List of server cert/key pairs
|
||||
- CERT_KEY_PAIR_1=/generic/ssl/certs/echovault/server/server1.crt,/generic/ssl/certs/echovault/server/server1.key
|
||||
- CERT_KEY_PAIR_2=/generic/ssl/certs/echovault/server/server2.crt,/generic/ssl/certs/echovault/server/server2.key
|
||||
# List of client certificate authorities
|
||||
- CLIENT_CA_1=/generic/ssl/certs/echovault/client/rootCA.crt
|
||||
ports:
|
||||
- "7482:7480"
|
||||
- "7947:7946"
|
||||
- "8001:8000"
|
||||
volumes:
|
||||
- ./config/acl.yml:/generic/config/echovault/acl.yml
|
||||
- ./volumes/cluster_node_2:/var/lib/echovault
|
||||
networks:
|
||||
- testnet
|
||||
|
||||
cluster_node_3:
|
||||
container_name: cluster_node_3
|
||||
build:
|
||||
context: .
|
||||
dockerfile: Dockerfile.dev
|
||||
environment:
|
||||
- PORT=7480
|
||||
- RAFT_PORT=8000
|
||||
- ML_PORT=7946
|
||||
- KEY=/generic/ssl/certs/echovault/server1.key
|
||||
- CERT=/generic/ssl/certs/echovault/server1.crt
|
||||
- SERVER_ID=3
|
||||
- JOIN_ADDR=cluster_node_1:7946
|
||||
- DATA_DIR=/var/lib/echovault
|
||||
- IN_MEMORY=false
|
||||
- TLS=false
|
||||
- MTLS=false
|
||||
- BOOTSTRAP_CLUSTER=false
|
||||
- ACL_CONFIG=/generic/config/echovault/acl.yml
|
||||
- REQUIRE_PASS=false
|
||||
- FORWARD_COMMAND=true
|
||||
- SNAPSHOT_THRESHOLD=1000
|
||||
- SNAPSHOT_INTERVAL=5m30s
|
||||
- RESTORE_SNAPSHOT=false
|
||||
- RESTORE_AOF=false
|
||||
- AOF_SYNC_STRATEGY=everysec
|
||||
- MAX_MEMORY=2000kb
|
||||
- EVICTION_POLICY=allkeys-lfu
|
||||
# List of server cert/key pairs
|
||||
- CERT_KEY_PAIR_1=/generic/ssl/certs/echovault/server/server1.crt,/generic/ssl/certs/echovault/server/server1.key
|
||||
- CERT_KEY_PAIR_2=/generic/ssl/certs/echovault/server/server2.crt,/generic/ssl/certs/echovault/server/server2.key
|
||||
# List of client certificate authorities
|
||||
- CLIENT_CA_1=/generic/ssl/certs/echovault/client/rootCA.crt
|
||||
ports:
|
||||
- "7483:7480"
|
||||
- "7948:7946"
|
||||
- "8002:8000"
|
||||
volumes:
|
||||
- ./config/acl.yml:/generic/config/echovault/acl.yml
|
||||
- ./volumes/cluster_node_3:/var/lib/echovault
|
||||
networks:
|
||||
- testnet
|
||||
|
||||
cluster_node_4:
|
||||
container_name: cluster_node_4
|
||||
build:
|
||||
context: .
|
||||
dockerfile: Dockerfile.dev
|
||||
environment:
|
||||
- PORT=7480
|
||||
- RAFT_PORT=8000
|
||||
- ML_PORT=7946
|
||||
- KEY=/generic/ssl/certs/echovault/server1.key
|
||||
- CERT=/generic/ssl/certs/echovault/server1.crt
|
||||
- SERVER_ID=4
|
||||
- JOIN_ADDR=cluster_node_1:7946
|
||||
- DATA_DIR=/var/lib/echovault
|
||||
- IN_MEMORY=false
|
||||
- TLS=false
|
||||
- MTLS=false
|
||||
- BOOTSTRAP_CLUSTER=false
|
||||
- ACL_CONFIG=/generic/config/echovault/acl.yml
|
||||
- REQUIRE_PASS=false
|
||||
- FORWARD_COMMAND=true
|
||||
- SNAPSHOT_THRESHOLD=1000
|
||||
- SNAPSHOT_INTERVAL=5m30s
|
||||
- RESTORE_SNAPSHOT=false
|
||||
- RESTORE_AOF=false
|
||||
- AOF_SYNC_STRATEGY=everysec
|
||||
- MAX_MEMORY=2000kb
|
||||
- EVICTION_POLICY=allkeys-lfu
|
||||
# List of server cert/key pairs
|
||||
- CERT_KEY_PAIR_1=/generic/ssl/certs/echovault/server/server1.crt,/generic/ssl/certs/echovault/server/server1.key
|
||||
- CERT_KEY_PAIR_2=/generic/ssl/certs/echovault/server/server2.crt,/generic/ssl/certs/echovault/server/server2.key
|
||||
# List of client certificate authorities
|
||||
- CLIENT_CA_1=/generic/ssl/certs/echovault/client/rootCA.crt
|
||||
ports:
|
||||
- "7484:7480"
|
||||
- "7949:7946"
|
||||
- "8003:8000"
|
||||
volumes:
|
||||
- ./config/acl.yml:/generic/config/echovault/acl.yml
|
||||
- ./volumes/cluster_node_4:/var/lib/echovault
|
||||
networks:
|
||||
- testnet
|
||||
|
||||
cluster_node_5:
|
||||
container_name: cluster_node_5
|
||||
build:
|
||||
context: .
|
||||
dockerfile: Dockerfile.dev
|
||||
environment:
|
||||
- PORT=7480
|
||||
- RAFT_PORT=8000
|
||||
- ML_PORT=7946
|
||||
- KEY=/generic/ssl/certs/echovault/server1.key
|
||||
- CERT=/generic/ssl/certs/echovault/server1.crt
|
||||
- SERVER_ID=5
|
||||
- JOIN_ADDR=cluster_node_1:7946
|
||||
- DATA_DIR=/var/lib/echovault
|
||||
- IN_MEMORY=false
|
||||
- TLS=false
|
||||
- MTLS=false
|
||||
- BOOTSTRAP_CLUSTER=false
|
||||
- ACL_CONFIG=/generic/config/echovault/acl.yml
|
||||
- REQUIRE_PASS=false
|
||||
- FORWARD_COMMAND=true
|
||||
- SNAPSHOT_THRESHOLD=1000
|
||||
- SNAPSHOT_INTERVAL=5m30s
|
||||
- RESTORE_SNAPSHOT=false
|
||||
- RESTORE_AOF=false
|
||||
- AOF_SYNC_STRATEGY=everysec
|
||||
- MAX_MEMORY=2000kb
|
||||
- EVICTION_POLICY=allkeys-lfu
|
||||
# List of server cert/key pairs
|
||||
- CERT_KEY_PAIR_1=/generic/ssl/certs/echovault/server/server1.crt,/generic/ssl/certs/echovault/server/server1.key
|
||||
- CERT_KEY_PAIR_2=/generic/ssl/certs/echovault/server/server2.crt,/generic/ssl/certs/echovault/server/server2.key
|
||||
# List of client certificate authorities
|
||||
- CLIENT_CA_1=/generic/ssl/certs/echovault/client/rootCA.crt
|
||||
ports:
|
||||
- "7485:7480"
|
||||
- "7950:7946"
|
||||
- "8004:8000"
|
||||
volumes:
|
||||
- ./config/acl.yml:/generic/config/echovault/acl.yml
|
||||
- ./volumes/cluster_node_5:/var/lib/echovault
|
||||
networks:
|
||||
- testnet
|
@@ -21,6 +21,7 @@ type DelegateOpts struct {
|
||||
addVoter func(id raft.ServerID, address raft.ServerAddress, prevIndex uint64, timeout time.Duration) error
|
||||
isRaftLeader func() bool
|
||||
applyMutate func(ctx context.Context, cmd []string) ([]byte, error)
|
||||
applyDeleteKey func(ctx context.Context, key string) error
|
||||
}
|
||||
|
||||
func NewDelegate(opts DelegateOpts) *Delegate {
|
||||
@@ -67,6 +68,24 @@ func (delegate *Delegate) NotifyMsg(msgBytes []byte) {
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
}
|
||||
|
||||
case "DeleteKey":
|
||||
// If the current node is not a cluster leader, re-broadcast the message
|
||||
if !delegate.options.isRaftLeader() {
|
||||
delegate.options.broadcastQueue.QueueBroadcast(&msg)
|
||||
return
|
||||
}
|
||||
// Current node is the cluster leader, handle the key deletion
|
||||
ctx := context.WithValue(
|
||||
context.WithValue(context.Background(), utils.ContextServerID("ServerID"), string(msg.ServerID)),
|
||||
utils.ContextConnID("ConnectionID"), msg.ConnId)
|
||||
|
||||
key := string(msg.Content)
|
||||
|
||||
if err := delegate.options.applyDeleteKey(ctx, key); err != nil {
|
||||
log.Println(err)
|
||||
}
|
||||
|
||||
case "MutateData":
|
||||
// If the current node is not a cluster leader, re-broadcast the message
|
||||
if !delegate.options.isRaftLeader() {
|
||||
|
@@ -19,23 +19,24 @@ type NodeMeta struct {
|
||||
RaftAddr raft.ServerAddress `json:"RaftAddr"`
|
||||
}
|
||||
|
||||
type MemberlistOpts struct {
|
||||
type Opts struct {
|
||||
Config utils.Config
|
||||
HasJoinedCluster func() bool
|
||||
AddVoter func(id raft.ServerID, address raft.ServerAddress, prevIndex uint64, timeout time.Duration) error
|
||||
RemoveRaftServer func(meta NodeMeta) error
|
||||
IsRaftLeader func() bool
|
||||
ApplyMutate func(ctx context.Context, cmd []string) ([]byte, error)
|
||||
ApplyDeleteKey func(ctx context.Context, key string) error
|
||||
}
|
||||
|
||||
type MemberList struct {
|
||||
options MemberlistOpts
|
||||
options Opts
|
||||
broadcastQueue *memberlist.TransmitLimitedQueue
|
||||
numOfNodes int
|
||||
memberList *memberlist.Memberlist
|
||||
}
|
||||
|
||||
func NewMemberList(opts MemberlistOpts) *MemberList {
|
||||
func NewMemberList(opts Opts) *MemberList {
|
||||
return &MemberList{
|
||||
options: opts,
|
||||
broadcastQueue: new(memberlist.TransmitLimitedQueue),
|
||||
@@ -53,6 +54,7 @@ func (m *MemberList) MemberListInit(ctx context.Context) {
|
||||
addVoter: m.options.AddVoter,
|
||||
isRaftLeader: m.options.IsRaftLeader,
|
||||
applyMutate: m.options.ApplyMutate,
|
||||
applyDeleteKey: m.options.ApplyDeleteKey,
|
||||
})
|
||||
cfg.Events = NewEventDelegate(EventDelegateOpts{
|
||||
incrementNodes: func() { m.numOfNodes += 1 },
|
||||
@@ -75,8 +77,8 @@ func (m *MemberList) MemberListInit(ctx context.Context) {
|
||||
if m.options.Config.JoinAddr != "" {
|
||||
backoffPolicy := utils.RetryBackoff(retry.NewFibonacci(1*time.Second), 5, 200*time.Millisecond, 0, 0)
|
||||
|
||||
err := retry.Do(ctx, backoffPolicy, func(ctx context.Context) error {
|
||||
_, err := list.Join([]string{m.options.Config.JoinAddr})
|
||||
err = retry.Do(ctx, backoffPolicy, func(ctx context.Context) error {
|
||||
_, err = list.Join([]string{m.options.Config.JoinAddr})
|
||||
if err != nil {
|
||||
return retry.RetryableError(err)
|
||||
}
|
||||
@@ -103,9 +105,26 @@ func (m *MemberList) broadcastRaftAddress(ctx context.Context) {
|
||||
m.broadcastQueue.QueueBroadcast(&msg)
|
||||
}
|
||||
|
||||
// The ForwardDeleteKey function is only called by non-leaders.
|
||||
// It uses the broadcast queue to forward a key eviction command within the cluster.
|
||||
func (m *MemberList) ForwardDeleteKey(ctx context.Context, key string) {
|
||||
connId, _ := ctx.Value(utils.ContextConnID("ConnectionID")).(string)
|
||||
m.broadcastQueue.QueueBroadcast(&BroadcastMessage{
|
||||
Action: "DeleteKey",
|
||||
Content: []byte(key),
|
||||
ContentHash: md5.Sum([]byte(key)),
|
||||
ConnId: connId,
|
||||
NodeMeta: NodeMeta{
|
||||
ServerID: raft.ServerID(m.options.Config.ServerID),
|
||||
RaftAddr: raft.ServerAddress(fmt.Sprintf("%s:%d",
|
||||
m.options.Config.BindAddr, m.options.Config.RaftBindPort)),
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
// The ForwardDataMutation function is only called by non-leaders.
|
||||
// It uses the broadcast queue to forward a data mutation within the cluster.
|
||||
func (m *MemberList) ForwardDataMutation(ctx context.Context, cmd []byte) {
|
||||
// This function is only called by non-leaders
|
||||
// It uses the broadcast queue to forward a data mutation within the cluster
|
||||
connId, _ := ctx.Value(utils.ContextConnID("ConnectionID")).(string)
|
||||
m.broadcastQueue.QueueBroadcast(&BroadcastMessage{
|
||||
Action: "MutateData",
|
||||
|
@@ -15,6 +15,7 @@ type FSMOpts struct {
|
||||
Config utils.Config
|
||||
Server utils.Server
|
||||
GetCommand func(command string) (utils.Command, error)
|
||||
DeleteKey func(ctx context.Context, key string) error
|
||||
}
|
||||
|
||||
type FSM struct {
|
||||
@@ -53,7 +54,16 @@ func (fsm *FSM) Apply(log *raft.Log) interface{} {
|
||||
}
|
||||
|
||||
case "delete-key":
|
||||
// TODO: Handle key deletion
|
||||
if err := fsm.options.DeleteKey(ctx, request.Key); err != nil {
|
||||
return utils.ApplyResponse{
|
||||
Error: err,
|
||||
Response: nil,
|
||||
}
|
||||
}
|
||||
return utils.ApplyResponse{
|
||||
Error: nil,
|
||||
Response: []byte("OK"),
|
||||
}
|
||||
|
||||
case "command":
|
||||
// Handle command
|
||||
|
@@ -20,6 +20,7 @@ type Opts struct {
|
||||
Config utils.Config
|
||||
Server utils.Server
|
||||
GetCommand func(command string) (utils.Command, error)
|
||||
DeleteKey func(ctx context.Context, key string) error
|
||||
}
|
||||
|
||||
type Raft struct {
|
||||
@@ -94,6 +95,7 @@ func (r *Raft) RaftInit(ctx context.Context) {
|
||||
Config: r.options.Config,
|
||||
Server: r.options.Server,
|
||||
GetCommand: r.options.GetCommand,
|
||||
DeleteKey: r.options.DeleteKey,
|
||||
}),
|
||||
logStore,
|
||||
stableStore,
|
||||
|
@@ -85,10 +85,25 @@ func (server *Server) KeyExists(ctx context.Context, key string) bool {
|
||||
}
|
||||
|
||||
if entry.ExpireAt != (time.Time{}) && entry.ExpireAt.Before(time.Now()) {
|
||||
if !server.IsInCluster() {
|
||||
// If in standalone mode, delete the key directly.
|
||||
err := server.DeleteKey(ctx, key)
|
||||
if err != nil {
|
||||
log.Printf("keyExists: %+v\n", err)
|
||||
}
|
||||
} else if server.IsInCluster() && server.raft.IsRaftLeader() {
|
||||
// If we're in a raft cluster, and we're the leader, send command to delete the key in the cluster.
|
||||
err := server.raftApplyDeleteKey(ctx, key)
|
||||
if err != nil {
|
||||
log.Printf("keyExists: %+v\n", err)
|
||||
}
|
||||
} else if server.IsInCluster() && !server.raft.IsRaftLeader() {
|
||||
// Forward message to leader to initiate key deletion.
|
||||
// This is always called regardless of ForwardCommand config value
|
||||
// because we always want to remove expired keys.
|
||||
server.memberList.ForwardDeleteKey(ctx, key)
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
@@ -251,6 +266,8 @@ func (server *Server) DeleteKey(ctx context.Context, key string) error {
|
||||
server.lruCache.cache.Delete(key)
|
||||
}
|
||||
|
||||
log.Printf("deleted key %s\n", key)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
|
@@ -94,14 +94,16 @@ func NewServer(opts Opts) *Server {
|
||||
Config: opts.Config,
|
||||
Server: server,
|
||||
GetCommand: server.getCommand,
|
||||
DeleteKey: server.DeleteKey,
|
||||
})
|
||||
server.memberList = memberlist.NewMemberList(memberlist.MemberlistOpts{
|
||||
server.memberList = memberlist.NewMemberList(memberlist.Opts{
|
||||
Config: opts.Config,
|
||||
HasJoinedCluster: server.raft.HasJoinedCluster,
|
||||
AddVoter: server.raft.AddVoter,
|
||||
RemoveRaftServer: server.raft.RemoveServer,
|
||||
IsRaftLeader: server.raft.IsRaftLeader,
|
||||
ApplyMutate: server.raftApplyCommand,
|
||||
ApplyDeleteKey: server.raftApplyDeleteKey,
|
||||
})
|
||||
} else {
|
||||
// Set up standalone snapshot engine
|
||||
|
Reference in New Issue
Block a user