Upgrade ranch 1.7.0 → 2.2.0

Ranch 2.x breaking changes addressed:
- Protocol callback changed from start_link/4 (Ref, Socket, Transport, Opts)
  to start_link/3 (Ref, Transport, Opts); socket obtained via ranch:handshake/1
- ranch:info/0 now returns #{Name => #{...}} instead of [{Name, [proplists]}];
  updated mtp_listeners/0, running_ports/0, and config_change_case test

Also update AGENTS.md with CT failure debugging workflow.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This commit is contained in:
Sergey Prokhorov 2026-04-05 01:41:01 +02:00
parent 683732e584
commit fc9ec1d326
No known key found for this signature in database
GPG key ID: 1C570244E4EF3337
7 changed files with 36 additions and 19 deletions

View file

@ -79,6 +79,25 @@ Individual steps:
Always run `make test` before committing. Fix all xref warnings and dialyzer errors — they are treated as errors.
### Debugging CT failures
When `rebar3 ct` (or `make test`) reports failures, **do not rely on the terminal output** — it is truncated and shows only the last error. Instead, go straight to the HTML logs:
```
_build/test/logs/ct_run.<timestamp>/lib.mtproto_proxy.logs/run.<timestamp>/
```
Key files:
- `suite.log` — machine-readable summary; `=case` lines show test order, `=result failed` shows which failed
- `single_dc_suite.<test_name>.html` — full log for one test case (strip HTML tags to read: `sed 's/<[^>]*>//g'`)
- `suite.log.html` / `index.html` — human-readable in a browser
Workflow:
1. Run `make test` — note how many pass/fail
2. Check `suite.log` for `=case` ordering and `=result failed` to identify the failing test
3. Read that test's `.html` log for the full stacktrace and system reports
4. Fix, then re-run `make test`. If tests still fail spuriously, try `rm -rf _build/test && make test` to clear stale test artifacts (removing only `_build/test` is faster than a full clean build).
## Code Style
- Language: **Erlang**. Follow standard Erlang OTP conventions.

View file

@ -1,7 +1,7 @@
% -*- mode: erlang -*-
{erl_opts, [debug_info]}.
{deps, [{ranch, "1.7.0"},
{deps, [{ranch, "2.2.0"},
{erlang_psq, {git, "https://github.com/seriyps/psq", {branch, "master"}}}
]}.
{project_plugins, [rebar3_proper,

View file

@ -3,10 +3,10 @@
{git,"https://github.com/seriyps/psq",
{ref,"46329ccb60f27d7d4c3f3643441ccef6c5f9c89c"}},
0},
{<<"ranch">>,{pkg,<<"ranch">>,<<"1.7.0">>},0}]}.
{<<"ranch">>,{pkg,<<"ranch">>,<<"2.2.0">>},0}]}.
[
{pkg_hash,[
{<<"ranch">>, <<"9583F47160CA62AF7F8D5DB11454068EAA32B56EEADF984D4F46E61A076DF5F2">>}]},
{<<"ranch">>, <<"25528F82BC8D7C6152C57666CA99EC716510FE0925CB188172F41CE93117B1B0">>}]},
{pkg_hash_ext,[
{<<"ranch">>, <<"59F7501C3A56125B2FC5684C3048FAC9D043C0BF4D173941B12CA927949AF189">>}]}
{<<"ranch">>, <<"FA0B99A1780C80218A4197A59EA8D3BDAE32FBFF7E88527D7D8A4787EFF4F8E7">>}]}
].

View file

@ -10,7 +10,7 @@
-behaviour(ranch_protocol).
%% API
-export([start_link/4, send/2]).
-export([start_link/3, send/2]).
-export([hex/1, unhex/1]).
-export([keys_str/0]).
@ -65,7 +65,7 @@
%% APIs
start_link(Ref, _Socket, Transport, Opts) ->
start_link(Ref, Transport, Opts) ->
{ok, proc_lib:spawn_link(?MODULE, ranch_init, [{Ref, Transport, Opts}])}.
keys_str() ->

View file

@ -94,21 +94,19 @@ diff_env(NewEnv, OldEnv) ->
%% @doc List of ranch listeners running mtproto_proxy
-spec mtp_listeners() -> [tuple()].
mtp_listeners() ->
lists:filter(
fun({_Name, Opts}) ->
proplists:get_value(protocol, Opts) == mtp_handler
end,
ranch:info()).
maps:to_list(
maps:filter(
fun(_Name, #{protocol := Protocol}) ->
Protocol == mtp_handler
end,
ranch:info())).
%% @doc Currently running listeners in a form of proxy_port()
-spec running_ports() -> [proxy_port()].
running_ports() ->
lists:map(
fun({Name, Opts}) ->
#{protocol_options := ProtoOpts,
ip := Ip,
port := Port} = maps:from_list(Opts),
fun({Name, #{protocol_options := ProtoOpts, ip := Ip, port := Port}}) ->
[Name, Secret, AdTag] = ProtoOpts,
case inet:ntoa(Ip) of
{error, einval} ->

View file

@ -6,7 +6,7 @@
-export([start/2,
stop/1,
get_rpc_handler_state/1]).
-export([start_link/4,
-export([start_link/3,
ranch_init/1]).
-export([init/1,
callback_mode/0,
@ -63,7 +63,7 @@ get_rpc_handler_state(Pid) ->
%% Callbacks
start_link(Ref, _, Transport, Opts) ->
start_link(Ref, Transport, Opts) ->
{ok, proc_lib:spawn_link(?MODULE, ranch_init, [{Ref, Transport, Opts}])}.
ranch_init({Ref, Transport, Opts}) ->

View file

@ -317,11 +317,11 @@ config_change_case({post, Cfg}) ->
stop_single(Cfg);
config_change_case(Cfg) when is_list(Cfg) ->
%% test "max_connections"
MaxConnsBefore = [{Listener, proplists:get_value(max_connections, Opts)}
MaxConnsBefore = [{Listener, maps:get(max_connections, Opts)}
|| {Listener, Opts} <- mtproto_proxy_app:mtp_listeners()],
NewMaxConns = 10,
ok = mtproto_proxy_app:config_change([{max_connections, NewMaxConns}], [], []),
MaxConnsAfter = [{Listener, proplists:get_value(max_connections, Opts)}
MaxConnsAfter = [{Listener, maps:get(max_connections, Opts)}
|| {Listener, Opts} <- mtproto_proxy_app:mtp_listeners()],
?assertNotEqual(MaxConnsBefore, MaxConnsAfter),
?assert(lists:all(fun({_Listener, MaxConns}) ->