Skip to content

Commit 0e1ec28

Browse files
committed
Playground basic command line
1 parent df0f603 commit 0e1ec28

File tree

4 files changed

+191
-7
lines changed

4 files changed

+191
-7
lines changed

cmd/playground.go

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
package cmd
2+
3+
import (
4+
"fmt"
5+
6+
"github.com/unpackdev/fdb/playground"
7+
"github.com/urfave/cli/v2"
8+
"go.uber.org/zap"
9+
)
10+
11+
const (
12+
DefaultBasePort = 50000
13+
DefaultNodeCount = 5
14+
)
15+
16+
// PlaygroundCommand returns a cli.Command that plays with the real clients over simulated network
17+
func PlaygroundCommand() *cli.Command {
18+
return &cli.Command{
19+
Name: "playground",
20+
Usage: "Play with (f)db clients over simulated network",
21+
Flags: []cli.Flag{
22+
&cli.IntFlag{
23+
Name: "base-port",
24+
Aliases: []string{"p"},
25+
Value: DefaultBasePort,
26+
Usage: "Base port for the nodes (each node will use this port + index)",
27+
},
28+
&cli.IntFlag{
29+
Name: "node-count",
30+
Aliases: []string{"n"},
31+
Value: DefaultNodeCount,
32+
Usage: "Number of nodes to start in the playground",
33+
},
34+
&cli.StringFlag{
35+
Name: "log-level",
36+
Aliases: []string{"l"},
37+
Value: "debug",
38+
Usage: "Log level (debug, info, warn, error)",
39+
},
40+
},
41+
Action: func(c *cli.Context) error {
42+
// Create a config with defaults that can be overridden by CLI flags
43+
config := playground.Config{
44+
BasePort: DefaultBasePort,
45+
NodeCount: DefaultNodeCount,
46+
LogLevel: zap.NewAtomicLevelAt(zap.DebugLevel),
47+
}
48+
49+
// Parse log level if provided
50+
if c.IsSet("log-level") {
51+
logLevelStr := c.String("log-level")
52+
level, err := zap.ParseAtomicLevel(logLevelStr)
53+
if err != nil {
54+
return fmt.Errorf("invalid log level: %w", err)
55+
}
56+
57+
config.LogLevel = level
58+
}
59+
60+
// Run the playground with both the context and config
61+
return playground.Run(c, config)
62+
},
63+
}
64+
}

entrypoint/main.go

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,24 @@
11
package main
22

33
import (
4-
"github.com/unpackdev/fdb/cmd"
5-
"github.com/urfave/cli/v2"
64
"log"
75
"os"
6+
7+
"github.com/unpackdev/fdb/cmd"
8+
"github.com/urfave/cli/v2"
89
)
910

