Update
This commit is contained in:
@@ -38,29 +38,6 @@ const io = new Server(server, {
|
||||
|
||||
jobService.setSocket(io);
|
||||
|
||||
let counter = 0;
|
||||
let counterTimer: NodeJS.Timeout | null = null;
|
||||
|
||||
const broadcastCounter = () => {
|
||||
io.emit("counter:update", { value: counter });
|
||||
};
|
||||
|
||||
const startCounter = () => {
|
||||
if (counterTimer) return;
|
||||
counterTimer = setInterval(() => {
|
||||
counter += 1;
|
||||
broadcastCounter();
|
||||
}, 1000);
|
||||
};
|
||||
|
||||
const stopCounter = () => {
|
||||
if (counterTimer) {
|
||||
clearInterval(counterTimer);
|
||||
counterTimer = null;
|
||||
}
|
||||
io.emit("counter:stopped", { value: counter });
|
||||
};
|
||||
|
||||
io.use((socket, next) => {
|
||||
const token = socket.handshake.auth?.token as string | undefined;
|
||||
if (!token) {
|
||||
@@ -81,20 +58,6 @@ io.on("connection", (socket) => {
|
||||
socket.emit("pong", "pong");
|
||||
});
|
||||
|
||||
socket.on("counter:start", (ack?: (payload: { running: boolean; value: number }) => void) => {
|
||||
startCounter();
|
||||
ack?.({ running: true, value: counter });
|
||||
});
|
||||
|
||||
socket.on("counter:stop", (ack?: (payload: { running: boolean; value: number }) => void) => {
|
||||
stopCounter();
|
||||
ack?.({ running: false, value: counter });
|
||||
});
|
||||
|
||||
socket.on("counter:status", (ack?: (payload: { running: boolean; value: number }) => void) => {
|
||||
ack?.({ running: !!counterTimer, value: counter });
|
||||
});
|
||||
|
||||
socket.on("job:subscribe", async ({ jobId }: { jobId: string }) => {
|
||||
if (!jobId) return;
|
||||
socket.join(`job:${jobId}`);
|
||||
|
||||
@@ -25,6 +25,52 @@ router.get("/", async (_req, res) => {
|
||||
);
|
||||
});
|
||||
|
||||
router.get("/metrics/summary", async (_req, res) => {
|
||||
const since = new Date();
|
||||
since.setDate(since.getDate() - 7);
|
||||
|
||||
const dailyStats = await JobRun.aggregate([
|
||||
{ $match: { startedAt: { $gte: since } } },
|
||||
{
|
||||
$group: {
|
||||
_id: { $dateToString: { format: "%Y-%m-%d", date: "$startedAt" } },
|
||||
total: { $sum: 1 },
|
||||
success: {
|
||||
$sum: {
|
||||
$cond: [{ $eq: ["$status", "success"] }, 1, 0]
|
||||
}
|
||||
},
|
||||
failed: {
|
||||
$sum: {
|
||||
$cond: [{ $eq: ["$status", "failed"] }, 1, 0]
|
||||
}
|
||||
},
|
||||
avgDurationMs: { $avg: "$durationMs" }
|
||||
}
|
||||
},
|
||||
{ $sort: { _id: 1 } }
|
||||
]);
|
||||
|
||||
const recentRuns = await JobRun.find()
|
||||
.sort({ startedAt: -1 })
|
||||
.limit(10)
|
||||
.populate("job", "name repoUrl status")
|
||||
.lean();
|
||||
|
||||
const successTotal = dailyStats.reduce((acc, d) => acc + (d.success || 0), 0);
|
||||
const totalRuns = dailyStats.reduce((acc, d) => acc + (d.total || 0), 0);
|
||||
const successRate = totalRuns ? Math.round((successTotal / totalRuns) * 100) : 0;
|
||||
|
||||
return res.json({
|
||||
dailyStats,
|
||||
recentRuns,
|
||||
totals: {
|
||||
successRate,
|
||||
totalRuns
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
router.get("/:id", async (req, res) => {
|
||||
const { id } = req.params;
|
||||
const job = await Job.findById(id).lean();
|
||||
|
||||
@@ -34,8 +34,15 @@ function runCommand(command: string, cwd: string, onData: (chunk: string) => voi
|
||||
env: { ...process.env, CI: process.env.CI || "1" }
|
||||
});
|
||||
|
||||
child.stdout.on("data", (data) => onData(cleanOutput(data.toString())));
|
||||
child.stderr.on("data", (data) => onData(cleanOutput(data.toString())));
|
||||
const emitLines = (chunk: Buffer) => {
|
||||
const cleaned = cleanOutput(chunk.toString()).replace(/\r\n|\r/g, "\n");
|
||||
cleaned.split("\n").forEach((line) => {
|
||||
onData(line);
|
||||
});
|
||||
};
|
||||
|
||||
child.stdout.on("data", emitLines);
|
||||
child.stderr.on("data", emitLines);
|
||||
|
||||
child.on("error", (err) => {
|
||||
onData(`Hata: ${err.message}`);
|
||||
|
||||
Reference in New Issue
Block a user