Dispatch-Chron Jobs in Core-Server verschoben #65

This commit is contained in:
PxlLoewe
2025-07-16 00:15:38 -07:00
parent fc698b22d7
commit 844cfa4b56
8 changed files with 62 additions and 21 deletions

View File

@@ -1,3 +1,5 @@
REDIS_HOST=localhost
REDIS_PORT=6379
DISCORD_SERVER_PORT=3005
DISCORD_GUILD_ID=1077269395019141140
DISCORD_OAUTH_CLIENT_ID=930384053344034846

View File

@@ -3,10 +3,19 @@ import express from "express";
import { createServer } from "http";
import router from "routes/router";
import cors from "cors";
import { Server } from "socket.io";
import { createAdapter } from "@socket.io/redis-adapter";
import { pubClient, subClient } from "modules/redis";
import "modules/chron";
const app = express();
const server = createServer(app);
export const io = new Server(server, {
adapter: createAdapter(pubClient, subClient),
cors: {},
});
app.use(cors());
app.use(express.json());
app.use(router);

View File

@@ -0,0 +1,155 @@
import { MissionLog, NotificationPayload, prisma } from "@repo/db";
import { io } from "index";
import cron from "node-cron";
const removeClosedMissions = async () => {
const oldMissions = await prisma.mission.findMany({
where: {
state: "running",
},
});
oldMissions.forEach(async (mission) => {
const lastAlert = (mission.missionLog as unknown as MissionLog[]).find((l) => {
return l.type === "alert-log";
});
const lastAlertTime = lastAlert ? new Date(lastAlert.timeStamp) : null;
const aircraftsInMission = await prisma.connectedAircraft.findMany({
where: {
stationId: {
in: mission.missionStationIds,
},
},
});
const allConnectedAircraftsInIdleStatus = aircraftsInMission.every((a) =>
["1", "2", "6"].includes(a.fmsStatus),
);
const allStationsInMissionChangedFromStatus4to1Or8to1 = mission.missionStationIds.every(
(stationId) => {
const status4Log = (mission.missionLog as unknown as MissionLog[]).findIndex((l) => {
return (
l.type === "station-log" &&
l.data?.stationId === stationId &&
l.data?.newFMSstatus === "4"
);
});
const status8Log = (mission.missionLog as unknown as MissionLog[]).findIndex((l) => {
return (
l.type === "station-log" &&
l.data?.stationId === stationId &&
l.data?.newFMSstatus === "8"
);
});
const status1Log = (mission.missionLog as unknown as MissionLog[]).findIndex((l) => {
return (
l.type === "station-log" &&
l.data?.stationId === stationId &&
l.data?.newFMSstatus === "1"
);
});
const status6Log = (mission.missionLog as unknown as MissionLog[]).findIndex((l) => {
return (
l.type === "station-log" &&
l.data?.stationId === stationId &&
l.data?.newFMSstatus === "6"
);
});
return (
(status4Log !== -1 || status8Log !== -1) &&
(status1Log !== -1 || status6Log !== -1) &&
(status4Log < status1Log ||
status8Log < status1Log ||
status8Log < status6Log ||
status1Log < status6Log)
);
},
);
const missionHastManualReactivation = (mission.missionLog as unknown as MissionLog[]).some(
(l) => l.type === "reopened-log",
);
if (
!allConnectedAircraftsInIdleStatus // If some aircrafts are still active, do not close the mission
)
return;
const now = new Date();
if (!lastAlertTime) return;
// Case 1: Forgotten Mission, last alert more than 3 Hours ago
// Case 2: All stations in mission changed from status 4 to 1 or from status 8 to 1
if (
!(
now.getTime() - lastAlertTime.getTime() > 1000 * 60 * 180 ||
allStationsInMissionChangedFromStatus4to1Or8to1
) ||
missionHastManualReactivation
)
return;
const log: MissionLog = {
type: "completed-log",
auto: true,
timeStamp: new Date().toISOString(),
data: {},
};
const updatedMission = await prisma.mission.update({
where: {
id: mission.id,
},
data: {
state: "finished",
missionLog: {
push: log as any,
},
},
});
io.to("dispatchers").emit("new-mission", { updatedMission });
io.to("dispatchers").emit("notification", {
type: "mission-auto-close",
status: "chron",
message: `Einsatz ${updatedMission.publicId} wurde aufgrund ${allStationsInMissionChangedFromStatus4to1Or8to1 ? "des Freimeldens aller Stationen" : "von Inaktivität"} geschlossen.`,
data: {
missionId: updatedMission.id,
publicMissionId: updatedMission.publicId,
},
} as NotificationPayload);
console.log(`Mission ${mission.id} closed due to inactivity.`);
});
};
const removeConnectedAircrafts = async () => {
const connectedAircrafts = await prisma.connectedAircraft.findMany({
where: {
logoutTime: null,
},
});
connectedAircrafts.forEach(async (aircraft) => {
const lastUpdate = new Date(aircraft.lastHeartbeat);
const now = new Date();
if (now.getTime() - lastUpdate.getTime() > 12 * 60 * 60 * 1000) {
await prisma.connectedAircraft.update({
where: { id: aircraft.id },
data: { logoutTime: now },
});
console.log(`Aircraft ${aircraft.id} disconnected due to inactivity.`);
}
});
};
removeClosedMissions();
cron.schedule("*/1 * * * *", async () => {
try {
await removeClosedMissions();
await removeConnectedAircrafts();
} catch (error) {
console.error("Error on cron job:", error);
}
});

View File

@@ -0,0 +1,13 @@
import { createClient, RedisClientType } from "redis";
export const pubClient: RedisClientType = createClient({
url: `redis://${process.env.REDIS_HOST}:${process.env.REDIS_PORT}`,
});
export const subClient: RedisClientType = pubClient.duplicate();
Promise.all([pubClient.connect(), subClient.connect()]).then(() => {
console.log("Redis connected");
});
pubClient.on("error", (err: unknown) => console.log("Redis Client Error", err));
subClient.on("error", (err: unknown) => console.log("Redis Client Error", err));

View File

@@ -20,6 +20,7 @@
"typescript": "latest"
},
"dependencies": {
"@socket.io/redis-adapter": "^8.3.0",
"axios": "^1.9.0",
"cors": "^2.8.5",
"cron": "^4.3.1",
@@ -30,6 +31,8 @@
"nodemon": "^3.1.10",
"prom-client": "^15.1.3",
"react": "^19.1.0",
"redis": "^5.1.1",
"socket.io": "^4.8.1",
"tsx": "^4.19.4"
}
}