mirror of
https://github.com/DeBrosOfficial/orama.git
synced 2026-03-17 08:36:57 +00:00
fixed more bugs and updated docs
This commit is contained in:
parent
73dfe22438
commit
c401fdcd74
@ -452,15 +452,16 @@ make test-e2e # Run E2E tests
|
|||||||
|
|
||||||
```bash
|
```bash
|
||||||
# First node (genesis — creates cluster)
|
# First node (genesis — creates cluster)
|
||||||
sudo orama install --vps-ip <IP> --domain node1.example.com --nameserver
|
# Nameserver nodes use the base domain as --domain
|
||||||
|
sudo orama install --vps-ip <IP> --domain example.com --base-domain example.com --nameserver
|
||||||
|
|
||||||
# On the genesis node, generate an invite for a new node
|
# On the genesis node, generate an invite for a new node
|
||||||
orama invite
|
orama invite
|
||||||
# Outputs: sudo orama install --join https://node1.example.com --token <TOKEN> --vps-ip <NEW_IP>
|
# Outputs: sudo orama install --join https://example.com --token <TOKEN> --vps-ip <NEW_IP>
|
||||||
|
|
||||||
# Additional nodes (join via invite token over HTTPS)
|
# Additional nameserver nodes (join via invite token over HTTPS)
|
||||||
sudo orama install --join https://node1.example.com --token <TOKEN> \
|
sudo orama install --join https://example.com --token <TOKEN> \
|
||||||
--vps-ip <IP> --nameserver
|
--vps-ip <IP> --domain example.com --base-domain example.com --nameserver
|
||||||
```
|
```
|
||||||
|
|
||||||
**Security:** Nodes join via single-use invite tokens over HTTPS. A WireGuard VPN tunnel
|
**Security:** Nodes join via single-use invite tokens over HTTPS. A WireGuard VPN tunnel
|
||||||
|
|||||||
@ -100,10 +100,10 @@ To deploy to all nodes, repeat steps 3-5 (dev) or 3-4 (production) for each VPS
|
|||||||
| Flag | Description |
|
| Flag | Description |
|
||||||
|------|-------------|
|
|------|-------------|
|
||||||
| `--vps-ip <ip>` | VPS public IP address (required) |
|
| `--vps-ip <ip>` | VPS public IP address (required) |
|
||||||
| `--domain <domain>` | Domain for HTTPS certificates |
|
| `--domain <domain>` | Domain for HTTPS certificates. Nameserver nodes use the base domain (e.g., `example.com`); non-nameserver nodes use a subdomain (e.g., `node-4.example.com`) |
|
||||||
| `--base-domain <domain>` | Base domain for deployment routing (e.g., dbrs.space) |
|
| `--base-domain <domain>` | Base domain for deployment routing (e.g., example.com) |
|
||||||
| `--nameserver` | Configure this node as a nameserver (CoreDNS + Caddy) |
|
| `--nameserver` | Configure this node as a nameserver (CoreDNS + Caddy) |
|
||||||
| `--join <url>` | Join existing cluster via HTTPS URL (e.g., `https://node1.dbrs.space`) |
|
| `--join <url>` | Join existing cluster via HTTPS URL (e.g., `https://node1.example.com`) |
|
||||||
| `--token <token>` | Invite token for joining (from `orama invite` on existing node) |
|
| `--token <token>` | Invite token for joining (from `orama invite` on existing node) |
|
||||||
| `--branch <branch>` | Git branch to use (default: main) |
|
| `--branch <branch>` | Git branch to use (default: main) |
|
||||||
| `--no-pull` | Skip git clone/pull, use existing `/home/debros/src` |
|
| `--no-pull` | Skip git clone/pull, use existing `/home/debros/src` |
|
||||||
@ -143,16 +143,18 @@ To deploy to all nodes, repeat steps 3-5 (dev) or 3-4 (production) for each VPS
|
|||||||
|
|
||||||
```bash
|
```bash
|
||||||
# 1. Genesis node (first node, creates cluster)
|
# 1. Genesis node (first node, creates cluster)
|
||||||
sudo orama install --vps-ip 1.2.3.4 --domain node1.dbrs.space \
|
# Nameserver nodes use the base domain as --domain
|
||||||
--base-domain dbrs.space --nameserver
|
sudo orama install --vps-ip 1.2.3.4 --domain example.com \
|
||||||
|
--base-domain example.com --nameserver
|
||||||
|
|
||||||
# 2. On genesis node, generate an invite
|
# 2. On genesis node, generate an invite
|
||||||
orama invite
|
orama invite
|
||||||
# Output: sudo orama install --join https://node1.dbrs.space --token <TOKEN> --vps-ip <IP>
|
# Output: sudo orama install --join https://example.com --token <TOKEN> --vps-ip <IP>
|
||||||
|
|
||||||
# 3. On the new node, run the printed command
|
# 3. On the new node, run the printed command
|
||||||
sudo orama install --join https://node1.dbrs.space --token abc123... \
|
# Nameserver nodes use the base domain; non-nameserver nodes use subdomains (e.g., node-4.example.com)
|
||||||
--vps-ip 5.6.7.8 --nameserver
|
sudo orama install --join https://example.com --token abc123... \
|
||||||
|
--vps-ip 5.6.7.8 --domain example.com --base-domain example.com --nameserver
|
||||||
```
|
```
|
||||||
|
|
||||||
The join flow establishes a WireGuard VPN tunnel before starting cluster services.
|
The join flow establishes a WireGuard VPN tunnel before starting cluster services.
|
||||||
@ -161,9 +163,9 @@ No cluster ports are ever exposed publicly.
|
|||||||
|
|
||||||
#### DNS Prerequisite
|
#### DNS Prerequisite
|
||||||
|
|
||||||
The `--join` URL should use the HTTPS domain of the genesis node (e.g., `https://node1.dbrs.space`).
|
The `--join` URL should use the HTTPS domain of the genesis node (e.g., `https://node1.example.com`).
|
||||||
For this to work, the domain registrar for `dbrs.space` must have NS records pointing to the genesis
|
For this to work, the domain registrar for `example.com` must have NS records pointing to the genesis
|
||||||
node's IP so that `node1.dbrs.space` resolves publicly.
|
node's IP so that `node1.example.com` resolves publicly.
|
||||||
|
|
||||||
**If DNS is not yet configured**, you can use the genesis node's public IP with HTTP as a fallback:
|
**If DNS is not yet configured**, you can use the genesis node's public IP with HTTP as a fallback:
|
||||||
|
|
||||||
|
|||||||
@ -484,9 +484,9 @@ func promptForBaseDomain() string {
|
|||||||
fmt.Println("=================================")
|
fmt.Println("=================================")
|
||||||
fmt.Println("Select the network environment for this node:")
|
fmt.Println("Select the network environment for this node:")
|
||||||
fmt.Println()
|
fmt.Println()
|
||||||
fmt.Println(" 1. devnet-orama.network (Development - for testing)")
|
fmt.Println(" 1. orama-devnet.network (Development - for testing)")
|
||||||
fmt.Println(" 2. testnet-orama.network (Testnet - pre-production)")
|
fmt.Println(" 2. orama-testnet.network (Testnet - pre-production)")
|
||||||
fmt.Println(" 3. mainnet-orama.network (Mainnet - production)")
|
fmt.Println(" 3. orama-mainnet.network (Mainnet - production)")
|
||||||
fmt.Println(" 4. Custom domain...")
|
fmt.Println(" 4. Custom domain...")
|
||||||
fmt.Println()
|
fmt.Println()
|
||||||
fmt.Print("Select option [1-4] (default: 1): ")
|
fmt.Print("Select option [1-4] (default: 1): ")
|
||||||
@ -496,21 +496,21 @@ func promptForBaseDomain() string {
|
|||||||
|
|
||||||
switch choice {
|
switch choice {
|
||||||
case "", "1":
|
case "", "1":
|
||||||
fmt.Println("✓ Selected: devnet-orama.network")
|
fmt.Println("✓ Selected: orama-devnet.network")
|
||||||
return "devnet-orama.network"
|
return "orama-devnet.network"
|
||||||
case "2":
|
case "2":
|
||||||
fmt.Println("✓ Selected: testnet-orama.network")
|
fmt.Println("✓ Selected: orama-testnet.network")
|
||||||
return "testnet-orama.network"
|
return "orama-testnet.network"
|
||||||
case "3":
|
case "3":
|
||||||
fmt.Println("✓ Selected: mainnet-orama.network")
|
fmt.Println("✓ Selected: orama-mainnet.network")
|
||||||
return "mainnet-orama.network"
|
return "orama-mainnet.network"
|
||||||
case "4":
|
case "4":
|
||||||
fmt.Print("Enter custom base domain (e.g., example.com): ")
|
fmt.Print("Enter custom base domain (e.g., example.com): ")
|
||||||
customDomain, _ := reader.ReadString('\n')
|
customDomain, _ := reader.ReadString('\n')
|
||||||
customDomain = strings.TrimSpace(customDomain)
|
customDomain = strings.TrimSpace(customDomain)
|
||||||
if customDomain == "" {
|
if customDomain == "" {
|
||||||
fmt.Println("⚠️ No domain entered, using devnet-orama.network")
|
fmt.Println("⚠️ No domain entered, using orama-devnet.network")
|
||||||
return "devnet-orama.network"
|
return "orama-devnet.network"
|
||||||
}
|
}
|
||||||
// Remove any protocol prefix if user included it
|
// Remove any protocol prefix if user included it
|
||||||
customDomain = strings.TrimPrefix(customDomain, "https://")
|
customDomain = strings.TrimPrefix(customDomain, "https://")
|
||||||
@ -519,7 +519,7 @@ func promptForBaseDomain() string {
|
|||||||
fmt.Printf("✓ Selected: %s\n", customDomain)
|
fmt.Printf("✓ Selected: %s\n", customDomain)
|
||||||
return customDomain
|
return customDomain
|
||||||
default:
|
default:
|
||||||
fmt.Println("⚠️ Invalid option, using devnet-orama.network")
|
fmt.Println("⚠️ Invalid option, using orama-devnet.network")
|
||||||
return "devnet-orama.network"
|
return "orama-devnet.network"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -176,6 +176,7 @@ func (cg *ConfigGenerator) GenerateNodeConfig(peerAddresses []string, vpsIP stri
|
|||||||
TLSCacheDir: tlsCacheDir,
|
TLSCacheDir: tlsCacheDir,
|
||||||
HTTPPort: httpPort,
|
HTTPPort: httpPort,
|
||||||
HTTPSPort: httpsPort,
|
HTTPSPort: httpsPort,
|
||||||
|
WGIP: vpsIP,
|
||||||
}
|
}
|
||||||
|
|
||||||
// RQLite node-to-node TLS encryption is disabled by default
|
// RQLite node-to-node TLS encryption is disabled by default
|
||||||
|
|||||||
@ -504,7 +504,7 @@ func (ps *ProductionSetup) Phase4GenerateConfigs(peerAddresses []string, vpsIP s
|
|||||||
olricSeedPeers = olricPeers[0]
|
olricSeedPeers = olricPeers[0]
|
||||||
}
|
}
|
||||||
olricConfig, err := ps.configGenerator.GenerateOlricConfig(
|
olricConfig, err := ps.configGenerator.GenerateOlricConfig(
|
||||||
"127.0.0.1", // HTTP API on localhost
|
vpsIP, // HTTP API on WG IP (unique per node, avoids memberlist name conflict)
|
||||||
3320,
|
3320,
|
||||||
vpsIP, // Memberlist on WG IP for clustering
|
vpsIP, // Memberlist on WG IP for clustering
|
||||||
3322,
|
3322,
|
||||||
|
|||||||
@ -70,7 +70,11 @@ http_gateway:
|
|||||||
client_namespace: "default"
|
client_namespace: "default"
|
||||||
rqlite_dsn: "http://localhost:{{.RQLiteHTTPPort}}"
|
rqlite_dsn: "http://localhost:{{.RQLiteHTTPPort}}"
|
||||||
olric_servers:
|
olric_servers:
|
||||||
|
{{- if .WGIP}}
|
||||||
|
- "{{.WGIP}}:3320"
|
||||||
|
{{- else}}
|
||||||
- "127.0.0.1:3320"
|
- "127.0.0.1:3320"
|
||||||
|
{{- end}}
|
||||||
olric_timeout: "10s"
|
olric_timeout: "10s"
|
||||||
ipfs_cluster_api_url: "http://localhost:{{.ClusterAPIPort}}"
|
ipfs_cluster_api_url: "http://localhost:{{.ClusterAPIPort}}"
|
||||||
ipfs_api_url: "http://localhost:{{.IPFSAPIPort}}"
|
ipfs_api_url: "http://localhost:{{.IPFSAPIPort}}"
|
||||||
|
|||||||
@ -32,6 +32,7 @@ type NodeConfigData struct {
|
|||||||
TLSCacheDir string // Directory for ACME certificate cache
|
TLSCacheDir string // Directory for ACME certificate cache
|
||||||
HTTPPort int // HTTP port for ACME challenges (usually 80)
|
HTTPPort int // HTTP port for ACME challenges (usually 80)
|
||||||
HTTPSPort int // HTTPS port (usually 443)
|
HTTPSPort int // HTTPS port (usually 443)
|
||||||
|
WGIP string // WireGuard IP address (e.g., 10.0.0.1)
|
||||||
|
|
||||||
// Node-to-node TLS encryption for RQLite Raft communication
|
// Node-to-node TLS encryption for RQLite Raft communication
|
||||||
// Required when using SNI gateway for Raft traffic routing
|
// Required when using SNI gateway for Raft traffic routing
|
||||||
|
|||||||
@ -10,7 +10,11 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"path/filepath"
|
||||||
|
|
||||||
"github.com/DeBrosOfficial/network/pkg/rqlite"
|
"github.com/DeBrosOfficial/network/pkg/rqlite"
|
||||||
|
"github.com/libp2p/go-libp2p/core/crypto"
|
||||||
|
"github.com/libp2p/go-libp2p/core/peer"
|
||||||
"go.uber.org/zap"
|
"go.uber.org/zap"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -406,12 +410,30 @@ func (h *Handler) queryIPFSClusterPeerInfo(myWGIP string) PeerInfo {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// buildBootstrapPeers constructs bootstrap peer multiaddrs using WG IPs
|
// buildBootstrapPeers constructs bootstrap peer multiaddrs using WG IPs
|
||||||
|
// Uses the node's LibP2P peer ID (port 4001), NOT the IPFS peer ID (port 4101)
|
||||||
func (h *Handler) buildBootstrapPeers(myWGIP, ipfsPeerID string) []string {
|
func (h *Handler) buildBootstrapPeers(myWGIP, ipfsPeerID string) []string {
|
||||||
if ipfsPeerID == "" {
|
// Read the node's LibP2P identity from disk
|
||||||
|
keyPath := filepath.Join(h.oramaDir, "data", "identity.key")
|
||||||
|
keyData, err := os.ReadFile(keyPath)
|
||||||
|
if err != nil {
|
||||||
|
h.logger.Warn("Failed to read node identity for bootstrap peers", zap.Error(err))
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
priv, err := crypto.UnmarshalPrivateKey(keyData)
|
||||||
|
if err != nil {
|
||||||
|
h.logger.Warn("Failed to unmarshal node identity key", zap.Error(err))
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
peerID, err := peer.IDFromPublicKey(priv.GetPublic())
|
||||||
|
if err != nil {
|
||||||
|
h.logger.Warn("Failed to derive peer ID from identity key", zap.Error(err))
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
return []string{
|
return []string{
|
||||||
fmt.Sprintf("/ip4/%s/tcp/4101/p2p/%s", myWGIP, ipfsPeerID),
|
fmt.Sprintf("/ip4/%s/tcp/4001/p2p/%s", myWGIP, peerID.String()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -75,7 +75,7 @@ type InstanceConfig struct {
|
|||||||
Namespace string // Namespace name (e.g., "alice")
|
Namespace string // Namespace name (e.g., "alice")
|
||||||
NodeID string // Physical node ID
|
NodeID string // Physical node ID
|
||||||
HTTPPort int // HTTP API port
|
HTTPPort int // HTTP API port
|
||||||
BaseDomain string // Base domain (e.g., "devnet-orama.network")
|
BaseDomain string // Base domain (e.g., "orama-devnet.network")
|
||||||
RQLiteDSN string // RQLite connection DSN (e.g., "http://localhost:10000")
|
RQLiteDSN string // RQLite connection DSN (e.g., "http://localhost:10000")
|
||||||
OlricServers []string // Olric server addresses
|
OlricServers []string // Olric server addresses
|
||||||
NodePeerID string // Physical node's peer ID for home node management
|
NodePeerID string // Physical node's peer ID for home node management
|
||||||
|
|||||||
@ -20,7 +20,7 @@ import (
|
|||||||
|
|
||||||
// ClusterManagerConfig contains configuration for the cluster manager
|
// ClusterManagerConfig contains configuration for the cluster manager
|
||||||
type ClusterManagerConfig struct {
|
type ClusterManagerConfig struct {
|
||||||
BaseDomain string // Base domain for namespace gateways (e.g., "devnet-orama.network")
|
BaseDomain string // Base domain for namespace gateways (e.g., "orama-devnet.network")
|
||||||
BaseDataDir string // Base directory for namespace data (e.g., "~/.orama/data/namespaces")
|
BaseDataDir string // Base directory for namespace data (e.g., "~/.orama/data/namespaces")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -9,12 +9,12 @@ import (
|
|||||||
|
|
||||||
func TestClusterManagerConfig(t *testing.T) {
|
func TestClusterManagerConfig(t *testing.T) {
|
||||||
cfg := ClusterManagerConfig{
|
cfg := ClusterManagerConfig{
|
||||||
BaseDomain: "devnet-orama.network",
|
BaseDomain: "orama-devnet.network",
|
||||||
BaseDataDir: "~/.orama/data/namespaces",
|
BaseDataDir: "~/.orama/data/namespaces",
|
||||||
}
|
}
|
||||||
|
|
||||||
if cfg.BaseDomain != "devnet-orama.network" {
|
if cfg.BaseDomain != "orama-devnet.network" {
|
||||||
t.Errorf("BaseDomain = %s, want devnet-orama.network", cfg.BaseDomain)
|
t.Errorf("BaseDomain = %s, want orama-devnet.network", cfg.BaseDomain)
|
||||||
}
|
}
|
||||||
if cfg.BaseDataDir != "~/.orama/data/namespaces" {
|
if cfg.BaseDataDir != "~/.orama/data/namespaces" {
|
||||||
t.Errorf("BaseDataDir = %s, want ~/.orama/data/namespaces", cfg.BaseDataDir)
|
t.Errorf("BaseDataDir = %s, want ~/.orama/data/namespaces", cfg.BaseDataDir)
|
||||||
@ -25,7 +25,7 @@ func TestNewClusterManager(t *testing.T) {
|
|||||||
mockDB := newMockRQLiteClient()
|
mockDB := newMockRQLiteClient()
|
||||||
logger := zap.NewNop()
|
logger := zap.NewNop()
|
||||||
cfg := ClusterManagerConfig{
|
cfg := ClusterManagerConfig{
|
||||||
BaseDomain: "devnet-orama.network",
|
BaseDomain: "orama-devnet.network",
|
||||||
BaseDataDir: "/tmp/test-namespaces",
|
BaseDataDir: "/tmp/test-namespaces",
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -288,10 +288,10 @@ func TestClusterManager_PortAllocationOrder(t *testing.T) {
|
|||||||
|
|
||||||
func TestClusterManager_DNSFormat(t *testing.T) {
|
func TestClusterManager_DNSFormat(t *testing.T) {
|
||||||
// Test the DNS domain format for namespace gateways
|
// Test the DNS domain format for namespace gateways
|
||||||
baseDomain := "devnet-orama.network"
|
baseDomain := "orama-devnet.network"
|
||||||
namespaceName := "alice"
|
namespaceName := "alice"
|
||||||
|
|
||||||
expectedDomain := "ns-alice.devnet-orama.network"
|
expectedDomain := "ns-alice.orama-devnet.network"
|
||||||
actualDomain := "ns-" + namespaceName + "." + baseDomain
|
actualDomain := "ns-" + namespaceName + "." + baseDomain
|
||||||
|
|
||||||
if actualDomain != expectedDomain {
|
if actualDomain != expectedDomain {
|
||||||
|
|||||||
@ -14,9 +14,9 @@ func TestDNSRecordManager_FQDNFormat(t *testing.T) {
|
|||||||
baseDomain string
|
baseDomain string
|
||||||
expected string
|
expected string
|
||||||
}{
|
}{
|
||||||
{"alice", "devnet-orama.network", "ns-alice.devnet-orama.network."},
|
{"alice", "orama-devnet.network", "ns-alice.orama-devnet.network."},
|
||||||
{"bob", "testnet-orama.network", "ns-bob.testnet-orama.network."},
|
{"bob", "orama-testnet.network", "ns-bob.orama-testnet.network."},
|
||||||
{"my-namespace", "mainnet-orama.network", "ns-my-namespace.mainnet-orama.network."},
|
{"my-namespace", "orama-mainnet.network", "ns-my-namespace.orama-mainnet.network."},
|
||||||
{"test123", "example.com", "ns-test123.example.com."},
|
{"test123", "example.com", "ns-test123.example.com."},
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -37,8 +37,8 @@ func TestDNSRecordManager_WildcardFQDNFormat(t *testing.T) {
|
|||||||
baseDomain string
|
baseDomain string
|
||||||
expected string
|
expected string
|
||||||
}{
|
}{
|
||||||
{"alice", "devnet-orama.network", "*.ns-alice.devnet-orama.network."},
|
{"alice", "orama-devnet.network", "*.ns-alice.orama-devnet.network."},
|
||||||
{"bob", "testnet-orama.network", "*.ns-bob.testnet-orama.network."},
|
{"bob", "orama-testnet.network", "*.ns-bob.orama-testnet.network."},
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, tt := range tests {
|
for _, tt := range tests {
|
||||||
@ -54,7 +54,7 @@ func TestDNSRecordManager_WildcardFQDNFormat(t *testing.T) {
|
|||||||
func TestNewDNSRecordManager(t *testing.T) {
|
func TestNewDNSRecordManager(t *testing.T) {
|
||||||
mockDB := newMockRQLiteClient()
|
mockDB := newMockRQLiteClient()
|
||||||
logger := zap.NewNop()
|
logger := zap.NewNop()
|
||||||
baseDomain := "devnet-orama.network"
|
baseDomain := "orama-devnet.network"
|
||||||
|
|
||||||
manager := NewDNSRecordManager(mockDB, baseDomain, logger)
|
manager := NewDNSRecordManager(mockDB, baseDomain, logger)
|
||||||
|
|
||||||
@ -88,9 +88,9 @@ func TestDNSRecordTTL(t *testing.T) {
|
|||||||
func TestDNSRecordManager_MultipleDomainFormats(t *testing.T) {
|
func TestDNSRecordManager_MultipleDomainFormats(t *testing.T) {
|
||||||
// Test support for different domain formats
|
// Test support for different domain formats
|
||||||
baseDomains := []string{
|
baseDomains := []string{
|
||||||
"devnet-orama.network",
|
"orama-devnet.network",
|
||||||
"testnet-orama.network",
|
"orama-testnet.network",
|
||||||
"mainnet-orama.network",
|
"orama-mainnet.network",
|
||||||
"custom.example.com",
|
"custom.example.com",
|
||||||
"subdomain.custom.example.com",
|
"subdomain.custom.example.com",
|
||||||
}
|
}
|
||||||
@ -203,7 +203,7 @@ func TestDNSRecordManager_FQDNWithTrailingDot(t *testing.T) {
|
|||||||
input string
|
input string
|
||||||
expected string
|
expected string
|
||||||
}{
|
}{
|
||||||
{"ns-alice.devnet-orama.network", "ns-alice.devnet-orama.network."},
|
{"ns-alice.orama-devnet.network", "ns-alice.orama-devnet.network."},
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, tt := range tests {
|
for _, tt := range tests {
|
||||||
|
|||||||
@ -306,6 +306,11 @@ func extractIPForSort(raftAddr string) string {
|
|||||||
// IsVoter returns true if the given raft address is in the voter set
|
// IsVoter returns true if the given raft address is in the voter set
|
||||||
// based on the current known peers. Must be called with c.mu held.
|
// based on the current known peers. Must be called with c.mu held.
|
||||||
func (c *ClusterDiscoveryService) IsVoterLocked(raftAddress string) bool {
|
func (c *ClusterDiscoveryService) IsVoterLocked(raftAddress string) bool {
|
||||||
|
// If we don't know enough peers yet, default to voter.
|
||||||
|
// Non-voter demotion only kicks in once we see more than MaxDefaultVoters peers.
|
||||||
|
if len(c.knownPeers) <= MaxDefaultVoters {
|
||||||
|
return true
|
||||||
|
}
|
||||||
raftAddrs := make([]string, 0, len(c.knownPeers))
|
raftAddrs := make([]string, 0, len(c.knownPeers))
|
||||||
for _, peer := range c.knownPeers {
|
for _, peer := range c.knownPeers {
|
||||||
raftAddrs = append(raftAddrs, peer.RaftAddress)
|
raftAddrs = append(raftAddrs, peer.RaftAddress)
|
||||||
|
|||||||
@ -122,7 +122,7 @@ func (r *RQLiteManager) launchProcess(ctx context.Context, rqliteDataDir string)
|
|||||||
if r.discoveryService != nil && !r.discoveryService.IsVoter(r.discoverConfig.RaftAdvAddress) {
|
if r.discoveryService != nil && !r.discoveryService.IsVoter(r.discoverConfig.RaftAdvAddress) {
|
||||||
r.logger.Info("Joining as non-voter (read replica)",
|
r.logger.Info("Joining as non-voter (read replica)",
|
||||||
zap.String("raft_address", r.discoverConfig.RaftAdvAddress))
|
zap.String("raft_address", r.discoverConfig.RaftAdvAddress))
|
||||||
args = append(args, "-non-voter")
|
args = append(args, "-raft-non-voter")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user