package main import ( "bufio" "fmt" "net" "os" "redisClone/pkg/commands" "redisClone/pkg/core" "redisClone/pkg/pubsub" "strings" "time" ) var db core.RedisDB var hub pubsub.Hub func main() { shards := make([]*core.Shard, core.NumShards) for i := 0; i < core.NumShards; i++ { shards[i] = &core.Shard{ Data: make(map[string]core.Item), Id: i, } } db = core.RedisDB{Shards: shards} commands.SetDB(db) hub = pubsub.Hub{Channels: make(map[string]map[net.Conn]struct{}),} go func() { ticker := time.NewTicker(1 * time.Second) for range ticker.C { for _,shard := range db.Shards{ shard.Mu.Lock() for k, v := range shard.Data { if v.ExpiresAt != nil && time.Now().After(*v.ExpiresAt) { delete(shard.Data, k) } } shard.Mu.Unlock() } } }() listener, err := net.Listen("tcp", ":6379") if err != nil { fmt.Println("error starting server: ", err) os.Exit(1) } defer listener.Close() fmt.Println("Redis clone listening on port 6379...") for { conn, err := listener.Accept() if err != nil { fmt.Println("Error accepting connection:", err) continue } go handleConnection(conn) } } func handleConnection(conn net.Conn) { defer func() { hub.HandleDisconnect(conn) conn.Close() }() fmt.Println("Client connected:", conn.RemoteAddr()) reader := bufio.NewReader(conn) for { args, err := parseRESP(reader) if err != nil { fmt.Println("Client disconnected or error parsing:", conn.RemoteAddr(), err) return } if len(args) == 0 { continue } fmt.Printf("Parsed RESP Arguments: %v\n", args) command := strings.ToUpper(args[0]) if cmd , ok := commands.PubSubRegistry[command]; ok { commands.DispatchPubSub(conn, &hub, cmd, args) } else if cmd, ok := commands.BaseRegistry[command]; ok { res := commands.DispatchBaseCommand(db, cmd, args) conn.Write(core.SerializeRESP(res)) } else { conn.Write(core.SerializeRESP(fmt.Errorf("ERR unknown command '%s'", command))) } } }