Enhance Schedule component by resetting time fields on cancel and draft mode toggle; improve session scheduling logic to prevent conflicts by adjusting start times if necessary.

This commit is contained in:
2025-12-03 17:37:35 +05:00
parent 36d5c88bf0
commit b1557453be
2 changed files with 55 additions and 4 deletions
+11 -2
View File
@@ -96,6 +96,9 @@ function Schedule({ selectedDay, slots, events }: Props) {
function handleClickCancel() {
setDraftMode(false);
setStartTime("");
setEndTime("");
setDuration(undefined);
}
async function addSchesuledSession() {
@@ -129,6 +132,9 @@ function Schedule({ selectedDay, slots, events }: Props) {
function handleClickScheduleDemo() {
setDateForInstantStart(undefined);
setStartAt(new Date());
setStartTime("");
setEndTime("");
setDuration(undefined);
setDraftMode(true);
}
@@ -184,9 +190,12 @@ function Schedule({ selectedDay, slots, events }: Props) {
useEffect(() => {
function handleEscKey(e: KeyboardEvent) {
if (!draftMode && e.key !== "Escape") return;
if (!draftMode || e.key !== "Escape") return;
setDraftMode(false);
setStartTime("");
setEndTime("");
setDuration(undefined);
}
document.addEventListener("keyup", handleEscKey, false);
@@ -194,7 +203,7 @@ function Schedule({ selectedDay, slots, events }: Props) {
return () => {
document.removeEventListener("keyup", handleEscKey, false);
};
}, []);
}, [draftMode]);
return (
<div className="relative h-screen overflow-y-auto bg-[#F2F2F2] text-sm">
+44 -2
View File
@@ -4,6 +4,7 @@ import Build from "../models/Build.js";
import Schedule from "../models/Schedule.js";
import {
addMinutes,
addSeconds,
areIntervalsOverlapping,
endOfDay,
isValid,
@@ -78,7 +79,7 @@ router.get("/:buildId", async (req, res) => {
router.post("/", async (req, res) => {
const { companyId, buildId, slot, startAt, client, duration } = req.body;
const startAtISO = parseISO(startAt);
let startAtISO = parseISO(startAt);
if (!isValid(startAtISO)) {
return res.status(400).json({
@@ -96,9 +97,50 @@ router.post("/", async (req, res) => {
});
}
// Check for conflicts at the same minute and adjust time if needed
// This prevents multiple sessions from starting simultaneously on the same server
// We check all sessions regardless of company, build, or slot to prevent server conflicts
let adjustedStartAt = startAtISO;
let maxAttempts = 100; // Prevent infinite loop
let attempts = 0;
while (attempts < maxAttempts) {
// Find sessions starting within 10 seconds of our target time
// This ensures sessions don't start simultaneously on the same session server
const conflictingSessions = await ScheduledSession.find({
startAt: {
$gte: adjustedStartAt,
$lt: addSeconds(adjustedStartAt, 10),
},
});
if (conflictingSessions.length === 0) {
// No conflict found, use this time
break;
}
// Find the latest conflicting session and schedule after it
// This gives the first build time to start and fill video memory
// so the second build will start on another server with more available memory
const latestSession = conflictingSessions.reduce((latest, session) =>
new Date(session.startAt) > new Date(latest.startAt) ? session : latest
);
adjustedStartAt = addSeconds(new Date(latestSession.startAt), 10);
attempts++;
}
if (attempts >= maxAttempts) {
return res.status(400).json({
status: "error",
message: "Не удалось найти свободное время для планирования сеанса",
});
}
startAtISO = adjustedStartAt;
const endAtISO = addMinutes(startAtISO, duration);
// Check for overlapping sessions first
// Check for overlapping sessions in the same slot
const scheduledSessions = await ScheduledSession.find({
companyId,
buildId,