You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
[TECH DEBT] Remove SyncWrapper and finish the move from tornado to asyncio (3009.x) #70366
Salt started on tornado before asyncio existed in the standard library. Since then we vendored it (3006.x), moved to a current tornado (3007.x), and replaced most tornado coroutines with async/await (3008.x). What is left is mostly salt.utils.asynchronous.SyncWrapper, which lets sync code call async classes.
SyncWrapper creates a private event loop per instance and blocks on it. This is the source of many open bugs: unclosed-object warnings, nested-wrapper deadlocks, task leaks, and fork/GC cleanup problems. This issue tracks removing it for 3009.x.
The hard part is not tornado itself. It is the sync callers of async code. The fix is to keep a small, well-defined sync boundary and make everything behind it async.
These all had warn_until(3009, ...) and nothing in salt/ used them. Master is 3009.0, so the expired warnings also fail some unit tests in CI (RAISE_DEPRECATIONS_RUNTIME_ERRORS=1). Other expired warn_until(3009) calls (x509, etcd, vsphere, ...) are not part of this work.
Step 2: Decide the sync boundary (medium risk, design first)
Write down which APIs stay sync (for example LocalClient, SaltEvent, the channel factory) and how they run async code (one shared background loop instead of one loop per object)
channel/client.py (ReqChannel.factory) and fileclient.py
utils/http.py: http.query() uses SyncWrapper around tornado's AsyncHTTPClient for the default tornado backend. About 24 callers, so decide first whether to keep the tornado HTTP backend or move to another one
Remove IOLoop and run_sync usage (aioloop() and current_ioloop() helpers)
cli/batch_async.py and utils/channel.py
Update the 54 test files that import tornado
Step 4: Event bus and TCP transport (high risk)
utils/event.py and transport/tcp.py
Decide how get_event() / fire_event() behave when called from sync code and from inside a running loop
Add stress tests for nested calls, fork, and shutdown
Do this in small PRs; several related fixes are still open
Step 5: Remove SyncWrapper (after steps 1-4)
Delete the class in salt/utils/asynchronous.py, or reduce it to the boundary helper from step 2
Remove the __del__ safety nets that only existed for it
Out of scope unless we decide otherwise
Replacing netapi/rest_tornado (about 2.4k lines, 15 of the @gen.coroutine). Dropping tornado as a dependency entirely would need a rewrite of salt-api.
Versions Report
N/A (tracking issue). Applies to 3008.x and master.
Activity
_store_job→fire_event(SyncWrapper join without timeout); wedged workers silently eat requests #69824_store_job→fire_event(SyncWrapper join without timeout); wedged workers silently eat requests #69824