Skip to content

Preserve public Rust timer API after cancellation lifetime fix - #120

Merged
egorsmkv merged 1 commit into
masterfrom
fix/rust-timer-api-compatibility
Oct 11, 2026
Merged

egorsmkv merged 1 commit into
masterfrom
fix/rust-timer-api-compatibility

Conversation

@egorsmkv

@egorsmkv egorsmkv commented Oct 11, 2026 •

Copy link
Copy Markdown
Contributor

Follow-up to merged #119 / issue #118.

The Python timer fix changed the exported Rust signatures of LoopCore::schedule_timer() and PyTimerHandle::new() from Arc<ReadyCallback> to the internal TimerCallback type. This restores the original Rust signatures and explicit shared ownership, while Python bindings use an internal detachable-payload scheduling/handle path. Existing Rust callers can still borrow callback/context and invoke their immutable ReadyCallback; Python cancellation continues releasing callback, args and context safely.

A Rust regression compiles and exercises the original typed return value and handle constructor, shared invocation, cancellation and queued removal. Enqueueing also moves its owned Arc directly into the entry, avoiding an extra clone/drop pair introduced by factoring scheduling.

Local checks: 56 Python timer tests passed (6 intentional control skips); 19 new free-threaded rsloop cases plus 5 existing timer tests passed; Clippy with all targets/features, fmt, Ruff and targeted Pyright passed. Rust default: 337 passed and 15 environment-restricted syscall failures; all features: 433 passed and 19 restricted failures. Core Python: 628 passed, with the same two Unix-socket restrictions seen before #119. Full Tests CI passed, including Linux/macOS/Windows, supported Python versions and free-threaded builds. Async ecosystem CI also passed all six jobs; real PostgreSQL on Python 3.10 and 3.14 each passed 39 tests.

Fresh-process 20,000-timer/timeout probes still retain 0 payloads/tasks after loop turns. Timer Python retention is 315 B (was 87.2 MB before #119); timeout retention is 33.8 KB (was 101.0 MB). RSS is 33.4 MiB / 34.4 MiB, versus 125.2 / 150.4 MiB before the original fix. This PR's fresh-process PostgreSQL probes on Python 3.10 and 3.14 each released all 500 caches and 1500 statements, leaving 0 retained caches, statement states and protocols. asyncio and uvloop controls also retained 0.

Final release microbenchmark: 1M operations/sample, two reversed-order pairs, 14 samples per build. Compared with original 0.1.63, retained zero-delay timers +2.9%, discarded +13.4%, cancelled +9.3%; scattered cancelled timers -7.6%. The extra timer cost is approximately 8–34 ns/op. call_soon has no added synchronization; its measurements varied by about 4%, so no speedup is claimed. The 300-second Granian workload was not repeated.

@egorsmkv
egorsmkv merged commit d7a6b6f into master Oct 11, 2026
44 checks passed
@egorsmkv
egorsmkv deleted the fix/rust-timer-api-compatibility branch October 11, 2026 09:37
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.

1 participant