package main import ( "bufio" "fmt" "net" "os" "strings" "time" ) const NumShards = 16 var db RedisDB var hub Hub type baseHandlerFunc func([]string)interface{} type connectionHandlerFunc func(net.Conn, []string) var baseCommandRegistry = map[string]baseHandlerFunc{ "GET": handleGet, "SET": handleSet, "DEL": handleDel, "EXISTS": handleExists, "INCR": handleIncr, "DECR": handleDecr, "RENAME": handleRename, "FLUSHALL": handleFlushall, "RPUSH": handleRpush, "LPUSH": handleLpush, "LRANGE": handleLrange, "LPOP": handleLpop, "RPOP": handleRpop, "EXPIRE": handleExpire, "HSET": handleHset, "HGET": handleHget, "HGETALL": handleHgetall, "HKEYS": handleHkeys, "HVALUES": handleHvalues, "TYPE": handleType, "DBSIZE": handleDbsize, "KEYS": handleKeys, "LREM": handleLrem, } var connectionCommandRegistry = map[string]connectionHandlerFunc{ "SUBSCRIBE": handleSubscribe, "UNSUBSCRIBE": handleUnsubscribe, "PUBLISH": handlePublish, "PING": handlePing, } func main() { shards := make([]*Shard, NumShards) for i := 0; i < NumShards; i++ { shards[i] = &Shard{ data: make(map[string]Item), id: i, } } db = RedisDB{shards: shards} hub = 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() { 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]) conn.Write(serializeRESP(DispatchBaseCommand(command,args))) } }