|
|
@ -529,11 +529,37 @@ public final class SonioxSessionPool { |
|
|
public static let shared = SonioxSessionPool() |
|
|
public static let shared = SonioxSessionPool() |
|
|
|
|
|
|
|
|
private var prewarmedSession: SonioxLiveSession? |
|
|
private var prewarmedSession: SonioxLiveSession? |
|
|
|
|
|
private var prewarmedSessionCreatedAt: Date = Date() |
|
|
private let lock = NSLock() |
|
|
private let lock = NSLock() |
|
|
private var isPrewarming = false |
|
|
private var isPrewarming = false |
|
|
|
|
|
|
|
|
private init() { |
|
|
private init() { |
|
|
prewarmNextSession() |
|
|
prewarmNextSession() |
|
|
|
|
|
setupSleepWakeObservers() |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
private func setupSleepWakeObservers() { |
|
|
|
|
|
NSWorkspace.shared.notificationCenter.addObserver(forName: NSWorkspace.willSleepNotification, object: nil, queue: .main) { [weak self] _ in |
|
|
|
|
|
print("SonioxSessionPool: Mac entering sleep. Discarding pre-warmed session.") |
|
|
|
|
|
self?.discardPrewarmedSession() |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
NSWorkspace.shared.notificationCenter.addObserver(forName: NSWorkspace.didWakeNotification, object: nil, queue: .main) { [weak self] _ in |
|
|
|
|
|
print("SonioxSessionPool: Mac woke from sleep. Re-priming fresh session in 2.0s...") |
|
|
|
|
|
self?.discardPrewarmedSession() |
|
|
|
|
|
DispatchQueue.main.asyncAfter(deadline: .now() + 2.0) { |
|
|
|
|
|
self?.prewarmNextSession() |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
public func discardPrewarmedSession() { |
|
|
|
|
|
lock.lock() |
|
|
|
|
|
prewarmedSession?.stopKeepAliveHeartbeat() |
|
|
|
|
|
prewarmedSession?.cancel() |
|
|
|
|
|
prewarmedSession = nil |
|
|
|
|
|
isPrewarming = false |
|
|
|
|
|
lock.unlock() |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
public func prewarmNextSession() { |
|
|
public func prewarmNextSession() { |
|
|
@ -541,8 +567,11 @@ public final class SonioxSessionPool { |
|
|
defer { lock.unlock() } |
|
|
defer { lock.unlock() } |
|
|
|
|
|
|
|
|
if let existing = prewarmedSession, existing.isReady { |
|
|
if let existing = prewarmedSession, existing.isReady { |
|
|
|
|
|
let age = Date().timeIntervalSince(prewarmedSessionCreatedAt) |
|
|
|
|
|
if age < 45.0 { |
|
|
return |
|
|
return |
|
|
} |
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
if isPrewarming { return } |
|
|
if isPrewarming { return } |
|
|
isPrewarming = true |
|
|
isPrewarming = true |
|
|
@ -562,6 +591,7 @@ public final class SonioxSessionPool { |
|
|
self.lock.lock() |
|
|
self.lock.lock() |
|
|
session.startKeepAliveHeartbeat() |
|
|
session.startKeepAliveHeartbeat() |
|
|
self.prewarmedSession = session |
|
|
self.prewarmedSession = session |
|
|
|
|
|
self.prewarmedSessionCreatedAt = Date() |
|
|
self.isPrewarming = false |
|
|
self.isPrewarming = false |
|
|
self.lock.unlock() |
|
|
self.lock.unlock() |
|
|
print("SonioxSessionPool: Fresh prewarmed session initialized & heartbeat started.") |
|
|
print("SonioxSessionPool: Fresh prewarmed session initialized & heartbeat started.") |
|
|
@ -570,18 +600,14 @@ public final class SonioxSessionPool { |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
public func reconnectAll() { |
|
|
public func reconnectAll() { |
|
|
lock.lock() |
|
|
|
|
|
prewarmedSession?.stopKeepAliveHeartbeat() |
|
|
|
|
|
prewarmedSession?.cancel() |
|
|
|
|
|
prewarmedSession = nil |
|
|
|
|
|
isPrewarming = false |
|
|
|
|
|
lock.unlock() |
|
|
|
|
|
|
|
|
discardPrewarmedSession() |
|
|
prewarmNextSession() |
|
|
prewarmNextSession() |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
public func acquireSession() -> SonioxLiveSession { |
|
|
public func acquireSession() -> SonioxLiveSession { |
|
|
lock.lock() |
|
|
lock.lock() |
|
|
let session = prewarmedSession |
|
|
let session = prewarmedSession |
|
|
|
|
|
let createdAt = prewarmedSessionCreatedAt |
|
|
prewarmedSession = nil |
|
|
prewarmedSession = nil |
|
|
lock.unlock() |
|
|
lock.unlock() |
|
|
|
|
|
|
|
|
@ -590,13 +616,17 @@ public final class SonioxSessionPool { |
|
|
self?.prewarmNextSession() |
|
|
self?.prewarmNextSession() |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
if let session = session, session.isReady { |
|
|
|
|
|
|
|
|
let age = Date().timeIntervalSince(createdAt) |
|
|
|
|
|
if let session = session, session.isReady && age < 60.0 { |
|
|
session.stopKeepAliveHeartbeat() |
|
|
session.stopKeepAliveHeartbeat() |
|
|
print("SonioxSessionPool: Acquired HOT prewarmed session (0ms connect delay!)") |
|
|
|
|
|
|
|
|
print("SonioxSessionPool: Acquired HOT prewarmed session (age: \(String(format: "%.1f", age))s, 0ms connect delay!)") |
|
|
return session |
|
|
return session |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
print("SonioxSessionPool: Prewarmed session not ready yet, creating immediate on-demand session.") |
|
|
|
|
|
|
|
|
session?.stopKeepAliveHeartbeat() |
|
|
|
|
|
session?.cancel() |
|
|
|
|
|
|
|
|
|
|
|
print("SonioxSessionPool: Prewarmed session not ready/stale (age: \(String(format: "%.1f", age))s), creating immediate on-demand session.") |
|
|
let hints = SonioxSettings.shared.language.hints |
|
|
let hints = SonioxSettings.shared.language.hints |
|
|
return SonioxLiveSession(languageHints: hints) |
|
|
return SonioxLiveSession(languageHints: hints) |
|
|
} |
|
|
} |
|
|
|