1011
func main() {
1112
app := &cli.App{
1213
Name: "(f)db",
1314
Usage: "Fast Database Transports",
1415
Commands: []*cli.Command{
15-
cmd.CertsCommand(), // Command for handling certificates
16-
cmd.BenchmarkCommand(), // Command for running benchmarks
17-
cmd.EbpfCommands(), // Command for running eBPF specific workload
18-
cmd.ServeCommand(), // Command to start the server
19-
cmd.KeystoreCommand(), // Command for handling keystore (Peer IDs)
16+
cmd.CertsCommand(), // Command for handling certificates
17+
cmd.BenchmarkCommand(), // Command for running benchmarks
18+
cmd.EbpfCommands(), // Command for running eBPF specific workload
19+
cmd.ServeCommand(), // Command to start the server
20+
cmd.KeystoreCommand(), // Command for handling keystore (Peer IDs)
21+
cmd.PlaygroundCommand(), // Command for playing with real clients over simulated network
2022
},
2123
}
2224

playground/README.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
# Playground
2+
3+
This directory is used for testing and playing around with different things. Idea is to have a place where we can spawn
4+
as many as possible nodes we want and see them in grafana dashboard how they behave. Behaviour include:
5+
6+
- Network, latencies and availability
7+
- RPC
8+
- Raw TCP and Capn Proto

playground/entrypoint.go

Lines changed: 110 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,110 @@
1+
package playground
2+
3+
import (
4+
"context"
5+
"fmt"
6+
"os"
7+
"os/signal"
8+
"syscall"
9+
"time"
10+
11+
"github.com/unpackdev/fdb/pkg/rbac"
12+
"github.com/unpackdev/fdb/pkg/types"
13+
"github.com/unpackdev/fdb/playground/suite"
14+
"github.com/urfave/cli/v2"
15+
"go.uber.org/zap"
16+
)
17+
18+
// Config holds the configuration for the playground environment
19+
type Config struct {
20+
BasePort int
21+
NodeCount int
22+
LogLevel zap.AtomicLevel
23+
}
24+
25+
// Run initializes and runs the playground environment based on the provided CLI context and config
26+
func Run(cliCtx *cli.Context, config Config) error {
27+
// Create a cancelable context
28+
ctx, cancel := context.WithCancel(context.Background())
29+
defer cancel()
30+
31+
// Use configuration from config parameter, overridden by CLI flags if provided
32+
basePort := config.BasePort
33+
if basePort == 0 {
34+
basePort = 9000
35+
}
36+
if cliCtx.IsSet("base-port") {
37+
basePort = cliCtx.Int("base-port")
38+
}
39+
40+
nodeCount := config.NodeCount
41+
if nodeCount == 0 {
42+
nodeCount = 5
43+
}
44+
if cliCtx.IsSet("node-count") {
45+
nodeCount = cliCtx.Int("node-count")
46+
}
47+
48+
logLevel := zap.InfoLevel
49+
if config.LogLevel.Level() != zap.InfoLevel {
50+
logLevel = config.LogLevel.Level()
51+
}
52+
if cliCtx.IsSet("debug") && cliCtx.Bool("debug") {
53+
logLevel = zap.DebugLevel
54+
}
55+
56+
// Define the node roles
57+
roles := make([]types.Role, nodeCount)
58+
for i := range roles {
59+
roles[i] = rbac.RoleNode
60+
}
61+
62+
// Initialize the nodes
63+
fmt.Printf("Initializing %d nodes with base port %d...\n", nodeCount, basePort)
64+
nodes, err := suite.InitializeNodes(
65+
ctx,
66+
logLevel,
67+
types.Ed25519SignerType,
68+
roles,
69+
basePort,
70+
types.TCPTransportType,
71+
)
72+
if err != nil {
73+
return fmt.Errorf("failed to initialize nodes: %w", err)
74+
}
75+
76+
// Ensure we clean up nodes when exiting
77+
defer func() {
78+
fmt.Println("Shutting down nodes...")
79+
if err := suite.ShutdownTestNodes(nodes); err != nil {
80+
fmt.Printf("Error shutting down nodes: %v\n", err)
81+
}
82+
}()
83+
84+
// Print node information
85+
fmt.Println("Playground nodes initialized:")
86+
for i, node := range nodes {
87+
fmt.Printf("Node %d: PeerID=%s, Role=%s\n", i, node.PeerID().String(), node.Role())
88+
}
89+
90+
// Wait for nodes to connect to each other
91+
fmt.Println("Waiting for nodes to connect to each other...")
92+
for i, node := range nodes {
93+
// Minus one because own peer needs to be excluded
94+
if err := node.WaitForPeersConnected(len(roles)-1, 10*time.Second); err != nil {
95+
fmt.Printf("Warning: Node %d didn't connect to all peers in time: %v\n", i, err)
96+
}
97+
}
98+
99+
// Setup a signal handler for graceful shutdown
100+
sigCh := make(chan os.Signal, 1)
101+
signal.Notify(sigCh, syscall.SIGINT, syscall.SIGTERM)
102+
103+
fmt.Println("Playground environment is ready!")
104+
fmt.Println("Press Ctrl+C to exit...")
105+
106+
// Wait for interrupt signal
107+
<-sigCh
108+
fmt.Println("Received interrupt signal, shutting down playground...")
109+
return nil
110+
}

0 commit comments

Comments
 (0)