diff --git a/rebar.config b/rebar.config index 0043d41..1899428 100644 --- a/rebar.config +++ b/rebar.config @@ -20,7 +20,7 @@ {deps, [ {cowboy, "2.12.0"}, - {erlang_python, "1.8.1"} + {erlang_python, "2.1.0"} ]}. {shell, [ @@ -39,7 +39,7 @@ {profiles, [ {test, [ {deps, [ - {hackney, "3.0.2"}, + {hackney, "3.2.1"}, {jsx, "3.1.0"} ]} ]} diff --git a/rebar.lock b/rebar.lock deleted file mode 100644 index ecd87bb..0000000 --- a/rebar.lock +++ /dev/null @@ -1,17 +0,0 @@ -{"1.2.0", -[{<<"cowboy">>,{pkg,<<"cowboy">>,<<"2.12.0">>},0}, - {<<"cowlib">>,{pkg,<<"cowlib">>,<<"2.13.0">>},1}, - {<<"erlang_python">>,{pkg,<<"erlang_python">>,<<"1.8.1">>},0}, - {<<"ranch">>,{pkg,<<"ranch">>,<<"1.8.0">>},1}]}. -[ -{pkg_hash,[ - {<<"cowboy">>, <<"F276D521A1FF88B2B9B4C54D0E753DA6C66DD7BE6C9FCA3D9418B561828A3731">>}, - {<<"cowlib">>, <<"DB8F7505D8332D98EF50A3EF34B34C1AFDDEC7506E4EE4DD4A3A266285D282CA">>}, - {<<"erlang_python">>, <<"4DAFC7AFD315F0D5D45792F722364D8721CED438E396B7D14F19518DC78D198B">>}, - {<<"ranch">>, <<"8C7A100A139FD57F17327B6413E4167AC559FBC04CA7448E9BE9057311597A1D">>}]}, -{pkg_hash_ext,[ - {<<"cowboy">>, <<"8A7ABE6D183372CEB21CAA2709BEC928AB2B72E18A3911AA1771639BEF82651E">>}, - {<<"cowlib">>, <<"E1E1284DC3FC030A64B1AD0D8382AE7E99DA46C3246B815318A4B848873800A4">>}, - {<<"erlang_python">>, <<"0F5893100A92285096519F8111D3A6D3F5DCD18668545ADF9F4144899D5997C2">>}, - {<<"ranch">>, <<"49FBCFD3682FAB1F5D109351B61257676DA1A2FDBE295904176D5E521A2DDFE5">>}]} -]. diff --git a/src/hornbeam_handler.erl b/src/hornbeam_handler.erl index 8621741..a5526ee 100644 --- a/src/hornbeam_handler.erl +++ b/src/hornbeam_handler.erl @@ -146,7 +146,7 @@ run_wsgi_optimized(Req, AppModule, AppCallable, State) -> end. %% @private -%% Context-aware fallback path using py:ctx_call +%% Context-aware fallback path using py:call run_wsgi_with_context(Req, AppModule, AppCallable, PyContext, TimeoutMs, State) -> %% Build environ options from state (for multi-app mode) EnvOpts = case maps:get(script_name, State, undefined) of @@ -159,8 +159,8 @@ run_wsgi_with_context(Req, AppModule, AppCallable, PyContext, TimeoutMs, State) undefined -> Environ; PathInfo -> Environ#{<<"PATH_INFO">> => PathInfo} end, - py:ctx_call(PyContext, hornbeam_wsgi_runner, run_wsgi, - [AppModule, AppCallable, Environ1], #{}, TimeoutMs). + py:call(PyContext, hornbeam_wsgi_runner, run_wsgi, + [AppModule, AppCallable, Environ1], #{timeout => TimeoutMs}). %% @private %% Build environ dict for NIF optimization. @@ -356,7 +356,7 @@ run_asgi_optimized(Req, AppModule, AppCallable, ReqBody, State) -> end. %% @private -%% Context-aware fallback path using py:ctx_call +%% Context-aware fallback path using py:call run_asgi_with_context(Req, AppModule, AppCallable, ReqBody, PyContext, TimeoutMs, State) -> %% Build scope options from state (for multi-app mode) ScopeOpts = case maps:get(script_name, State, undefined) of @@ -369,8 +369,8 @@ run_asgi_with_context(Req, AppModule, AppCallable, ReqBody, PyContext, TimeoutMs undefined -> Scope; PathInfo -> Scope#{<<"path">> => PathInfo, <<"raw_path">> => PathInfo} end, - py:ctx_call(PyContext, hornbeam_asgi_runner, run_asgi, - [AppModule, AppCallable, Scope1, ReqBody], #{}, TimeoutMs). + py:call(PyContext, hornbeam_asgi_runner, run_asgi, + [AppModule, AppCallable, Scope1, ReqBody], #{timeout => TimeoutMs}). %% @private %% Bound context path - binds a worker for the request duration. @@ -388,11 +388,9 @@ run_asgi_bound(Req, AppModule, AppCallable, ReqBody, TimeoutMs, State) -> undefined -> Scope; PathInfo -> Scope#{<<"path">> => PathInfo, <<"raw_path">> => PathInfo} end, - %% Use with_context to bind a worker for the request duration - py:with_context(fun() -> - py:call(hornbeam_asgi_runner, run_asgi, - [AppModule, AppCallable, Scope1, ReqBody], #{}, TimeoutMs) - end). + %% Call ASGI runner - context routing handled automatically by py:call + py:call(hornbeam_asgi_runner, run_asgi, + [AppModule, AppCallable, Scope1, ReqBody], #{}, TimeoutMs). %% @private %% Build scope with atom keys for NIF optimization. diff --git a/src/hornbeam_lifespan.erl b/src/hornbeam_lifespan.erl index c6ba3e7..b735d2b 100644 --- a/src/hornbeam_lifespan.erl +++ b/src/hornbeam_lifespan.erl @@ -155,11 +155,11 @@ init(Opts) -> {read_concurrency, true} ]), - %% Create a dedicated Python context for ASGI affinity + %% Get a Python context for ASGI affinity %% This ensures module-level state persists across requests - PyContext = case py:bind(new) of - {ok, Ctx} -> Ctx; - _ -> undefined + PyContext = case py:contexts_started() of + true -> py:context(); + false -> undefined end, %% Cache initial values @@ -261,12 +261,8 @@ terminate(_Reason, #state{started = true, supported = true, py_context = PyContext}) -> %% Run shutdown on terminate _ = run_shutdown(AppModule, AppCallable, PyContext), - %% Unbind the context - catch py:unbind(PyContext), ok; -terminate(_Reason, #state{py_context = PyContext}) -> - %% Just unbind context if lifespan not started - catch py:unbind(PyContext), +terminate(_Reason, _State) -> ok. code_change(_OldVsn, State, _Extra) -> @@ -293,10 +289,10 @@ run_startup(AppModule, AppCallable, PyContext) -> Result = case PyContext of undefined -> py:call(hornbeam_lifespan_runner, startup, - [AppModule, AppCallable, TimeoutMs], #{}, TimeoutMs + 5000); + [AppModule, AppCallable, TimeoutMs], #{timeout => TimeoutMs + 5000}); Ctx -> - py:ctx_call(Ctx, hornbeam_lifespan_runner, startup, - [AppModule, AppCallable, TimeoutMs], #{}, TimeoutMs + 5000) + py:call(Ctx, hornbeam_lifespan_runner, startup, + [AppModule, AppCallable, TimeoutMs], #{timeout => TimeoutMs + 5000}) end, case Result of {ok, Response} -> @@ -337,10 +333,10 @@ run_shutdown(AppModule, AppCallable, PyContext) -> Result = case PyContext of undefined -> py:call(hornbeam_lifespan_runner, shutdown, - [AppModule, AppCallable], #{}, TimeoutMs); + [AppModule, AppCallable], #{timeout => TimeoutMs}); Ctx -> - py:ctx_call(Ctx, hornbeam_lifespan_runner, shutdown, - [AppModule, AppCallable], #{}, TimeoutMs) + py:call(Ctx, hornbeam_lifespan_runner, shutdown, + [AppModule, AppCallable], #{timeout => TimeoutMs}) end, case Result of {ok, Response} ->