benoitc / couchbeam

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

Database disconnect throws unmatched clause error on gen_changes #198

Open javierg opened 1 year ago

javierg commented 1 year 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 1 year 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 1 year 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

  ...