fix(erlang): pass expected version to worker and fail fast on xdb mismatch

This commit is contained in:
Alice39s 2026-06-28 05:17:59 +09:00
parent e50ead2cba
commit daf6749c34
No known key found for this signature in database
GPG Key ID: 0E0AA11C3939DDDD
3 changed files with 24 additions and 27 deletions

View File

@ -67,12 +67,12 @@ pool_child_specs() ->
Acc Acc
end, [], DbConfig). end, [], DbConfig).
make_pool_spec(PoolName, _Version, File, PoolArgsCfg) -> make_pool_spec(PoolName, Version, File, PoolArgsCfg) ->
PoolArgs = [ PoolArgs = [
{strategy, fifo}, {strategy, fifo},
{name, {local, PoolName}}, {name, {local, PoolName}},
{worker_module, ip2region_worker} {worker_module, ip2region_worker}
| PoolArgsCfg | PoolArgsCfg
], ],
WorkerArgs = [{xdb_file, File}], WorkerArgs = [{xdb_file, File}, {expected_version, Version}],
poolboy:child_spec(PoolName, PoolArgs, WorkerArgs). poolboy:child_spec(PoolName, PoolArgs, WorkerArgs).

View File

@ -62,10 +62,14 @@ init(Args) ->
{ok, IoDevice} = file:open(XdbFileName, [read, binary]), {ok, IoDevice} = file:open(XdbFileName, [read, binary]),
{ok, HeaderBin} = file:read(IoDevice, ?XDB_HEADER_SIZE), {ok, HeaderBin} = file:read(IoDevice, ?XDB_HEADER_SIZE),
{ok, Header} = ip2region_xdb:parse_header(HeaderBin), {ok, Header} = ip2region_xdb:parse_header(HeaderBin),
ExpectedVersion = proplists:get_value(expected_version, Args),
case resolve_version(Header) of case resolve_version(Header) of
{ok, Version} -> {ok, Version} when ExpectedVersion =:= undefined; ExpectedVersion =:= Version ->
load_vector_index(IoDevice, Version), load_vector_index(IoDevice, Version),
{ok, #state{xdb_fd = IoDevice, version = Version}}; {ok, #state{xdb_fd = IoDevice, version = Version}};
{ok, Version} ->
file:close(IoDevice),
{stop, {xdb_version_mismatch, ExpectedVersion, Version}};
{error, Reason} -> {error, Reason} ->
file:close(IoDevice), file:close(IoDevice),
{stop, Reason} {stop, Reason}

View File

@ -5,7 +5,7 @@
-define(IPV6_RESULT, "United States|Florida|Miami|Google LLC|US"). -define(IPV6_RESULT, "United States|Florida|Miami|Google LLC|US").
search_test_() -> search_test_() ->
{ok, _} = application:ensure_all_started(ip2region), {ok, _} = ip2region_test_util:start_app(),
A = "中国|广东省|广州市|中国电信|CN", A = "中国|广东省|广州市|中国电信|CN",
Region0 = xdb:search("1.0.8.0"), Region0 = xdb:search("1.0.8.0"),
Region1 = xdb:search(<<"1.0.8.0">>), Region1 = xdb:search(<<"1.0.8.0">>),
@ -19,7 +19,7 @@ search_test_() ->
]. ].
ipv6_search_test_() -> ipv6_search_test_() ->
setup_ipv6(), {ok, _} = ip2region_test_util:start_app(),
[ [
?_assert(?IPV6_RESULT =:= xdb:search("2001:4860:4860::8888")), ?_assert(?IPV6_RESULT =:= xdb:search("2001:4860:4860::8888")),
?_assert(?IPV6_RESULT =:= xdb:search(<<"2001:4860:4860::8888">>)), ?_assert(?IPV6_RESULT =:= xdb:search(<<"2001:4860:4860::8888">>)),
@ -27,7 +27,7 @@ ipv6_search_test_() ->
]. ].
invalid_search_test_() -> invalid_search_test_() ->
{ok, _} = application:ensure_all_started(ip2region), {ok, _} = ip2region_test_util:start_app(),
[ [
?_assertEqual({error, bad_ip_format}, xdb:search("xxx.0.8.0")), ?_assertEqual({error, bad_ip_format}, xdb:search("xxx.0.8.0")),
?_assertEqual({error, bad_ip_format}, xdb:search("::ggg")), ?_assertEqual({error, bad_ip_format}, xdb:search("::ggg")),
@ -35,27 +35,20 @@ invalid_search_test_() ->
]. ].
ipv6_pool_not_configured_test() -> ipv6_pool_not_configured_test() ->
try application:stop(ip2region) catch _:_ -> ok end, {ok, _} = ip2region_test_util:start_app([{ipv4, "ip2region.xdb"}]),
try application:unload(ip2region) catch _:_ -> ok end,
ok = application:load(ip2region),
ok = application:set_env(ip2region, db, [{ipv4, "ip2region.xdb"}]),
{ok, _} = application:ensure_all_started(ip2region),
?assertEqual({error, pool_not_configured}, xdb:search("2001:4860:4860::8888")). ?assertEqual({error, pool_not_configured}, xdb:search("2001:4860:4860::8888")).
setup_ipv6() -> xdb_version_mismatch_test() ->
try application:stop(ip2region) catch _:_ -> ok end, {ok, _} = ip2region_test_util:start_app(),
try application:unload(ip2region) catch _:_ -> ok end, V4File = filename:join([
ok = application:load(ip2region), ip2region_test_util:repo_root(), "binding", "erlang", "priv", "ip2region.xdb"
RepoRoot = repo_root(),
V6File = filename:join([RepoRoot, "data", "ip2region_v6.xdb"]),
ok = application:set_env(ip2region, db, [
{ipv4, "ip2region.xdb"},
{ipv6, V6File}
]), ]),
{ok, _} = application:ensure_all_started(ip2region). error_logger:tty(false),
try
repo_root() -> ?assertEqual(
TestDir = filename:dirname(?FILE), {error, {xdb_version_mismatch, ipv6, ipv4}},
ErlangDir = filename:dirname(TestDir), ip2region_worker:start([{xdb_file, V4File}, {expected_version, ipv6}])
BindingDir = filename:dirname(ErlangDir), )
filename:dirname(BindingDir). after
error_logger:tty(true)
end.