Repository navigation
Conversation
…g behind fetches Every call into Python was serialised behind PythonLock because FindMy.py's sync AppleAccount enters its event loop per call with run_until_complete. A first import walks thousands of key indices inside a single fetch_location, so the iCloud screen waited minutes for its turn (parawanderer#126). account_loop.attach now swaps the account's _evt_loop for a stand-in that hands coroutines to the real loop, running forever on a thread of its own. Same loop, same session, same identity. The account is still used by one operation at a time: request_pet swaps the login state out across a GSA round trip, so a report request running beside it would read a missing dsid. Ordinary calls take the account's turn for their whole length; a location fetch inside interleaving() takes it once per fetch_raw_reports, so an iCloud step waits for one request rather than the whole walk. PythonICloudService no longer takes PythonLock. Location fetches still do, against each other. The "waiting for the location check" caption is gone with the wait it described. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A failed sign-in or an abandoned code screen never reaches closeAccount. That used to cost two sockets until the collector ran; with the loop on its own thread it would also leave a thread idling forever. A finaliser on the account now lets whatever is already on the loop finish - including the close FindMy.py's own finaliser schedules - and then stops the thread. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…aise The emulator suite's two iCloud bridge classes built accounts with a bare event loop, which openSession now refuses. They attach it the way main does. attach no longer assumes fetch_raw_reports exists or that the account can be weakly referenced. Without the method the loop still gets its thread and a fetch inside interleaving() takes one whole turn, as before; an exception there would fail the restore and sign the user out. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This was referenced Oct 20, 2026
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes #126.
Problem
Every call into Python held
PythonLock, because FindMy.py's syncAppleAccountenters its event loop per call withrun_until_complete. A first import walks thousands of key indices inside a singlefetch_location, so opening the iCloud screen during one meant waiting minutes.Change
app/src/main/python/account_loop.py(new):attach(account)replaces_evt_loopwith a stand-in that submits coroutines to the real loop, which runs forever on its own thread. Same loop, session and identity.request_pet(called when a keychain session opens) swaps the login state across a GSA round trip, so a report request running beside it would read a missingdsid. Ordinary calls hold the account's turn for their whole length; location fetches run insideinterleaving()and take the turn once perfetch_raw_reports. An iCloud step therefore waits for at most one request.main.pyattaches on sign-in and restore, detaches incloseAccount, and wraps the two fetch call sites ininterleaving(). An account dropped without being closed stops its thread via a finaliser.attachdegrades rather than raising: if the pinned FindMy.py ever stops exposingfetch_raw_reportsor_evt_loop, the account still gets its thread (fetches then take whole turns) or is left as it was.icloud_bridge.openSessionrefuses an account whose loop is not attached. The iCloud test double andOpeningARealICloudSessionTestattach their accounts.PythonICloudServiceandFetchFromICloudActivityno longer takePythonLock. Location fetches still take it against each other.icloud_loading_waiting_for_location_checkfrom all locales withscripts/add_strings.py --remove; that wait no longer exists.Testing
test_account_loop.py: 17 tests against the real pinnedAppleAccountwith only the network replaced. They cover an iCloud call completing mid-walk, no overlap with an in-flight request, the reentrant turn, closing with calls queued, abandoned accounts, wheremain.pyattaches, and the degraded paths. Each core assertion was confirmed to fail with the corresponding part removed.add_strings.py --checkpasses.testDebugUnitTest: 471 JVM tests, 0 failures. Static checks, build and the emulator suite are green on the fork: Run the account's loop on its own thread so iCloud calls stop queueing behind fetches lazzurs/OpenTagViewer#1otp()/machine()) from the loop thread rather than an Rx thread. The branch merges cleanly with Sign in as the Android device the ADI libraries actually are — fixes #248 #261, so it can be re-tested on top of it.🤖 Generated with Claude Code