Dialyzer error on ack_immediately/1
mortont opened this issue · comments
When using Broadway.Message.ack_immediately/1
on a single message and running mix dialyzer
on the code, dialyzer returns the following error:
lib/test/test_broadway.ex:38:callback_arg_type_mismatch
The inferred type for the 2nd argument is not a
supertype of the expected type for the handle_message/3 callback
in the Broadway behaviour.
Success type:
[
%Broadway.Message{
:acknowledger => {atom(), _, _},
:batch_key => _,
:batch_mode => :bulk | :flush,
:batcher => atom(),
:data => _,
:metadata => %{atom() => _},
:status =>
:ok
| {:failed, binary()}
| {:error, _, [any()]}
| {:exit, _, [any()]}
| {:throw, _, [any()]}
},
...
]
Behaviour callback type:
%Broadway.Message{
:acknowledger => {atom(), _, _},
:batch_key => _,
:batch_mode => :bulk | :flush,
:batcher => atom(),
:data => _,
:metadata => %{atom() => _},
:status =>
:ok
| {:failed, binary()}
| {:error, _,
[
{(... -> any), [any()] | non_neg_integer(), Keyword.t()}
| {atom(), atom(), [any()] | non_neg_integer(), Keyword.t()}
]}
| {:exit, _,
[
{(... -> any), [any()] | non_neg_integer(), Keyword.t()}
| {atom(), atom(), [any()] | non_neg_integer(), Keyword.t()}
]}
| {:throw, _,
[
{(... -> any), [any()] | non_neg_integer(), Keyword.t()}
| {atom(), atom(), [any()] | non_neg_integer(), Keyword.t()}
]}
}
Looking around it seems like others have run into this issue as well here. Of note, dialyzer is happy with passing a list of messages to ack_immediately/1
. Also, the code functions as expected, so I think this is a spec or dialyzer error. Relevant code to reproduce:
@impl true
def handle_message(_, message, _) do
message |> Message.ack_immediately
end
A PR is welcome!
Looking at this more, I found the fix but I don't understand why it's the fix. In lib/broadway/message.ex
if you change
def ack_immediately(%Message{} = message) do
[message] = ack_immediately([message])
message
end
to
def ack_immediately(%Message{} = message) do
ack_immediately([message]) |> List.first
end
dialyzer is happy. Based on my understanding, they should be equivalent so I'm not sure why one generates a dialyzer error while the other doesn't. Something seems fishy with dialyzer here... I don't think this is worth a PR since everything works as expected, but let me know if you think otherwise.
Yes, if that's the fix, then I agree with you. I will close but I will be glad if someone finds another fix and wants to submit a PR :) Thanks for the follow up!