diff --git a/app/server.ts b/app/server.ts index c5262e3..1eaf5c3 100644 --- a/app/server.ts +++ b/app/server.ts @@ -4,11 +4,11 @@ import next from "next"; import { Server } from "socket.io"; import type { SocketServer } from "@/types"; import { Field } from "@/utils/game"; +import * as redis from "@/utils/redis"; const dev = process.env.NODE_ENV !== "production"; const hostname = "localhost"; const port = 3000; -const sessions = new Map(); async function main() { const app = next({ dev, hostname, port }); @@ -24,8 +24,8 @@ async function main() { io.use(async (socket, next) => { const { sessionId } = socket.handshake.auth; - const sessionState = sessions.get(sessionId); - if (sessions.get(sessionId) === "dead") { + const sessionState = await redis.getSession(sessionId); + if (sessionState === "dead") { return next(new Error("dead")); } socket.data.sessionId = sessionState @@ -34,8 +34,8 @@ async function main() { next(); }); - io.on("connection", (socket) => { - sessions.set(socket.data.sessionId, "alive"); + io.on("connection", async (socket) => { + await redis.startSession(socket.data.sessionId); socket.emit("sessionAlive", socket.data.sessionId); clientsCount++; @@ -45,7 +45,7 @@ async function main() { socket.on("expose", async (index) => { if (field.exposeCell(index) === "dead") { - sessions.set(socket.data.sessionId, "dead"); + await redis.killSession(socket.data.sessionId); socket.emit("sessionDead"); } else { field = await field.handleComplete(); diff --git a/app/utils/redis.ts b/app/utils/redis.ts index f2550ef..710d143 100644 --- a/app/utils/redis.ts +++ b/app/utils/redis.ts @@ -1,24 +1,40 @@ import { Redis } from "ioredis"; import _ from "lodash"; -const key = "field:data"; +const fieldKey = "field:data"; +const sessionKey = "user:sessions"; -function getClient() { - return new Redis(process.env["REDIS_URL"]!, { family: 6 }); -} +const redis = new Redis(process.env["REDIS_URL"]!, { family: 6 }); export async function decodeData() { - const redis = getClient(); - const value = await redis.get(key); + const value = await redis.get(fieldKey); if (typeof value !== "string" || !value) { - throw new Error(`unexpected data on key: ${key}`); + throw new Error(`unexpected data on key: ${fieldKey}`); } return Array.from(value, (char) => char.charCodeAt(0)); } export async function encodeData(value: number[]) { - const redis = getClient(); const binaryString = Buffer.from(value).toString("binary"); - await redis.set(key, binaryString); + await redis.set(fieldKey, binaryString); return value; } + +export async function getSession(sessionId: string) { + const value = await redis.hget(sessionKey, sessionId); + return value === "alive" || value === "dead" ? value : null; +} + +export async function startSession(sessionId: string) { + return redis.hset(sessionKey, sessionId, "alive"); +} + +export async function killSession(sessionId: string) { + return redis.hset(sessionKey, sessionId, "dead"); +} + +export async function reviveSessions() { + const sessions = await redis.hkeys(sessionKey); + const args = sessions.flatMap((sessionId) => [sessionId, "alive"]); + redis.hset(sessionKey, ...args); +}