Danilo Fragoso před 10 měsíci
revize
b26ab44fd7
2 změnil soubory, kde provedl 170 přidání a 0 odebrání
  1. 113 0
      main.zig
  2. 57 0
      requirements.md

+ 113 - 0
main.zig

@@ -0,0 +1,113 @@
+const std = @import("std");
+const net = std.net;
+const posix = std.posix;
+
+pub fn main() !void {
+    const address = try std.net.Address.parseIp("127.0.0.1", 6000);
+
+    const tpe: u32 = posix.SOCK.STREAM;
+    const protocol = posix.IPPROTO.TCP;
+    const listener = try posix.socket(address.any.family, tpe, protocol);
+    defer posix.close(listener);
+
+    try posix.setsockopt(listener, posix.SOL.SOCKET, posix.SO.REUSEADDR, &std.mem.toBytes(@as(c_int, 1)));
+    try posix.bind(listener, &address.any, address.getOsSockLen());
+    try posix.listen(listener, 128);
+
+    while (true) {
+        var client_address: net.Address = undefined;
+        var client_address_len: posix.socklen_t = @sizeOf(net.Address);
+
+        const socket = posix.accept(listener, &client_address.any, &client_address_len, 0) catch |err| {
+            std.debug.print("error accept: {any}\n", .{err});
+            continue;
+        };
+        defer posix.close(socket);
+
+        std.debug.print("Connection received\n", .{});
+        var buf: [128]u8 = undefined;
+        const n = try read(socket, &buf);
+        std.debug.print("Read {d} bytes: {s}\n", .{ n, buf[0..n] });
+
+        try parseMessage(buf[0..n]);
+
+        write(socket, "congratulations") catch |err| {
+            // This can easily happen, say if the client disconnects.
+            std.debug.print("error writing: {any}\n", .{err});
+        };
+    }
+}
+
+const Command = enum {
+    read,
+    write,
+    delete,
+    status,
+};
+
+fn parseKeyValue(buf: []const u8) ?[2][]const u8 {
+    var kvIterator = std.mem.splitAny(u8, buf, "|");
+    const key = kvIterator.first();
+    const value = kvIterator.next() orelse {
+        std.debug.print("No value found for key: {s}\n", .{key});
+        return null;
+    };
+
+    std.debug.print("Parsed key: {s}, value: {s}\n", .{ key, value });
+    return [2][]const u8{ key, value };
+}
+
+fn parseMessage(buf: []const u8) !void {
+    var messageIterator = std.mem.splitAny(u8, buf, " ");
+
+    const command = std.meta.stringToEnum(Command, messageIterator.first()) orelse {
+        std.debug.print("Failed to parse command\n", .{});
+        return;
+    };
+
+    switch (command) {
+        .read => {
+            std.debug.print("Read command received\n", .{});
+        },
+        .write => {
+            std.debug.print("Write command received\n", .{});
+
+            const kvPair = messageIterator.next() orelse {
+                std.debug.print("No key-value pair provided for read command\n", .{});
+                return;
+            };
+
+            const kv = parseKeyValue(kvPair) orelse {
+                std.debug.print("Failed to parse key-value pair\n", .{});
+                return;
+            };
+
+            std.debug.print("Key: {s}, Value: {s}\n", .{ kv[0], kv[1] });
+        },
+        .delete => std.debug.print("Delete command received\n", .{}),
+        .status => std.debug.print("Status command received\n", .{}),
+    }
+}
+
+fn read(socket: posix.socket_t, buf: []u8) !usize {
+    var pos: usize = 0;
+    while (pos < buf.len) {
+        const n = try posix.read(socket, buf[pos..]);
+        if (n == 0) {
+            return pos; // connection closed
+        }
+        pos += n;
+    }
+    return pos;
+}
+
+fn write(socket: posix.socket_t, msg: []const u8) !void {
+    var pos: usize = 0;
+    while (pos < msg.len) {
+        const written = try posix.write(socket, msg[pos..]);
+        if (written == 0) {
+            return error.Closed;
+        }
+        pos += written;
+    }
+}

+ 57 - 0
requirements.md

@@ -0,0 +1,57 @@
+# Desafio Técnico: Banco de Dados Key-Value para Pizzaria Bate-Papo
+
+## 📋 Visão Geral
+
+- Desenvolvimento de um banco de dados key-value com persistencia com operações via TCP
+
+
+## 🎯 Requisitos Principais
+
+
+Operações via TCP
+
+
+COMANDOS:
+- read <key>          → Retorna valor ou erro
+- write <key>|<value> → Retorna bool (sucesso/falha)
+- delete <key>        → Retorna bool (sucesso/falha)
+- status             → Retorna uint (métricas do sistema)
+
+- 70% chaves pequenas (<= 1KB)
+- 20% chaves médias (1KB - 10KB) 
+- 10% chaves grandes (10KB - 100KB)
+- Padrão de acesso: 80/20 (80% das consultas em 20% dos dados)
+
+
+### Critérios de Avaliação
+
+1. Velocidade de Escrita (prioridade alta)
+2. Velocidade de Leitura (prioridade alta)
+3. Tamanho do Armazenamento (prioridade média)
+4. Persistência e Recuperação (crítico)
+
+
+### 📊 Métricas Expandidas
+| Métrica              | Descrição                               |
+|----------------------|-----------------------------------------|
+| Throughput Escrita   | Operações de escrita por segundo        |
+| Throughput Leitura   | Operações de leitura por segundo        |
+| Latência P95 Escrita | 95º percentil de latência               |
+| Latência P95 Leitura | 95º percentil de latência               |
+| Tempo de Recuperação | Tempo para recuperar dados após restart |
+
+
+### 💾 Métricas de Armazenamento
+| Métrica                   | Descrição                          |
+|---------------------------|------------------------------------|
+| Overhead de Armazenamento | <15% do tamanho dos dados          |
+| Taxa de Compactação       | Eficiência na compactação de dados |
+| Fragmentação              | Percentual de espaço desperdiçado  |
+
+
+### 🛡️ Métricas de Confiabilidade
+| Métrica                | Descrição                           |
+|------------------------|-------------------------------------|
+| Durabilidade dos Dados | Garantia de persistência após write |
+| Consistência em Falhas | Integridade após kill -9            |
+| Log de Operações       | Rastreabilidade das operações       |