From da85b54fc2f627123cc7ba0a73a69f77443853a5 Mon Sep 17 00:00:00 2001 From: Alex P Date: Fri, 17 Oct 2025 10:44:18 +0300 Subject: [PATCH] [WIP] Optimizations: code readiness optimizations --- hidrpc.go | 4 ++-- native.go | 3 +++ session_manager.go | 34 ++++++++++++++++----------------- ui/src/components/ActionBar.tsx | 9 ++++++--- 4 files changed, 27 insertions(+), 23 deletions(-) diff --git a/hidrpc.go b/hidrpc.go index 1a7e1d3c..3f1bc0b3 100644 --- a/hidrpc.go +++ b/hidrpc.go @@ -146,8 +146,8 @@ const baseExtension = expectedRate + maxLateness // 100ms extension on perfect t const maxStaleness = 225 * time.Millisecond // discard ancient packets outright func handleHidRPCKeypressKeepAlive(session *Session) error { - // Update LastActive to prevent session timeout (jiggler sends every 50ms) - sessionManager.UpdateLastActive(session.ID) + // NOTE: Do NOT update LastActive here - jiggler keep-alives are automated, + // not human input. Only actual keyboard/mouse input should prevent timeout. session.keepAliveJitterLock.Lock() defer session.keepAliveJitterLock.Unlock() diff --git a/native.go b/native.go index 06781bec..da667a72 100644 --- a/native.go +++ b/native.go @@ -62,6 +62,9 @@ func initNative(systemVersion *semver.Version, appVersion *semver.Version) { Str("sessionID", s.ID). Err(err). Msg("error writing sample to session") + } else { + // Update LastActive when video frame successfully sent (prevents observer timeout) + sessionManager.UpdateLastActive(s.ID) } } }) diff --git a/session_manager.go b/session_manager.go index aad0e7a9..174203a1 100644 --- a/session_manager.go +++ b/session_manager.go @@ -84,10 +84,6 @@ type TransferBlacklistEntry struct { var ( lastBroadcast time.Time broadcastMutex sync.Mutex - - // Pre-allocated event maps to reduce allocations - modePrimaryEvent = map[string]string{"mode": "primary"} - modeObserverEvent = map[string]string{"mode": "observer"} ) type SessionManager struct { @@ -413,18 +409,20 @@ func (sm *SessionManager) RemoveSession(sessionID string) { // Only add grace period if this is NOT an intentional logout if !isIntentionalLogout { // Limit grace period entries to prevent memory exhaustion + // Evict the entry that will expire soonest (oldest expiration time) for len(sm.reconnectGrace) >= maxGracePeriodEntries { - var oldestID string - var oldestTime time.Time + var evictID string + var earliestExpiration time.Time for id, graceTime := range sm.reconnectGrace { - if oldestTime.IsZero() || graceTime.Before(oldestTime) { - oldestID = id - oldestTime = graceTime + // Find the grace period that expires first (earliest time) + if earliestExpiration.IsZero() || graceTime.Before(earliestExpiration) { + evictID = id + earliestExpiration = graceTime } } - if oldestID != "" { - delete(sm.reconnectGrace, oldestID) - delete(sm.reconnectInfo, oldestID) + if evictID != "" { + delete(sm.reconnectGrace, evictID) + delete(sm.reconnectInfo, evictID) } else { break } @@ -668,7 +666,7 @@ func (sm *SessionManager) RequestPrimary(sessionID string) error { err := sm.transferPrimaryRole("", sessionID, "initial_promotion", "first session auto-promotion") if err == nil { // Send mode change event after promoting - writeJSONRPCEvent("modeChanged", modePrimaryEvent, session) + writeJSONRPCEvent("modeChanged", map[string]string{"mode": "primary"}, session) go sm.broadcastSessionListUpdate() } return err @@ -755,7 +753,7 @@ func (sm *SessionManager) ReleasePrimary(sessionID string) error { // Send mode change event for promoted session go func() { if promotedSession := sessionManager.GetSession(promotedSessionID); promotedSession != nil { - writeJSONRPCEvent("modeChanged", modePrimaryEvent, promotedSession) + writeJSONRPCEvent("modeChanged", map[string]string{"mode": "primary"}, promotedSession) } }() } else { @@ -797,13 +795,13 @@ func (sm *SessionManager) TransferPrimary(fromID, toID string) error { // Send events in goroutines to avoid holding lock go func() { if fromSession := sessionManager.GetSession(fromID); fromSession != nil { - writeJSONRPCEvent("modeChanged", modeObserverEvent, fromSession) + writeJSONRPCEvent("modeChanged", map[string]string{"mode": "observer"}, fromSession) } }() go func() { if toSession := sessionManager.GetSession(toID); toSession != nil { - writeJSONRPCEvent("modeChanged", modePrimaryEvent, toSession) + writeJSONRPCEvent("modeChanged", map[string]string{"mode": "primary"}, toSession) } sm.broadcastSessionListUpdate() }() @@ -861,13 +859,13 @@ func (sm *SessionManager) ApprovePrimaryRequest(currentPrimaryID, requesterID st // Send events after releasing lock to avoid deadlock go func() { if demotedSession := sessionManager.GetSession(currentPrimaryID); demotedSession != nil { - writeJSONRPCEvent("modeChanged", modeObserverEvent, demotedSession) + writeJSONRPCEvent("modeChanged", map[string]string{"mode": "observer"}, demotedSession) } }() go func() { if promotedSession := sessionManager.GetSession(requesterID); promotedSession != nil { - writeJSONRPCEvent("modeChanged", modePrimaryEvent, promotedSession) + writeJSONRPCEvent("modeChanged", map[string]string{"mode": "primary"}, promotedSession) } sm.broadcastSessionListUpdate() }() diff --git a/ui/src/components/ActionBar.tsx b/ui/src/components/ActionBar.tsx index 840f0ba8..d978ef64 100644 --- a/ui/src/components/ActionBar.tsx +++ b/ui/src/components/ActionBar.tsx @@ -52,7 +52,6 @@ export default function Actionbar({ const response = JSON.parse(event.data); if (response.id === id && response.result) { setSessions(response.result); - rpcDataChannel.removeEventListener("message", handler); } } catch { // Ignore parse errors for non-JSON messages @@ -62,10 +61,14 @@ export default function Actionbar({ rpcDataChannel.addEventListener("message", handler); rpcDataChannel.send(message); - // Clean up after timeout - setTimeout(() => { + const timeoutId = setTimeout(() => { rpcDataChannel.removeEventListener("message", handler); }, 5000); + + return () => { + clearTimeout(timeoutId); + rpcDataChannel.removeEventListener("message", handler); + }; } }, [rpcDataChannel, sessions.length, setSessions]);