feat: Enhance user status update throttling with force update mechanism
- Increase status update intervals to reduce unnecessary network calls - Implement force update every 5 minutes regardless of status change - Add detailed logging for skipped status updates - Include additional context in status update payload (reason, time since last update)
- commit
- afa6c9d9131ee9c2ebde985f40d39315b28297ca
- author
- Kit · · 2025-02-15 08:34 UTC
- parent
- a3b34f2
- signature
- SSH Unverified
SHA256:H91DFuEG4jpk5edzLA4aUKkpv4zv9Q339ipRmkph6TkThe key is unknown
1 file · +19 -8
M src/routes/+layout.svelte +19 -8
| @@ -13,22 +13,31 @@ | |||
| 13 | 13 | // New throttle state variables | |
| 14 | 14 | let lastSentStatus = $state<string | null>(null); | |
| 15 | 15 | let lastStatusSentAt = $state<number>(0); | |
| 16 | - | const STATUS_UPDATE_INTERVAL = 5000; // 5 seconds | |
| 17 | - | const THROTTLE_TIME_MS = 4000; // 4 seconds to prevent edge case overlaps | |
| 16 | + | const STATUS_UPDATE_INTERVAL = 15000; // Changed to 15 seconds | |
| 17 | + | const THROTTLE_TIME_MS = 10000; // Changed to 10 seconds to prevent edge case overlaps | |
| 18 | + | const FORCE_UPDATE_INTERVAL = 5 * 60000; // Force update every 5 minutes regardless of status change | |
| 18 | 19 | ||
| 19 | 20 | async function updateUserStatus(status: 'online' | 'offline' | 'busy') { | |
| 20 | 21 | if (!data.user?.id || updateInProgress) return; | |
| 21 | 22 | ||
| 22 | - | // Throttle duplicate status updates | |
| 23 | + | const now = Date.now(); | |
| 24 | + | const timeSinceLastUpdate = now - lastStatusSentAt; | |
| 25 | + | ||
| 26 | + | // Only update if: | |
| 27 | + | // 1. Status has changed OR | |
| 28 | + | // 2. We haven't updated in FORCE_UPDATE_INTERVAL (5 minutes) | |
| 23 | 29 | if ( | |
| 24 | - | status === lastSentStatus && | |
| 25 | - | Date.now() - lastStatusSentAt < THROTTLE_TIME_MS | |
| 30 | + | status === lastSentStatus && | |
| 31 | + | timeSinceLastUpdate < FORCE_UPDATE_INTERVAL && | |
| 32 | + | timeSinceLastUpdate < THROTTLE_TIME_MS | |
| 26 | 33 | ) { | |
| 27 | - | console.debug('Throttling duplicate status update:', status); | |
| 34 | + | console.debug('Skipping status update - no change and within throttle period:', { | |
| 35 | + | status, | |
| 36 | + | timeSinceLastUpdate, | |
| 37 | + | lastUpdate: new Date(lastStatusSentAt).toISOString() | |
| 38 | + | }); | |
| 28 | 39 | return; | |
| 29 | 40 | } | |
| 30 | - | lastSentStatus = status; | |
| 31 | - | lastStatusSentAt = Date.now(); | |
| 32 | 41 | ||
| 33 | 42 | updateInProgress = true; | |
| 34 | 43 | const timestamp = new Date().toISOString(); | |
| @@ -36,6 +45,8 @@ | |||
| 36 | 45 | userId: data.user.id, | |
| 37 | 46 | status, | |
| 38 | 47 | timestamp, | |
| 48 | + | reason: status !== lastSentStatus ? 'status_changed' : 'force_update', | |
| 49 | + | timeSinceLastUpdate, | |
| 39 | 50 | trigger: new Error().stack?.split('\n')[2]?.trim(), | |
| 40 | 51 | hasSession: true, | |
| 41 | 52 | cookiePresent: browser ? document.cookie.includes('session=') : false | |
| @@ -13,22 +13,31 @@ | |||||
| 13 | // New throttle state variables | 13 | // New throttle state variables | ||
| 14 | let lastSentStatus = $state<string | null>(null); | 14 | let lastSentStatus = $state<string | null>(null); | ||
| 15 | let lastStatusSentAt = $state<number>(0); | 15 | let lastStatusSentAt = $state<number>(0); | ||
| 16 | - | const STATUS_UPDATE_INTERVAL = 5000; // 5 seconds | 16 | + | const STATUS_UPDATE_INTERVAL = 15000; // Changed to 15 seconds |
| 17 | - | const THROTTLE_TIME_MS = 4000; // 4 seconds to prevent edge case overlaps | 17 | + | const THROTTLE_TIME_MS = 10000; // Changed to 10 seconds to prevent edge case overlaps |
| 18 | + | const FORCE_UPDATE_INTERVAL = 5 * 60000; // Force update every 5 minutes regardless of status change | |||
| 18 | 19 | ||||
| 19 | async function updateUserStatus(status: 'online' | 'offline' | 'busy') { | 20 | async function updateUserStatus(status: 'online' | 'offline' | 'busy') { | ||
| 20 | if (!data.user?.id || updateInProgress) return; | 21 | if (!data.user?.id || updateInProgress) return; | ||
| 21 | 22 | ||||
| 22 | - | // Throttle duplicate status updates | 23 | + | const now = Date.now(); |
| 24 | + | const timeSinceLastUpdate = now - lastStatusSentAt; | |||
| 25 | + | ||||
| 26 | + | // Only update if: | |||
| 27 | + | // 1. Status has changed OR | |||
| 28 | + | // 2. We haven't updated in FORCE_UPDATE_INTERVAL (5 minutes) | |||
| 23 | if ( | 29 | if ( | ||
| 24 | - | status === lastSentStatus && | 30 | + | status === lastSentStatus && |
| 25 | - | Date.now() - lastStatusSentAt < THROTTLE_TIME_MS | 31 | + | timeSinceLastUpdate < FORCE_UPDATE_INTERVAL && |
| 32 | + | timeSinceLastUpdate < THROTTLE_TIME_MS | |||
| 26 | ) { | 33 | ) { | ||
| 27 | - | console.debug('Throttling duplicate status update:', status); | 34 | + | console.debug('Skipping status update - no change and within throttle period:', { |
| 35 | + | status, | |||
| 36 | + | timeSinceLastUpdate, | |||
| 37 | + | lastUpdate: new Date(lastStatusSentAt).toISOString() | |||
| 38 | + | }); | |||
| 28 | return; | 39 | return; | ||
| 29 | } | 40 | } | ||
| 30 | - | lastSentStatus = status; | |||
| 31 | - | lastStatusSentAt = Date.now(); | |||
| 32 | 41 | ||||
| 33 | updateInProgress = true; | 42 | updateInProgress = true; | ||
| 34 | const timestamp = new Date().toISOString(); | 43 | const timestamp = new Date().toISOString(); | ||
| @@ -36,6 +45,8 @@ | |||||
| 36 | userId: data.user.id, | 45 | userId: data.user.id, | ||
| 37 | status, | 46 | status, | ||
| 38 | timestamp, | 47 | timestamp, | ||
| 48 | + | reason: status !== lastSentStatus ? 'status_changed' : 'force_update', | |||
| 49 | + | timeSinceLastUpdate, | |||
| 39 | trigger: new Error().stack?.split('\n')[2]?.trim(), | 50 | trigger: new Error().stack?.split('\n')[2]?.trim(), | ||
| 40 | hasSession: true, | 51 | hasSession: true, | ||
| 41 | cookiePresent: browser ? document.cookie.includes('session=') : false | 52 | cookiePresent: browser ? document.cookie.includes('session=') : false | ||