persistent canvas size (fixes #12)

This commit is contained in:
Grant 2024-05-30 16:34:03 -06:00
parent 1d00b53aba
commit 6294a28c56
7 changed files with 121 additions and 6 deletions

View File

@ -2,6 +2,11 @@
//// THIS FILE WAS AUTOMATICALLY GENERATED (DO NOT MODIFY)
//// ------------------------------------------------------
Table Setting {
key String [pk]
value String [not null]
}
Table User {
sub String [pk]
lastPixelTime DateTime [default: `now()`, not null]

View File

@ -0,0 +1,7 @@
-- CreateTable
CREATE TABLE "Setting" (
"key" TEXT NOT NULL,
"value" TEXT NOT NULL,
CONSTRAINT "Setting_pkey" PRIMARY KEY ("key")
);

View File

@ -14,6 +14,11 @@ datasource db {
url = env("DATABASE_URL")
}
model Setting {
key String @id
value String // this value will be parsed with JSON.parse
}
model User {
sub String @id
lastPixelTime DateTime @default(now()) // the time the last pixel was placed at

View File

@ -5,6 +5,7 @@ import { Logger } from "./lib/Logger";
import { ExpressServer } from "./lib/Express";
import { SocketServer } from "./lib/SocketServer";
import { OpenID } from "./lib/oidc";
import { loadSettings } from "./lib/Settings";
// Validate environment variables
@ -57,10 +58,16 @@ if (!process.env.OIDC_CALLBACK_HOST) {
process.exit(1);
}
Redis.connect();
OpenID.setup().then(() => {
// run startup tasks, all of these need to be completed to serve
Promise.all([
Redis.connect(),
OpenID.setup().then(() => {
Logger.info("Setup OpenID");
});
}),
loadSettings(),
]).then(() => {
Logger.info("Startup tasks have completed, starting server");
const express = new ExpressServer();
new SocketServer(express.httpServer);
const express = new ExpressServer();
new SocketServer(express.httpServer);
});

View File

@ -2,6 +2,7 @@ import { CanvasConfig } from "@sc07-canvas/lib/src/net";
import { prisma } from "./prisma";
import { Redis } from "./redis";
import { SocketServer } from "./SocketServer";
import { Logger } from "./Logger";
class Canvas {
/**
@ -37,7 +38,23 @@ class Canvas {
* @param height
*/
async setSize(width: number, height: number) {
Logger.info("Canvas#setSize has started", {
old: this.canvasSize,
new: [width, height],
});
this.canvasSize = [width, height];
await prisma.setting.upsert({
where: { key: "canvas.size" },
create: {
key: "canvas.size",
value: JSON.stringify({ width, height }),
},
update: {
key: "canvas.size",
value: JSON.stringify({ width, height }),
},
});
// we're about to use the redis keys, make sure they are all updated
await this.pixelsToRedis();
@ -51,6 +68,8 @@ class Canvas {
await this.getPixelsArray().then((pixels) => {
SocketServer.instance.io.emit("canvas", pixels);
});
Logger.info("Canvas#setSize has finished");
}
/**

View File

@ -0,0 +1,31 @@
import Canvas from "./Canvas";
import { Logger } from "./Logger";
import { prisma } from "./prisma";
export const loadSettings = async () => {
Logger.info("Loading settings...");
const sideEffects: Promise<unknown>[] = [];
// canvas size
const canvasSize = await prisma.setting.findFirst({
where: { key: "canvas.size" },
});
if (canvasSize) {
const data = JSON.parse(canvasSize.value);
Logger.info("Canvas size loaded as " + JSON.stringify(data));
sideEffects.push(
Canvas.setSize(data.width, data.height).then(() => {
Logger.info("Canvas size successfully updated");
})
);
} else {
Logger.warn("Setting canvas.size is not set, did you run init_settings?");
}
Logger.info(
"Settings loaded into memory, waiting for side effects to finish..."
);
await Promise.allSettled(sideEffects);
};

View File

@ -0,0 +1,41 @@
import { PrismaClient } from "@prisma/client";
const prisma = new PrismaClient();
// eslint-disable-next-line no-console
const log = (...msg: any[]) => console.log(...msg);
async function main() {
const SETTINGS: { key: string; defaultValue: any }[] = [
{
key: "canvas.size",
defaultValue: {
width: 100,
height: 100,
},
},
];
for (const setting of SETTINGS) {
log("Ensuring setting", setting.key);
await prisma.setting.upsert({
where: { key: setting.key },
update: {},
create: {
key: setting.key,
value: JSON.stringify(setting.defaultValue),
},
});
}
}
main()
.then(async () => {
await prisma.$disconnect();
})
.catch(async (e) => {
// eslint-disable-next-line no-console
console.error(e);
await prisma.$disconnect();
process.exit(1);
});