Browse Source

refactor: attempt to further improve system time difference calculation, taking into account backend overload throwing the calculation off

Kristian Vos 2 months ago
parent
commit
8c61681b99
2 changed files with 83 additions and 56 deletions
  1. 6 1
      backend/logic/ws.js
  2. 77 55
      frontend/src/pages/Station/index.vue

+ 6 - 1
backend/logic/ws.js

@@ -19,7 +19,7 @@ let PunishmentsModule;
 class _WSModule extends CoreClass {
 	// eslint-disable-next-line require-jsdoc
 	constructor() {
-		super("ws");
+		super("ws", { concurrency: 2 });
 
 		WSModule = this;
 	}
@@ -629,6 +629,11 @@ class _WSModule extends CoreClass {
 				if (data.length === 0) return socket.dispatch("ERROR", "Not enough arguments specified.");
 				if (typeof data[0] !== "string") return socket.dispatch("ERROR", "First argument must be a string.");
 
+				if (data[0] === "ping" && data.length === 2) {
+					const [, CB_REF] = data;
+					return socket.dispatch("CB_REF", CB_REF.CB_REF, Date.now());
+				}
+
 				const namespaceAction = data[0];
 				if (
 					!namespaceAction ||

+ 77 - 55
frontend/src/pages/Station/index.vue

@@ -118,6 +118,8 @@ const startedAt = ref();
 const pausedAt = ref();
 const stationIdentifier = ref();
 const calculateTimeDifferenceTimeout = ref();
+const systemDifferenceHighDifferenceInARowCount = ref(0);
+const lastSystemDifference = ref(0);
 
 const playerDebugBox = ref();
 const keyboardShortcutsHelper = ref();
@@ -261,7 +263,7 @@ const {
 // const stopVideo = payload =>
 // 	store.dispatch("modals/editSong/stopVideo", payload);
 
-const calculateTimeDifference = (firstRun = false) => {
+const calculateTimeDifference = () => {
 	if (localStorage.getItem("stationNoSystemTimeDifference") === "true") {
 		console.log(
 			"Not calculating time different because 'stationNoSystemTimeDifference' is 'true' in localStorage"
@@ -274,70 +276,90 @@ const calculateTimeDifference = (firstRun = false) => {
 
 	// Store the current time in ms before we send a ping to the backend
 	const beforePing = Date.now();
-	socket.dispatch("apis.ping", res => {
-		if (res.status === "success") {
-			// Store the current time in ms after we receive a pong from the backend
-			const afterPing = Date.now();
-
-			// Calculate the approximate latency between the client and the backend, by taking the time the request took and dividing it in 2
-			// This is not perfect, as the request could take longer to get to the server than be sent back, or the other way around
-			let connectionLatency = (afterPing - beforePing) / 2;
+	socket.dispatch("ping", serverDate => {
+		// Store the current time in ms after we receive a pong from the backend
+		const afterPing = Date.now();
+
+		// Calculate the approximate latency between the client and the backend, by taking the time the request took and dividing it in 2
+		// This is not perfect, as the request could take longer to get to the server than be sent back, or the other way around
+		let connectionLatency = (afterPing - beforePing) / 2;
+		console.log(
+			`Latency between client and server: ${connectionLatency}ms`,
+			beforePing,
+			afterPing
+		);
+
+		// If we have a station latency in localStorage, use that. Can be used for debugging.
+		if (localStorage.getItem("stationLatency")) {
+			connectionLatency = parseInt(
+				localStorage.getItem("stationLatency")
+			);
 			console.log(
-				`Latency between client and server: ${connectionLatency}ms`,
-				beforePing,
-				afterPing
+				`Using latency from local storage: ${connectionLatency}ms`
 			);
+		}
 
-			// If we have a station latency in localStorage, use that. Can be used for debugging.
-			if (localStorage.getItem("stationLatency")) {
-				connectionLatency = parseInt(
-					localStorage.getItem("stationLatency")
-				);
-				console.log(
-					`Using latency from local storage: ${connectionLatency}ms`
-				);
-			}
-
-			// Store the server time in ms that the server had before sending the pong
-			const serverDate = res.data.date;
+		// Store the server time in ms that the server had before sending the pong
+		// const serverDate = res.data.date;
 
-			// Calculates the approximate different in system time that the current client has, compared to the system time of the backend
-			// Takes into account the approximate latency, so if it took approximately 500ms between the backend sending the pong, and the client receiving the pong,
-			// the system time from the backend has to have 500ms added for it to be correct
-			const difference = serverDate + connectionLatency - afterPing;
+		// Calculates the approximate different in system time that the current client has, compared to the system time of the backend
+		// Takes into account the approximate latency, so if it took approximately 500ms between the backend sending the pong, and the client receiving the pong,
+		// the system time from the backend has to have 500ms added for it to be correct
+		const difference = serverDate + connectionLatency - afterPing;
 
-			console.log(
-				`Difference in system time compared to server: ${difference}ms`
-			);
-			if (Math.abs(difference) > 3000) {
-				console.log("System time difference is bigger than 3 seconds.");
-			}
+		console.log(
+			`Difference in system time compared to server: ${difference}ms`
+		);
+		if (Math.abs(difference) > 3000) {
+			console.log("System time difference is bigger than 3 seconds.");
+		}
 
-			// Gets how many ms. difference there is between the last time this function was called and now
-			const differenceBetweenLastTime = Math.abs(
-				systemDifference.value - difference
-			);
-			systemDifference.value = difference;
+		// Gets how many ms. difference there is between the last time this function was called and now
+		const differenceBetweenLastTime = Math.abs(
+			lastSystemDifference.value - difference
+		);
+		const differenceBetweenCurrent = Math.abs(
+			systemDifference.value - difference
+		);
 
-			// By default, we want to re-run this function every 5 minutes
-			let timeoutTime = 1000 * 300;
-			// If this is the first time this command is called, we want to re-run this function after 15 seconds
-			// Also, if the system time difference is more than 500ms different from last time, we also want to re-run after 15 seconds
-			if (firstRun || differenceBetweenLastTime > 500) {
-				timeoutTime = 1000 * 15;
+		// By default, we want to re-run this function every 5 minutes
+		let timeoutTime = 1000 * 300;
+		if (differenceBetweenCurrent > 250) {
+			// If the calculated difference is more than 250ms, there might be something wrong
+			if (differenceBetweenLastTime > 250) {
+				// If there's more than 250ms difference between the last calculated difference, reset the difference in a row count to 1
+				systemDifferenceHighDifferenceInARowCount.value = 1;
+			} else if (systemDifferenceHighDifferenceInARowCount.value < 3) {
+				systemDifferenceHighDifferenceInARowCount.value += 1;
+			} else {
+				// If we're on the third attempt in a row where the difference between last time is less than 250ms, accept it as the difference
+				systemDifferenceHighDifferenceInARowCount.value = 0;
+				systemDifference.value = difference;
 			}
-
+			timeoutTime = 1000 * 10;
+		} else {
+			// Calculated difference is less than 250ms, so we just accept that it's correct
+			systemDifferenceHighDifferenceInARowCount.value = 0;
+			systemDifference.value = difference;
+		}
+		if (systemDifferenceHighDifferenceInARowCount.value > 0) {
 			console.log(
-				`Will attempt to get system time difference again in ${
-					timeoutTime / 1000
-				} seconds.`
+				`System difference high difference in a row count: ${systemDifferenceHighDifferenceInARowCount.value}`
 			);
-			if (calculateTimeDifferenceTimeout.value)
-				clearTimeout(calculateTimeDifferenceTimeout.value);
-			calculateTimeDifferenceTimeout.value = setTimeout(() => {
-				calculateTimeDifference();
-			}, timeoutTime);
 		}
+
+		lastSystemDifference.value = difference;
+
+		console.log(
+			`Will attempt to get system time difference again in ${
+				timeoutTime / 1000
+			} seconds.`
+		);
+		if (calculateTimeDifferenceTimeout.value)
+			clearTimeout(calculateTimeDifferenceTimeout.value);
+		calculateTimeDifferenceTimeout.value = setTimeout(() => {
+			calculateTimeDifference();
+		}, timeoutTime);
 	});
 };
 const updateMediaSessionData = song => {
@@ -1535,7 +1557,7 @@ onMounted(async () => {
 					}
 				);
 
-				calculateTimeDifference(true);
+				calculateTimeDifference();
 
 				console.debug(TAG, "Station join end");
 			} else {