Skip to content

Commit 2db9d6d

Browse files
Implement message deduplication logic in bootstrap.js to enhance session event handling; improving performance and user experience during session management.
1 parent 3438027 commit 2db9d6d

File tree

1 file changed

+56
-8
lines changed

1 file changed

+56
-8
lines changed

resources/js/bootstrap.js

Lines changed: 56 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -497,6 +497,32 @@ if (userID) {
497497
};
498498

499499
const sessionChannel = "BroadcastChannel" in window ? new BroadcastChannel(sessionChannelName) : null;
500+
const recentMessageIds = new Map();
501+
const recentMessageTtlMs = 5000;
502+
const maxRecentMessageIds = 100;
503+
504+
const shouldSkipMessage = (message) => {
505+
if (!message?.id) {
506+
return false;
507+
}
508+
const now = Date.now();
509+
const lastSeen = recentMessageIds.get(message.id);
510+
if (lastSeen && now - lastSeen < recentMessageTtlMs) {
511+
return true;
512+
}
513+
recentMessageIds.set(message.id, now);
514+
if (recentMessageIds.size > maxRecentMessageIds) {
515+
for (const [id, ts] of recentMessageIds) {
516+
if (now - ts > recentMessageTtlMs) {
517+
recentMessageIds.delete(id);
518+
}
519+
if (recentMessageIds.size <= maxRecentMessageIds) {
520+
break;
521+
}
522+
}
523+
}
524+
return false;
525+
};
500526

501527
const broadcastSessionEvent = (type, data = {}) => {
502528
const message = {
@@ -595,21 +621,31 @@ if (userID) {
595621
if (!message || message.from === sessionTabId) {
596622
return;
597623
}
624+
if (shouldSkipMessage(message)) {
625+
return;
626+
}
598627

599628
sessionDebugLog("receive", message);
600629
if (message.type === "warning") {
601630
const time = Number(message.data?.time);
602631
if (time) {
603632
setWarningState(time);
604-
}
605-
if (!isLeader() && window.ProcessMaker.closeSessionModal) {
606-
window.ProcessMaker.closeSessionModal();
633+
if (document.visibilityState === "visible") {
634+
showWarningIfActive();
635+
}
607636
}
608637
return;
609638
}
610639

611640
if (message.type === "renewing") {
612-
setRenewingState(!!message.data?.isRenewing);
641+
const isRenewing = !!message.data?.isRenewing;
642+
setRenewingState(isRenewing);
643+
if (isRenewing) {
644+
clearWarningState();
645+
if (window.ProcessMaker.closeSessionModal) {
646+
window.ProcessMaker.closeSessionModal();
647+
}
648+
}
613649
return;
614650
}
615651

@@ -692,10 +728,16 @@ if (userID) {
692728
if (remainingTime <= 0) {
693729
sessionDebugLog("warning:skip", { remainingTime });
694730
clearWarningState();
731+
if (window.ProcessMaker.closeSessionModal) {
732+
window.ProcessMaker.closeSessionModal();
733+
}
695734
setRenewingState(false);
696735
return;
697736
}
698737
refreshRenewingStateFromStorage();
738+
if (renewingState?.isRenewing) {
739+
return;
740+
}
699741
sessionDebugLog("warning:show", { remainingTime });
700742
// Guard for layouts that don't include the session modal.
701743
if (typeof window.ProcessMaker.sessionModal === "function") {
@@ -720,7 +762,12 @@ if (userID) {
720762
now,
721763
});
722764
if (isVisible) {
723-
writeLeader();
765+
const leaderExpired = !leader || (now - leader.ts >= leaderTtlMs);
766+
if (leaderExpired || leader?.tabId === sessionTabId) {
767+
writeLeader();
768+
}
769+
refreshWarningStateFromStorage();
770+
showWarningIfActive();
724771
}
725772

726773
const leaderNow = isLeader();
@@ -747,12 +794,13 @@ if (userID) {
747794
setInterval(updateLeadership, leaderHeartbeatMs);
748795
window.addEventListener("visibilitychange", () => {
749796
updateLeadership();
797+
// Keep warning state in sync when switching tabs.
798+
refreshWarningStateFromStorage();
799+
showWarningIfActive();
750800
if (isLeader()) {
751-
// Keep warning/timer state in sync when switching tabs.
801+
// Only the leader drives the worker countdown.
752802
refreshSessionStateFromStorage();
753-
refreshWarningStateFromStorage();
754803
startTimeoutWorker(sessionState.timeout);
755-
showWarningIfActive();
756804
}
757805
});
758806

0 commit comments

Comments
 (0)