const net = require(“net”);
const fs = require(“fs”);
const path = require(“path”);
console.log(“Logs from your program will appear here!”);
const store = {}; // In-memory key-value store
const expiry = {}; // Store expiry timestamps for keys
const config = {}; // Store config dir and rdb file
// receive dir and filename as argument
const arguments = process.argv.slice(2);
const [fileDir, fileName] = [arguments[1] ?? null, arguments[3] ?? null];
// Function to parse the RDB file and extract keys
function parseRDB(filePath) {
if (!fs.existsSync(filePath)) {
console.log(“RDB file not found. Returning empty database.”);
return ;
}
const data = fs.readFileSync(filePath);
const keys = [];
let i = 0;
while (i < data.length) {
if (data[i] === 0xFE) {
i++;
continue;
}
if (data[i] === 0x00) {
i++;
const keyLength = data[i++];
const key = data.slice(i, i + keyLength).toString();
i += keyLength;
const valueLength = data[i++];
i += valueLength; // Skip value
keys.push(key);
} else {
i++;
}
}
return keys;
}
if (fileDir && fileName) {
config[‘dir’] = fileDir;
config[‘dbfilename’] = fileName;
const rdbPath = path.join(fileDir, fileName);
const keys = parseRDB(rdbPath);
keys.forEach(key => store[key] = “Loaded from RDB”);
}
const server = net.createServer((connection) => {
console.log(“Client connected”);
connection.on(“data”, (chunk) => {
const commands = Buffer.from(chunk).toString().split(“\r\n”);
if (commands[2] === "ECHO") {
const str = commands[4];
return connection.write(`$${str.length}\r\n${str}\r\n`);
} else if (commands[2] === "GET") {
const key = commands[4];
// Check if key has expired
if (expiry[key] && Date.now() > expiry[key]) {
delete store[key];
delete expiry[key];
return connection.write("$-1\r\n"); // Null bulk string
}
const value = store[key];
if (value !== undefined) {
return connection.write(`$${value.length}\r\n${value}\r\n`);
} else {
return connection.write("$-1\r\n"); // Null bulk string
}
} else if (commands[2] === "SET") {
const key = commands[4];
const value = commands[6];
store[key] = value;
// Check for PX flag
if (commands.length >= 10 && commands[8].toUpperCase() === "PX") {
const expiryTime = parseInt(commands[10]);
if (!isNaN(expiryTime)) {
expiry[key] = Date.now() + expiryTime;
setTimeout(() => {
if (Date.now() > expiry[key]) {
delete store[key];
delete expiry[key];
}
}, expiryTime);
}
}
return connection.write("+OK\r\n"); // Success message
} else if (commands[2] === "CONFIG" && commands[4] === "GET") {
const key = commands[6];
if (config[key] !== undefined) {
const value = config[key];
return connection.write(`*2\r\n$${key.length}\r\n${key}\r\n$${value.length}\r\n${value}\r\n`);
} else {
return connection.write("*2\r\n$0\r\n\r\n$0\r\n\r\n"); // Empty response for unknown parameter
}
}else if (commands[2] === "KEYS" && commands[4] === "*") {
const keys = Object.keys(store);
if (keys.length === 0) {
return connection.write("*0\r\n"); // Properly formatted empty response
}
let response = `*${keys.length}\r\n`;
keys.forEach(key => {
response += `$${Buffer.byteLength(key, 'utf8')}\r\n${key}\r\n`;
});
return connection.write(response);
}
});
connection.on(“end”, () => console.log(“Client disconnected”));
connection.on(“error”, (err) => console.error(“Connection error:”, err));
});
server.listen(6379, “127.0.0.1”, () => {
console.log(“Server listening on port 6379…”);
});