What's been accomplished in this session:

1. ContextVar is the primary logcontext storage — _thread_local removed from current_context()/set_current_context()
  2. Test base class switched from twisted.trial.unittest.TestCase to stdlib unittest.TestCase — with reimplemented successResultOf, failureResultOf, assertNoResult, assertApproximates, assertRaises, assertFailure, mktemp,
  _callTestMethod
  3. All 230 Twisted imports wrapped in try/except ImportError across production and test code
  4. All 5 @defer.inlineCallbacks converted to async def + await
  5. All module_api functions converted from returning Deferreds to async functions
  6. CancelledError switched to asyncio.CancelledError in 17 files (2 intentionally keep both)
  7. yieldable_gather_results rewritten to use asyncio.gather (with Twisted fallback)
  8. gather_optional_coroutines rewritten to use asyncio.gather
  9. Twisted removed from required dependencies in pyproject.toml
  10. All 21 synapse modules verified to import without Twisted installed

  What remains (needs reactor switch):

  - 12 defer.ensureDeferred — reactor entry points
  - 22 defer.Deferred() — in Linearizer, ReadWriteLock, AwakenableSleeper, DeferredEvent
  - 21 defer.gatherResults — in old implementations + fallback paths
  - 11 defer.succeed/fail — immediate value wrapping
  - 13 defer.TimeoutError — in timeout_deferred and callers
  - reactor.run() → needs asyncio.run() (requires aiohttp server, NativeClock)
  - reactor.listenTCP/SSL → needs aiohttp server

  These all depend on each other — they can only be swapped when the entire runtime switches from reactor.run() to asyncio.run(), which requires replacing the HTTP server (SynapseSite → aiohttp), the Clock (Clock →
  NativeClock), and the listener setup.
This commit is contained in:
Matthew Hodgson
2026-03-21 21:20:51 +00:00
parent 56ffcebdcf
commit b301afaa70
+7 -1
View File
@@ -315,7 +315,13 @@ def register_start(
os._exit(1)
clock = hs.get_clock()
clock.call_when_running(lambda: defer.ensureDeferred(wrapper()))
# Schedule the startup coroutine to run when the event loop starts
try:
clock.call_when_running(lambda: defer.ensureDeferred(wrapper()))
except Exception:
# Fallback if defer is not available
import asyncio as _asyncio
clock.call_when_running(lambda: _asyncio.ensure_future(wrapper()))
def listen_metrics(