Skip to content

spawn io worker for drive subsystem (SYN-10499)#4567

Merged
vEpiphyte merged 53 commits intomasterfrom
visi-io-spawn
Apr 20, 2026
Merged

spawn io worker for drive subsystem (SYN-10499)#4567
vEpiphyte merged 53 commits intomasterfrom
visi-io-spawn

Conversation

@invisig0th
Copy link
Copy Markdown
Contributor

@invisig0th invisig0th commented Nov 6, 2025

Overview

This branch introduces a dedicated IO worker subprocess for the Cell Drive subsystem.
The Drive's LMDB slab is migrated out of the shared Cell slab into its own file
(slabs/drive.lmdb) and is served from a separate process via Unix domain sockets
and the existing Telepath RPC framework. The change also modernizes dyndeps naming
conventions and improves subprocess coverage collection in CI.


New Files

File Purpose
synapse/lib/spawner.py Generic IO worker spawner framework (SpawnerMixin, _ioWorkProc, _spawnerWait)
synapse/tests/test_lib_spawner.py Tests for spawner timeout, OSError, and signal-handler paths
synapse/tests/test_lib_drive.py Drive tests (moved out of test_lib_cell.py) plus backup-sync test
.coveragerc.main Main-process coverage config (no multiprocessing tracer)
changes/c56856d0929e4a71fde0d98fc77ddeb5.yaml Changelog: drive slab migration
changes/fb1de9c8091f353422a50736baf4d803.yaml Changelog: dedicated IO worker for drive

Changed Files

File Summary
synapse/lib/drive.py New FileDrive subclass with SpawnerMixin; many sync methods converted to async; schema callback resolved via reqDynCoro; callback signature gains curv parameter
synapse/lib/cell.py Drive init via FileDrive.spawner(); sockdirn for Unix sockets; _driveCellMigration copies drive DB to dedicated slab; drive.sync() called in backup and shutdown paths; drive API calls changed from sync to async
synapse/lib/dyndeps.py New getDynCoro/reqDynCoro for async function import; tryDynMod/tryDynLocal/tryDynFunc deprecated in favor of reqDynMod/reqDynLocal/reqDynFunc; improved error messages
synapse/lib/link.py New unixwait() polling helper for socket availability
synapse/lib/const.py New UNIX_SOCKET_PATH_MAX = 103 constant
synapse/cortex.py tryDynFunc -> reqDynFunc
synapse/datamodel.py tryDynFunc -> reqDynFunc
synapse/tools/storm/pkg/gen.py tryDynMod -> reqDynMod
synapse/tools/utils/autodoc.py tryDynLocal -> reqDynLocal
synapse/tests/test_lib_cell.py Drive tests removed (moved to test_lib_drive.py); socket path constant updated
synapse/tests/test_lib_base.py Spawner fini lifecycle tests (Haha class)
synapse/tests/test_lib_dyndeps.py Tests for getDynCoro/reqDynCoro/reqDynMod/reqDynLocal/reqDynFunc/runDynTask error paths
synapse/tests/test_lib_link.py Test for unixwait()
synapse/tests/test_lib_agenda.py Event loop mock moved inside getTestCore context
synapse/tests/test_lib_stormtypes.py Event loop mock moved inside getTestCoreAndProxy context
synapse/tests/test_lib_nexus.py Size threshold relaxed (3x -> 4x) to account for drive slab
.circleci/config.yml COVERAGE_PROCESS_START added; --cov-config=.coveragerc.main for main process
.coveragerc Subprocess coverage config: concurrency = multiprocessing, parallel = True, sigterm = True
scripts/testrunner.sh Coverage flags updated; switched to --dist worksteal -n 8
docs/conf.py SIGTERM warning pattern added to ignore list
CLAUDE.md Coverage command example updated

Architectural Detail

