| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136 |
- package common
- import (
- "fmt"
- "regexp"
- "strconv"
- "strings"
- "time"
- "igit.com/xbase/raft"
- )
- const (
- ColorReset = "\033[0m"
- ColorDim = "\033[90m" // Dark Gray
- ColorRed = "\033[31m"
- ColorGreen = "\033[32m"
- ColorYellow = "\033[33m"
- ColorBlue = "\033[34m"
- ColorCyan = "\033[36m"
- )
- // Helper to calculate visible length of string ignoring ANSI codes
- var ansiRegex = regexp.MustCompile(`\x1b\[[0-9;]*m`)
- func visibleLen(s string) int {
- clean := ansiRegex.ReplaceAllString(s, "")
- return len([]rune(clean))
- }
- func printBoxed(content string) {
- lines := strings.Split(strings.TrimSpace(content), "\n")
- maxWidth := 0
- for _, line := range lines {
- l := visibleLen(line)
- if l > maxWidth {
- maxWidth = l
- }
- }
-
- // Min width to look decent
- if maxWidth < 20 {
- maxWidth = 20
- }
- // Add padding
- contentWidth := maxWidth + 2
- fmt.Println() // Start new line before box
- // Top Border
- fmt.Printf("%s╭%s╮%s\n", ColorDim, strings.Repeat("─", contentWidth), ColorReset)
-
- // Content
- for _, line := range lines {
- visLen := visibleLen(line)
- padding := contentWidth - visLen - 1 // -1 for the space after │
- // Ensure padding is not negative
- if padding < 0 { padding = 0 }
-
- fmt.Printf("%s│%s %s%s%s│%s\n", ColorDim, ColorReset, line, strings.Repeat(" ", padding), ColorDim, ColorReset)
- }
-
- // Bottom Border
- fmt.Printf("%s╰%s╯%s\n", ColorDim, strings.Repeat("─", contentWidth), ColorReset)
- fmt.Println() // End new line after box
- }
- // RegisterDemoCommands registers the demo commands (demodata, deletedatas) to the CLI
- func RegisterDemoCommands(cli *raft.CLI) {
- cli.RegisterCommand("demodata", "Generate n items (e.g. 'demodata 100 user.*')", func(parts []string, server *raft.KVServer) {
- if len(parts) != 3 {
- printBoxed("Usage: demodata <count> <pattern> (e.g. demodata 100 user.*)")
- return
- }
- count, err := strconv.Atoi(parts[1])
- if err != nil {
- printBoxed(fmt.Sprintf("Invalid count: %v", err))
- return
- }
- pattern := parts[2]
- fmt.Printf("Generating %d items with pattern '%s'...\n", count, pattern)
-
- start := time.Now()
- success := 0
- for i := 1; i <= count; i++ {
- key := strings.Replace(pattern, "*", strconv.Itoa(i), -1)
- val := fmt.Sprintf("val-%s", key) // Simple value derivation
- if err := server.Set(key, val); err != nil {
- fmt.Printf("Failed at %d: %v\n", i, err)
- } else {
- success++
- }
- if i%100 == 0 {
- fmt.Printf("Progress: %d/%d\r", i, count)
- }
- }
- duration := time.Since(start)
- printBoxed(fmt.Sprintf("%sDone!%s inserted %d/%d items in %v (Avg: %v/op)",
- ColorGreen, ColorReset, success, count, duration, duration/time.Duration(count)))
- })
- cli.RegisterCommand("deletedatas", "Batch delete n items matching pattern", func(parts []string, server *raft.KVServer) {
- // deletedatas <n> <pattern>
- if len(parts) != 3 {
- printBoxed("Usage: deletedatas <n> <pattern>")
- return
- }
- n, err := strconv.Atoi(parts[1])
- if err != nil {
- printBoxed("Invalid number: " + parts[1])
- return
- }
- pattern := parts[2]
-
- // Replace * with sequential numbers 1..n
- basePattern := strings.TrimSuffix(pattern, "*")
-
- successCount := 0
- start := time.Now()
-
- fmt.Printf("Deleting up to %d keys matching %s...\n", n, pattern)
-
- for i := 1; i <= n; i++ {
- key := fmt.Sprintf("%s%d", basePattern, i)
- if err := server.Del(key); err == nil {
- successCount++
- }
- if i % 100 == 0 {
- fmt.Print(".")
- }
- }
- fmt.Println()
-
- printBoxed(fmt.Sprintf("%sDeleted %d keys in %v%s", ColorGreen, successCount, time.Since(start), ColorReset))
- })
- }
|