Repository navigation
Conversation
…ot once per callback (#238) Every _create_*_callback helper declared a @jpype.JImplements class inside the call, so each callback built a Python type, a Java proxy class and a method table that stayed for the life of the process. callbacks.py already caches its proxy classes for the same reason. The classes are now built once per kind under a lock and the Python callables are state of the instance; the callbacks, their arguments and their order are unchanged. Tests count the class definitions and the type objects, and check that callbacks sharing a class keep their own arguments. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
Proof that the new tests fail on
The other eight tests of the file pass on Measured on |
|
Full JVM test run on head |
Closes #238
The JVM build's
AsyncExecutordefined a new@jpype.JImplementsclass inside every_create_*_callbackhelper, so each callback built a Python type, a Java proxy class and a method table that stayed for the life of the process. This defines each of the eight proxy classes once, on first use and under a lock, the waycallbacks.pyalready does for Python functions in SQL and record events. The Python callables of a call are state of the instance, so callbacks that share a class cannot see each other's arguments.The cache is per process, which includes per executor: a second executor reuses the classes of the first. Python only, no Java change, native is untouched (
async_executor.pyis the JVM path). Thecommanddocstring's callback-cost note is left as it is until a timed A/B says what the cost is now.Tests (
tests/test_async_proxy_cache.py, JVM only, listed inNATIVE_NOT_APPLICABLE):jpype.JImplementsfrom an empty cache: at most one per kind across three executors and 50 rounds of all eight kinds, and none after the first round of a 600-callback loadcommandresults and errors,queryrows,new_edge,scan_type,transactionblocks and handlers),create_recordcallbacks run in submission order on one writer and deliver every record at parallel level 4, andon_okandon_errorstill fireThe existing
test_async_executor.py,test_async_transaction.pyandtest_concurrency.pyare not edited.Verification state: static checks done (black, isort, pyflakes, compile). CI results and the proof that the new tests fail on
mainfollow in a comment. Nothing here is a speed claim yet: the step 0 probe and a timed A/B on the JVM wheel come first, and the verdict goes on this PR.🤖 Generated with Claude Code