Spawner Framework (synapse/lib/spawner.py)

  1. SpawnerMixin.spawner(base, sockpath) returns a factory coroutine.
  2. The factory calls _spawn() which:
    • Serializes the __anit__ constructor call as a todo tuple.
    • Falls back to a /tmp/<guid> socket path if the configured path exceeds UNIX_SOCKET_PATH_MAX.
    • Launches a subprocess via s_process.spawn() running _ioWorkProc.
    • Waits for the socket with _spawnerWait (1-second poll, 30-second deadline).
    • Opens a Telepath proxy to unix://<sockpath>:item.
    • Registers bidirectional fini handlers (proxy fini -> subprocess fini -> base fini, and base fini -> proxy fini).
  3. _ioWorkProc runs asyncio.run() in the subprocess, creates a Daemon, instantiates the target object, shares it, and listens on the Unix socket.

Drive Migration (cell.py + drive.py)

  • Version 1 (_drivePermMigration): Migrates perm -> permissions field (existing).
  • Version 2 (_driveCellMigration): Copies all drive rows from the shared cell slab into a new dedicated slab at slabs/drive.lmdb, then drops the old DB.
  • After migration, FileDrive.spawner() initializes the drive in a subprocess.

Schema Callback Change

setTypeSchema callbacks are now specified as importable Python dotted-path strings (e.g., 'synapse.tests.test_lib_drive.migrate_v1') instead of raw function references. They are resolved at call time via reqDynCoro, which validates that the target is an async coroutine function. The callback signature also gains a fourth curv parameter (the current schema version before the upgrade).

@codecov
Copy link
Copy Markdown

codecov bot commented Nov 6, 2025

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 97.74%. Comparing base (6dc9f70) to head (a23c25c).
⚠️ Report is 1 commits behind head on master.

Additional details and impacted files
@@           Coverage Diff            @@
##           master    #4567    +/-   ##
========================================
  Coverage   97.74%   97.74%            
========================================
  Files         298      299     +1     
  Lines       62998    63142   +144     
========================================
+ Hits        61576    61719   +143     
- Misses       1422     1423     +1     
Flag Coverage Δ
linux 97.67% <100.00%> (+<0.01%) ⬆️
linux_replay 93.47% <100.00%> (+0.01%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@invisig0th invisig0th changed the base branch from master to synapse-3xx January 16, 2026 12:41
@OCBender OCBender changed the base branch from synapse-3xx to master February 19, 2026 15:37
@OCBender OCBender changed the base branch from master to synapse-3xx February 19, 2026 15:38
@OCBender OCBender changed the base branch from synapse-3xx to master February 19, 2026 15:55
@OCBender OCBender changed the title WIP: prototype of spawn io worker spawn io worker for drive subsystem Feb 26, 2026
@OCBender OCBender marked this pull request as ready for review February 26, 2026 15:37
Comment thread synapse/lib/spawner.py Outdated
Comment thread synapse/lib/drive.py
Comment thread synapse/lib/drive.py Outdated
Comment thread synapse/lib/spawner.py Outdated
Comment thread synapse/lib/drive.py Outdated
Comment thread synapse/lib/drive.py Outdated
Comment thread synapse/lib/drive.py Outdated
…n provided (#4863)

- [x] Drive - ensure that the setTypeSchema callback is a valid dyncoro when provided
- [x] Dyndeps - add getDynCoro and reqDynCoro functions; add req* versions of dyn helpers, deprecated the try* versions.
Comment thread .circleci/config.yml
@vEpiphyte vEpiphyte added this to the v2.240.0 milestone Apr 14, 2026
Comment thread synapse/lib/cell.py Outdated
Comment thread synapse/lib/cell.py Outdated
Comment thread scripts/testrunner.sh
Comment thread synapse/lib/link.py Outdated
@vEpiphyte vEpiphyte merged commit a5cef68 into master Apr 20, 2026
6 checks passed
@vEpiphyte vEpiphyte deleted the visi-io-spawn branch April 20, 2026 18:53
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants