Skip to content

Commit a2d50bb

Browse files
committed
Fix context routing and avoid _decimal in tests
- Auto-bind context on first access to ensure same process uses same context - Check if bound context is alive to handle router restart - Replace statistics with json in test (avoids _decimal subinterpreter issues)
1 parent d42b903 commit a2d50bb

2 files changed

Lines changed: 25 additions & 9 deletions

File tree

src/py_context_router.erl

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -184,11 +184,23 @@ get_context(N) when is_integer(N), N > 0 ->
184184
persistent_term:get(?POOL_CONTEXT_KEY(?DEFAULT_POOL, N));
185185
get_context(Pool) when is_atom(Pool) ->
186186
%% Get context from named pool
187+
%% Auto-bind on first access to ensure consistent context for a process
187188
case get(?BOUND_CONTEXT_KEY(Pool)) of
188189
undefined ->
189-
select_by_scheduler(Pool);
190+
Ctx = select_by_scheduler(Pool),
191+
put(?BOUND_CONTEXT_KEY(Pool), Ctx),
192+
Ctx;
190193
Ctx ->
191-
Ctx
194+
%% Verify bound context is still alive
195+
case is_process_alive(Ctx) of
196+
true ->
197+
Ctx;
198+
false ->
199+
%% Re-bind to a new context
200+
NewCtx = select_by_scheduler(Pool),
201+
put(?BOUND_CONTEXT_KEY(Pool), NewCtx),
202+
NewCtx
203+
end
192204
end.
193205

194206
%% @doc Bind a context to the current process for the default pool.

test/py_import_SUITE.erl

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -639,40 +639,44 @@ _test_textwrap_in_sys = 'textwrap' in sys.modules
639639
%%
640640
%% The ETS registry tracks what should be imported, and sys.modules
641641
%% contains the actual imported modules.
642+
%%
643+
%% Note: Avoid modules that import C extensions with global state issues
644+
%% (e.g., statistics imports _decimal). Use json which has proper
645+
%% subinterpreter support. See https://github.com/python/cpython/issues/106078
642646
registry_import_in_sys_modules_test(_Config) ->
643647
%% Clear registry
644648
ok = py_import:clear_imports(),
645649

646650
%% Add to registry and import
647651
ok = py_import:ensure_imported(fractions),
648-
ok = py_import:ensure_imported(statistics),
652+
ok = py_import:ensure_imported(json),
649653

650654
%% Verify ETS registry has the entries
651655
Registry = py_import:all_imports(),
652656
?assert(lists:member({<<"fractions">>, all}, Registry)),
653-
?assert(lists:member({<<"statistics">>, all}, Registry)),
657+
?assert(lists:member({<<"json">>, all}, Registry)),
654658

655659
%% Use the modules to ensure they're imported
656660
{ok, _} = py:call(fractions, 'Fraction', [1, 3]),
657-
{ok, _} = py:call(statistics, mean, [[1, 2, 3, 4, 5]]),
661+
{ok, _} = py:call(json, dumps, [[1, 2, 3]]),
658662

659663
%% Verify both are in sys.modules by checking from Python
660664
ok = py:exec(<<"
661665
import sys
662666
_fractions_in_sys = 'fractions' in sys.modules
663-
_statistics_in_sys = 'statistics' in sys.modules
667+
_json_in_sys = 'json' in sys.modules
664668
_sys_modules_keys = list(sys.modules.keys())
665669
">>),
666670

667671
{ok, FractionsInSys} = py:eval(<<"_fractions_in_sys">>),
668-
{ok, StatsInSys} = py:eval(<<"_statistics_in_sys">>),
672+
{ok, JsonInSys} = py:eval(<<"_json_in_sys">>),
669673
?assertEqual(true, FractionsInSys),
670-
?assertEqual(true, StatsInSys),
674+
?assertEqual(true, JsonInSys),
671675

672676
%% Get the list of modules in sys.modules that match our registry
673677
{ok, SysModulesList} = py:eval(<<"_sys_modules_keys">>),
674678
?assert(lists:member(<<"fractions">>, SysModulesList)),
675-
?assert(lists:member(<<"statistics">>, SysModulesList)),
679+
?assert(lists:member(<<"json">>, SysModulesList)),
676680

677681
ct:pal("ETS registry and sys.modules are in sync").
678682

0 commit comments

Comments
 (0)