HCA-Healthcare / elixir-mllp

An Elixir library for transporting HL7 messages via MLLP (Minimal Lower Layer Protocol)
Apache License 2.0
41 stars 19 forks source link

Fragmented Ack #62

Closed Fritzelblitz closed 1 year ago

Fritzelblitz commented 1 year ago

We seem to have a problem where we send a message and receive the ack split into 2 TCP packets, in the first one is the MLLP start byte and the whole ML7 ack, in the second one is only the MLLP end bytes.

As a temporary solution, I have now adapted the MLLP library as follows:

def handle_call({:send, message, options}, _from, state) do
    options1 = Map.merge(state.send_opts, options)
    telemetry(:sending, %{}, state)
    payload = MLLP.Envelope.wrap_message(message)

    case state.tcp.send(state.socket, payload) do
      :ok ->
        case state.tcp.recv(state.socket, 0, options1.reply_timeout) do
          {:ok, reply} ->
            reply =
              case state.tcp.recv(state.socket, 0, 1_000) do
                {:ok, reply2} -> reply <> reply2
                _ -> reply
              end

            telemetry(:received, %{response: reply}, state)
            {:reply, {:ok, reply}, state}
  ...
  end

How could we solve this more cleanly, preferably in such a way that we can also deal with more fragmented messages?

starbelly commented 1 year ago

That makes sense and a great catch / call out. I think how we solve this is quite similar to how we solve this problem in the receiver. Specifically, we recurse until the trailer has been received (https://github.com/HCA-Healthcare/elixir-mllp/blob/27c738f62cc6b5fe4dc9ac475f81dbd79c608be9/lib/mllp/packet_framer.ex#L79).

We might be able to simply use the MLLP.PacketFramer module and provide an option to override. The need for the ability to override is driven by the fact that unfortunately MLLP is used for more than just HL7.