     {:reply, {:error, :closed}, s}
   end
 
-  def handle_call({:operation, op_name, args}, from, %{session_id: sid} = s) do
+  def handle_call({:operation, op_name, args}, from, s) do
     req = Protocol.encode_op(op_name, [sid|args])
     send_noreply_enqueueing(s, req, {from, op_name})
   end
 
   @doc false
-  def handle_cast(:fetch_schema, %{session_id: sid} = s) do
+  def handle_cast(:fetch_schema, s) do
     args = [sid, {:short, 0}, {:long, 1}, "*:-1", true, false]
     req = Protocol.encode_op(:record_load, args)
 


  def handle_info({:tcp, socket, msg}, %{session_id: sid, socket: socket} = s) do
    :inet.setopts(socket, active: :once)
    data = s.tail <> msg

    s =
      case :queue.out(s.queue) do
        {{:value, :fetch_schema}, new_queue} ->
          case Protocol.parse_resp(:record_load, data, s.schema) do
            :incomplete ->
              %{s | tail: data}
            {:error, %Error{}, _} ->
              raise "couldn't fetch schema"
            {:ok, ^sid, [resp], rest} ->
              %{s | schema: parse_schema(resp), tail: rest, queue: new_queue}
          end
        {{:value, {from, op_name}}, new_queue} ->
          case Protocol.parse_resp(op_name, data, s.schema) do
            :incomplete ->
              %{s | tail: data}
            {:unknown_property_id, rest} ->
              Connection.reply(from, {:error, :unknown_property_id})
              %{s | tail: rest}
            {:error, error, rest} ->
              Connection.reply(from, {:error, error})
              %{s | tail: rest, queue: new_queue}
            {:ok, ^sid, resp, rest} ->
              Connection.reply(from, {:ok, resp})
              %{s | tail: rest, queue: new_queue}
          end
      end

    {:noreply, s}
  end


  defp enqueue(s, what) do
    update_in s.queue, &:queue.in(what, &1)
  end

  defp dequeue_and_parse_resp(s, {{:value, :fetch_schema}, new_queue}, data) do
    sid = s.session_id

    case Protocol.parse_resp(:record_load, data, s.schema) do
      :incomplete ->
        %{s | tail: data}
      {:error, %Error{}, _} ->
        raise "couldn't fetch schema"
      {:ok, ^sid, [resp], rest} ->
        %{s | schema: parse_schema(resp), tail: rest, queue: new_queue}
    end
  end

  defp dequeue_and_parse_resp(s, {{:value, {from, op_name}}, new_queue}, data) do
    sid = s.session_id

    case Protocol.parse_resp(op_name, data, s.schema) do
      :incomplete ->
        %{s | tail: data}
      {:unknown_property_id, rest} ->
        Connection.reply(from, {:error, :unknown_property_id})
        %{s | tail: rest}
      {:error, error, rest} ->
        Connection.reply(from, {:error, error})
        %{s | tail: rest, queue: new_queue}
      {:ok, ^sid, resp, rest} ->
        Connection.reply(from, {:ok, resp})
        %{s | tail: rest, queue: new_queue}
    end
  end
end
