[Swift] Evict preloaded checkout under memory pressure#447
Conversation
|
Warning This pull request is not mergeable via GitHub because a downstack PR is open. Once all requirements are satisfied, merge this PR as a stack on Graphite.
This stack of pull requests is managed by Graphite. Learn more about stacking. |
e917898 to
7279a6f
Compare
43288ca to
03e7678
Compare
7279a6f to
df253fc
Compare
df253fc to
18b6dc0
Compare
Have you been able to reproduce iOS tearing down the preload cache? I believe the premise may be slightly off, though your changes still make sense to respond to the system warning, just want to ensure framing is correct / for anyone else following along Responding to low memory warningsUnder system pressure, iOS will alert running applications to it with the listener you added, it's then on app developers to free up memory, if they dont free up enough memory then the System will start killing apps to free up enough memory. Notably the System will kill an entire app, on a process by process basis, not individual memory allocations like the cache entry which would lead to app instability. xcode/responding-to-low-memory-warnings Valid gap - Missing coverageThe Web Content rendered in the web view (not the cache entry, but the out of process web content) is a unique case as its a separate process and up for collection We should look at whether we can inform the user that the system tore down the content process (I think this can be acheived with `webViewWebContentProcessDidTerminate`` On the PR body, I think the example is a bit misleading for any users that might discover the PR, it demonstrates repopulating the cache immediately after an eviction, which would be counter to the eviction we'd want to recommend they use the DispatchSource to listen for a checkoutPreload = ShopifyCheckoutKit.preload(checkout: url) { state in
if state == .evicted {
// freed under memory pressure — re-warm on the next runloop tick,
// not synchronously from inside this callback
DispatchQueue.main.async {
preloadCheckoutIfNeeded()
}
}
}A few questions
|
18b6dc0 to
6bd0117
Compare
6bd0117 to
00bddec
Compare
00bddec to
1472f29
Compare
1472f29 to
9d501ce
Compare
9d501ce to
5fb8321
Compare
174d3c9 to
0e05590
Compare
5fb8321 to
4950275
Compare
0e05590 to
1ae18db
Compare
e1e680f to
c640e93
Compare
6312803 to
d45eadc
Compare
d799837 to
a2a3439
Compare
23fda26 to
d4fff69
Compare
4e9e834 to
391cb55
Compare
37982e2 to
e3a3ccf
Compare
391cb55 to
6447416
Compare
Install this buildOpen Tophat, select your target device, then click Install. Links open on the Mac running Tophat.
Checkout Kit E2E results
|
e3a3ccf to
6f38ed6
Compare
e035af9 to
6a1fb1e
Compare
6f38ed6 to
200b47f
Compare
200b47f to
d812e9a
Compare
6a1fb1e to
ba71690
Compare
|
Thanks Kieran, this was spot on - you're right that the framing was off 👍 I've rewritten the description to lead with the accurate reason (proactively releasing an idle WebView lowers the host app's jetsam risk) and dropped the circular "closes a hole" justification. The isPresented guard is now framed as guarding a risk this handler would otherwise introduce, not a pre-existing one. Also fixed the misleading code example! (Good catch) On the web content process gap: good catch, this was the real missing coverage. Decided to add I stopped short of auto-reloading a presented session on termination - that recovery UX feels like a follow up. --- One more thing that came out of this: .evicted now carries a reason (.memoryPressure / .webContentProcessTerminated) so consumers can distinguish why the cache was reclaimed. |
ba71690 to
affdb58
Compare
b5368a2 to
ab0b2d8
Compare
ab0b2d8 to
c79c41f
Compare

Adds memory-pressure handling for the preloaded checkout WebView, plus related hardening surfaced in review.
A preloaded checkout keeps an idle
WKWebViewresident in memory until its TTL expires. Under memory pressure iOS asks apps to free memory voluntarily; an app that doesn't free enough is jetsam-killed as a whole process. This adds aDispatchSourceMemoryPressureon the shared cache that proactively releases the idle preloaded WebView when the system signals pressure, lowering the host app's jetsam risk.What's included
evict()funnel that only reclaims an idle preload. A presented checkout is tagged via a newisPresentedflag (set when the view controller takes ownership, cleared on teardown) and is always skipped, so the handler can never tear down an active session.PreloadState.evicted(reason:)—.memoryPressureor.webContentProcessTerminated— so consumers can distinguish why the cache was reclaimed..webContentProcessTerminated); a presented checkout surfaces an error to the delegate rather than sitting blank.invalidate()respects presentation: the publicinvalidate()no longer detaches the bridge of a presented checkout — it only clears an idle preload.preload()declines to warm the cache, so re-warming can't refill a starved system.present()is unaffected and always loads.Eviction is automatic — consumers observe
.evictedto know the cache was reclaimed and can re-warm at the next appropriate opportunity:Why ship this
DispatchSourceMemoryPressureand web-content-process termination is the idiomatic iOS behaviour for a reclaimable cache; proactively releasing an idle checkout WebView lowers the host app's jetsam risk under pressure.isPresentedguard ensures neither the pressure handler norinvalidate()can tear down a presented checkout.PreloadStatelifecycle from [Swift] Add preload state observability #445, keeping the kits — and the React Native wrapper on top of them — symmetric.