cli.go 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136
  1. package common
  2. import (
  3. "fmt"
  4. "regexp"
  5. "strconv"
  6. "strings"
  7. "time"
  8. "igit.com/xbase/raft"
  9. )
  10. const (
  11. ColorReset = "\033[0m"
  12. ColorDim = "\033[90m" // Dark Gray
  13. ColorRed = "\033[31m"
  14. ColorGreen = "\033[32m"
  15. ColorYellow = "\033[33m"
  16. ColorBlue = "\033[34m"
  17. ColorCyan = "\033[36m"
  18. )
  19. // Helper to calculate visible length of string ignoring ANSI codes
  20. var ansiRegex = regexp.MustCompile(`\x1b\[[0-9;]*m`)
  21. func visibleLen(s string) int {
  22. clean := ansiRegex.ReplaceAllString(s, "")
  23. return len([]rune(clean))
  24. }
  25. func printBoxed(content string) {
  26. lines := strings.Split(strings.TrimSpace(content), "\n")
  27. maxWidth := 0
  28. for _, line := range lines {
  29. l := visibleLen(line)
  30. if l > maxWidth {
  31. maxWidth = l
  32. }
  33. }
  34. // Min width to look decent
  35. if maxWidth < 20 {
  36. maxWidth = 20
  37. }
  38. // Add padding
  39. contentWidth := maxWidth + 2
  40. fmt.Println() // Start new line before box
  41. // Top Border
  42. fmt.Printf("%s╭%s╮%s\n", ColorDim, strings.Repeat("─", contentWidth), ColorReset)
  43. // Content
  44. for _, line := range lines {
  45. visLen := visibleLen(line)
  46. padding := contentWidth - visLen - 1 // -1 for the space after │
  47. // Ensure padding is not negative
  48. if padding < 0 { padding = 0 }
  49. fmt.Printf("%s│%s %s%s%s│%s\n", ColorDim, ColorReset, line, strings.Repeat(" ", padding), ColorDim, ColorReset)
  50. }
  51. // Bottom Border
  52. fmt.Printf("%s╰%s╯%s\n", ColorDim, strings.Repeat("─", contentWidth), ColorReset)
  53. fmt.Println() // End new line after box
  54. }
  55. // RegisterDemoCommands registers the demo commands (demodata, deletedatas) to the CLI
  56. func RegisterDemoCommands(cli *raft.CLI) {
  57. cli.RegisterCommand("demodata", "Generate n items (e.g. 'demodata 100 user.*')", func(parts []string, server *raft.KVServer) {
  58. if len(parts) != 3 {
  59. printBoxed("Usage: demodata <count> <pattern> (e.g. demodata 100 user.*)")
  60. return
  61. }
  62. count, err := strconv.Atoi(parts[1])
  63. if err != nil {
  64. printBoxed(fmt.Sprintf("Invalid count: %v", err))
  65. return
  66. }
  67. pattern := parts[2]
  68. fmt.Printf("Generating %d items with pattern '%s'...\n", count, pattern)
  69. start := time.Now()
  70. success := 0
  71. for i := 1; i <= count; i++ {
  72. key := strings.Replace(pattern, "*", strconv.Itoa(i), -1)
  73. val := fmt.Sprintf("val-%s", key) // Simple value derivation
  74. if err := server.Set(key, val); err != nil {
  75. fmt.Printf("Failed at %d: %v\n", i, err)
  76. } else {
  77. success++
  78. }
  79. if i%100 == 0 {
  80. fmt.Printf("Progress: %d/%d\r", i, count)
  81. }
  82. }
  83. duration := time.Since(start)
  84. printBoxed(fmt.Sprintf("%sDone!%s inserted %d/%d items in %v (Avg: %v/op)",
  85. ColorGreen, ColorReset, success, count, duration, duration/time.Duration(count)))
  86. })
  87. cli.RegisterCommand("deletedatas", "Batch delete n items matching pattern", func(parts []string, server *raft.KVServer) {
  88. // deletedatas <n> <pattern>
  89. if len(parts) != 3 {
  90. printBoxed("Usage: deletedatas <n> <pattern>")
  91. return
  92. }
  93. n, err := strconv.Atoi(parts[1])
  94. if err != nil {
  95. printBoxed("Invalid number: " + parts[1])
  96. return
  97. }
  98. pattern := parts[2]
  99. // Replace * with sequential numbers 1..n
  100. basePattern := strings.TrimSuffix(pattern, "*")
  101. successCount := 0
  102. start := time.Now()
  103. fmt.Printf("Deleting up to %d keys matching %s...\n", n, pattern)
  104. for i := 1; i <= n; i++ {
  105. key := fmt.Sprintf("%s%d", basePattern, i)
  106. if err := server.Del(key); err == nil {
  107. successCount++
  108. }
  109. if i % 100 == 0 {
  110. fmt.Print(".")
  111. }
  112. }
  113. fmt.Println()
  114. printBoxed(fmt.Sprintf("%sDeleted %d keys in %v%s", ColorGreen, successCount, time.Since(start), ColorReset))
  115. })
  116. }