diff --git a/lib/postoffice/rescuer/client.ex b/lib/postoffice/rescuer/client.ex index b3b42b0e..f5173fc5 100644 --- a/lib/postoffice/rescuer/client.ex +++ b/lib/postoffice/rescuer/client.ex @@ -10,7 +10,7 @@ defmodule Postoffice.Rescuer.Client do Logger.info("Succesfully listed pending messages from #{host}") {:ok, Poison.decode!(body)} - {:ok, %HTTPoison.Response{status_code: status_code, body: body}} -> + {:ok, %HTTPoison.Response{status_code: status_code}} -> Logger.info( "Non successful response list pending messages from #{host} with status code: #{ status_code @@ -31,7 +31,7 @@ defmodule Postoffice.Rescuer.Client do when status_code in 200..299 -> Logger.info("Successfully deleted message #{message_id} from #{host}") {:ok, :deleted} - {:ok, %HTTPoison.Response{status_code: status_code, body: body}} -> + {:ok, %HTTPoison.Response{status_code: status_code}} -> Logger.info( "Non successful response deleting message from #{host} with status code: #{ status_code diff --git a/lib/postoffice/rescuer/message_recovery.ex b/lib/postoffice/rescuer/message_recovery.ex new file mode 100644 index 00000000..797dd627 --- /dev/null +++ b/lib/postoffice/rescuer/message_recovery.ex @@ -0,0 +1,29 @@ +defmodule Postoffice.Rescuer.MessageRecovery do + alias Postoffice.Rescuer.Client + + require Logger + + def run(host) do + Logger.info("Started MessageRecovery for host #{host}") + case Client.list(host) do + {:ok, []} -> + Logger.info("Undelivered messages not found on #{host}") + {:ok, messages} -> + messages + |> Enum.map(fn message -> handle_message(message, host) end) + {:error, []} -> + Logger.info("Error on #{host} listing undelivering messages") + end + end + + defp handle_message(message, host) do + {id, message_params} = Map.pop(message, "id") + case Postoffice.receive_message(message_params) do + {:ok, created_message} -> + Logger.info("Successfully recovered message for topic #{created_message["topic"]} with public_id #{created_message["public_id"]}") + Client.delete(host, id) + {:relationship_does_not_exists, _errors} -> + Logger.info("Trying to receive message for non existing topic #{message["topic"]}") + end + end +end diff --git a/test/postoffice/rescuer/message_recovery_test.exs b/test/postoffice/rescuer/message_recovery_test.exs new file mode 100644 index 00000000..6d5865e3 --- /dev/null +++ b/test/postoffice/rescuer/message_recovery_test.exs @@ -0,0 +1,73 @@ +defmodule Postoffice.Rescuer.MessageRecoveryTest do + use ExUnit.Case + + import Mox + + alias Postoffice.Fixtures + alias Postoffice.Messaging + alias Postoffice.Rescuer.Adapters.HttpMock + alias Postoffice.Rescuer.MessageRecovery + + @origin_host "http://fake_origin.host" + @first_message_id 1 + @second_message_id 2 + @one_message_response "[{\"id\": 1, \"topic\": \"test\", \"payload\": {\"products\": [{\"code\": \"1234\"}, {\"code\": 2345}], \"reference\": 1234}, \"attributes\": {}}]" + @two_messages_response "[{\"id\": 1, \"topic\": \"test\", \"payload\": {\"products\": [{\"code\": \"1234\"}, {\"code\": 2345}], \"reference\": 1234}, \"attributes\": {}}, {\"id\": 2, \"topic\": \"test\", \"payload\": {\"products\": [{\"code\": \"1234\"}, {\"code\": 2345}], \"reference\": 1234}, \"attributes\": {}}]" + @wrong_topic_message "[{\"id\": 1, \"topic\": \"test2\", \"payload\": {\"products\": [{\"code\": \"1234\"}, {\"code\": 2345}], \"reference\": 1234}, \"attributes\": {}}]" + + setup [:set_mox_from_context, :verify_on_exit!] + + setup do + :ok = Ecto.Adapters.SQL.Sandbox.checkout(Postoffice.Repo) + end + + describe "recover messages" do + test "no message created if no undelivered message found" do + expect(HttpMock, :list, fn @origin_host -> + {:ok, %HTTPoison.Response{status_code: 200, body: "[]"}} + end) + + MessageRecovery.run(@origin_host) + assert Messaging.list_messages() == [] + end + + test "message created if one undelivered message found" do + expect(HttpMock, :list, fn @origin_host -> + {:ok, %HTTPoison.Response{status_code: 200, body: @one_message_response}} + end) + + expect(HttpMock, :delete, fn @origin_host, @first_message_id -> + {:ok, %HTTPoison.Response{status_code: 204}} + end) + + Fixtures.create_topic() + MessageRecovery.run(@origin_host) + assert Kernel.length(Messaging.list_messages()) == 1 + end + + test "more than one message is created if multiple undelivered messages found" do + expect(HttpMock, :list, fn @origin_host -> + {:ok, %HTTPoison.Response{status_code: 200, body: @two_messages_response}} + end) + expect(HttpMock, :delete, fn @origin_host, @first_message_id -> + {:ok, %HTTPoison.Response{status_code: 204}} + end) + expect(HttpMock, :delete, fn @origin_host, @second_message_id -> + {:ok, %HTTPoison.Response{status_code: 204}} + end) + + Fixtures.create_topic() + MessageRecovery.run(@origin_host) + assert Kernel.length(Messaging.list_messages()) == 2 + end + + test "no message created if something fails" do + expect(HttpMock, :list, fn @origin_host -> + {:ok, %HTTPoison.Response{status_code: 200, body: @wrong_topic_message}} + end) + + MessageRecovery.run(@origin_host) + assert Kernel.length(Messaging.list_messages()) == 0 + end + end +end