benoitc / couchbeam

Apache CouchDB client in Erlang
Other
242 stars 113 forks source link

Database disconnect throws unmatched clause error on gen_changes #198

Open javierg opened 11 months ago

javierg commented 11 months ago

I am using the gen_changes behavior and if the server disconnects the app throws an exception on

    State2 = case Msg of
        {done, LastSeq} ->
            State#gen_changes_state{last_seq=LastSeq};
        {change, Change} ->
            Seq = couchbeam_doc:get_value(<<"seq">>, Change),
            State#gen_changes_state{last_seq=Seq}

As hackney returns {hackney_response, Ref, done}

Is there something I am missing? I want my application to just log the error as it is done by /couchbeam_changes_stream.erl and let the handle_change callback in my app to decide what to do (wait for reconnection, or exit.

As a workaround I patched the library to set the state when error to the response from the server.

Thanks for the amazing job!

benoitc commented 11 months ago

@javierg can you share the exception raised? This should be normally catched. If you can also please share the portion of your code that intiate the change.

javierg commented 11 months ago

@benoitc

This is the exception raised

[error] GenServer #PID<0.2841.0> terminating
** (CaseClauseError) no case clause matching: {:error, {:hackney_response, #Reference<0.2008468710.2789736451.184912>, :done}}
    (couchbeam 1.4.2) /Users/javierg/contentinator/deps/couchbeam/src/gen_changes.erl:126: :gen_changes.handle_info/2
    (stdlib 3.17) gen_server.erl:695: :gen_server.try_dispatch/4
    (stdlib 3.17) gen_server.erl:771: :gen_server.handle_msg/6
    (stdlib 3.17) proc_lib.erl:226: :proc_lib.init_p_do_apply/3
Last message: {#Reference<0.2008468710.2789736452.179287>, {:error, {:hackney_response, #Reference<0.2008468710.2789736451.184912>, :done}}}
State: {:gen_changes_state, #Reference<0.2008468710.2789736452.179287>, "3686538-g1AAAACheJzLYWBgYMpgTmEQTM4vTc5ISXLIyU9OzMnILy7JAUklMiTV____PyuDOYlBRv9bLlCM3dTSJDnFIhGbHjwm5bEASYYGIPUfbqDAFLCBZmZpJmYG5ti0ZgEAuWYyfg", CouchDb.Observer, %{}, {:db, {:server, "http://localhost:8980", [basic_auth: {"root", "123"}]}, "bs", [basic_auth: {"root", "123"}]}, [feed: :longpoll, filter: "_doc_ids", doc_ids: ["publisher/amco", "publisher/sep"], heartbeat: 9000]}

The code that starts the gen_changes is on a modules' start_link

  @behaviour :gen_changes

  def start_link(db, opts) do
    :gen_changes.start_link(__MODULE__, db, opts, [])
  end

  @impl true
  def init([]) do
    {:ok, nil}
  end

  def child_spec(opts) do
    %{
      id: __MODULE__,
      start: {__MODULE__, :start_link, opts},
      type: :supervisor,
      restart: :permanent
    }
  end

  ...