Skip to content

Commit 0f1ff42

Browse files
committed
fix background foreground schedule issue
1 parent f97fc07 commit 0f1ff42

File tree

3 files changed

+31
-10
lines changed

3 files changed

+31
-10
lines changed

Examples/swift-demo-wallet/swift-demo-wallet/Contexts/AuthContext.swift

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -293,7 +293,6 @@ final class AuthContext: ObservableObject {
293293
try await turnkey.createSession(jwt: jwt, refreshedSessionTTLSeconds: Constants.Turnkey.sessionDuration)
294294

295295
} catch let error as TurnkeyRequestError {
296-
print("Turnkey \(error.statusCode ?? 0): \(error.fullMessage)")
297296
throw error
298297
}
299298
}

Sources/TurnkeySwift/Internal/TurnkeyContext+InternalHelpers.swift

Lines changed: 29 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -71,17 +71,36 @@ extension TurnkeyContext {
7171
expTimestamp: TimeInterval,
7272
buffer: TimeInterval = 5
7373
) {
74+
// cancel any old timer
7475
expiryTasks[sessionKey]?.cancel()
75-
76-
let now = DispatchTime.now()
77-
let interval = max(0, expTimestamp - Date().timeIntervalSince1970 - buffer)
78-
let deadline = now + .milliseconds(Int(interval * 1_000))
79-
76+
77+
let timeLeft = expTimestamp - Date().timeIntervalSince1970
78+
79+
// if already within (or past) the buffer window, we just clear now
80+
if timeLeft <= buffer {
81+
clearSession(for: sessionKey)
82+
return
83+
}
84+
85+
let interval = timeLeft - buffer
86+
let deadline = DispatchTime.now() + .milliseconds(Int(interval * 1_000))
8087
let timer = DispatchSource.makeTimerSource()
88+
8189
timer.schedule(deadline: deadline, leeway: .milliseconds(100))
8290
timer.setEventHandler { [weak self] in
8391
guard let self = self else { return }
84-
92+
93+
// we calculate how much time is left when this handler actually runs
94+
// this is needed because if the app was backgrounded past the expiry,
95+
// the dispatch timer will still fire once the app returns to foreground
96+
// this avoids making a call we know will fail
97+
let currentLeft = expTimestamp - Date().timeIntervalSince1970
98+
if currentLeft <= 0 {
99+
self.clearSession(for: sessionKey)
100+
timer.cancel()
101+
return
102+
}
103+
85104
if let dur = AutoRefreshStore.durationSeconds(for: sessionKey) {
86105
Task {
87106
do {
@@ -90,19 +109,21 @@ extension TurnkeyContext {
90109
sessionKey: sessionKey
91110
)
92111
} catch {
93-
// refreshSession failed so we resort to clearing the session
94112
self.clearSession(for: sessionKey)
95113
}
96114
}
97115
} else {
98116
self.clearSession(for: sessionKey)
99117
}
118+
100119
timer.cancel()
101120
}
121+
102122
timer.resume()
103-
104123
expiryTasks[sessionKey] = timer
105124
}
125+
126+
106127

107128
/// Persists all storage-level artefacts for a session, schedules its expiry
108129
/// timer, and (optionally) registers the session for auto-refresh.

Sources/TurnkeySwift/Public/TurnkeyContext.swift

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,8 +41,9 @@ public final class TurnkeyContext: NSObject, ObservableObject {
4141

4242
private func postInitSetup() {
4343
// clean up expired sessions and pending keys
44-
PendingKeysStore.purge()
4544
SessionRegistryStore.purgeExpiredSessions()
45+
PendingKeysStore.purge()
46+
4647

4748
// restore session and timers after launch
4849
Task { [weak self] in

0 commit comments

Comments
 (0)