Ayliane

Ayliane

DBConnection.ConnectionError PID(XXX) exited for some sql queries

Hi there,

I’m currently struggling with this bug, because i don’t have much logs and infos provided by my server. I have an endpoint called /stop (code sample provided below) in which i execute a lot of code before returning :ok . All this code is wrap in multiple functions and through multiple files and services.

Not far from the end of those functions, i’m writing to the database. I have 3 different inserts. But since a few days, i have this error : Postgrex.Protocol (#PID<0.375.0>) disconnected: ** (DBConnection.ConnectionError) client #PID<0.543.0> exited showing up randomly in one of those 3 inserts. (It could be the first one, it could be in the middle of the second one, or the last one. And sometimes (rarely) it doesn’t even fail). The only thing i’ve been able to isolate as a “trigger” is when the inserted data is a little bigger. It has always worked before, and it also worked nicely when i’m trying to insert those same datas directly via iex.

On the Postgres side, i only have this log : LOG: unexpected EOF on client connection with an open transaction .

The controller code looks like this :

  def stop(conn, params) do
        case @influx_caller.end_connexion_performable?(params) do
          true ->
            handle_end_of_connexion(params)
            conn |> send_resp(:ok, [])

          false ->
            if @influx_caller.connexion_data_from(params["connexion_key"]) == %{} do
              update_connexion_with(:influx_empty, params, true)
            end

            conn |> send_resp(:forbidden, [])
        end
      end
    end
  end

The failure happens in the happy path (the true option of the case) in one of the files called by the handle_end_of_connexion function. For example in this query :

Ecto.Changeset.change(connexion, %{
        closed_at: Calculation.get_close_time(events),
      })
      |> Ecto.Changeset.put_assoc(:infos, MyApp.InfosGenerator.perform(obj, obj_type, twi, twl, events))
      |> MyApp.Repo.update

That exact same file with that exact same data can be called from another controller in my app (sort of admin panel), and it works just fine. So i think my problem is coming from the /stop endpoint.

Things i’ve tested so far :

  • Checking my OTP version. It was 21.3 and i found a lot of reports talking about similar errors coming from it, so i updated it to 22.1.7
  • Activating the show_sensitive_data_on_connection_error hoping it would add some logs to investigate, but no luck.
  • Updating phoenix, plug_cowboy, postgrex, and ecto to the latest version.
  • Adding http: [protocol_options: [idle_timeout: :infinity]], in my Mix.Config, since i’ve also read about a timeout from cowboy since it’s 2.0 version.

None of this works. (Of course, i also tried to log things everywhere, but everything is working just fine in local mode)

Any help or at least lead would be much appreciated. Thanks in advance !

[EDIT] This bug only happens in production and staging environment, but not locally. We figured that if we gave more memory to our containers, the error still show up, but less. We’re suspecting that the process gets killed by phoenix, but we can’t figure out why and when :frowning:

[EDIT 2] Thanks to observer, i managed to collect those additional information :

  • When this errors happens : Postgrex.Protocol (#PID<0.422.0>) disconnected: ** (DBConnection.ConnectionError) client #PID<0.31212.0> exited, i have those lines popping in observer =>
11:06:52:783159 (<0.31212.0>) out {lists,reverse,1}
11:06:52:783212 (<0.31212.0>) in {lists,reverse,1}
11:06:52:783218 (<0.31212.0>) << {inet_reply,#Port<0.71>,ok}
11:06:52:783234 (<0.31212.0>) out {prim_inet,send_recv_reply,2}
11:06:52:783243 (<0.31212.0>) in {prim_inet,send_recv_reply,2}
11:06:52:783247 (<0.31212.0>) out {prim_inet,recv0,3}
11:06:52:797698 (<0.31209.0>) in {cowboy_http,loop,1}
11:06:52:797725 (<0.31209.0>) << {tcp_closed,#Port<0.140>}
11:06:52:797750 (<0.31209.0>) getting_unlinked #Port<0.140>
11:06:52:797786 (<0.31209.0>) out {cowboy_children,terminate_loop,2}
11:06:52:797794 (<0.31212.0>) in {prim_inet,recv0,3}
11:06:52:797800 (<0.31212.0>) exit shutdown
11:06:52:797820 (<0.31212.0>) out_exited 0
11:06:52:797905 (<0.31209.0>) in {cowboy_children,terminate_loop,2}
11:06:52:797911 (<0.31209.0>) getting_unlinked <0.31212.0>
11:06:52:797915 (<0.31209.0>) << {'EXIT',<0.31212.0>,shutdown}
11:06:52:797943 (<0.31209.0>) exit {shutdown,{socket_error,closed,'The socket has been closed.'}}
11:06:52:797951 (<0.31209.0>) out_exited 0

The process was spawn here :

11:06:52:304313 (<0.31209.0>) spawn <0.31212.0> as proc_lib:init_p(<0.31209.0>,[<0.447.0>,<0.446.0>,'Elixir.Tracking.Endpoint',<0.414.0>,<0.413.0>],cowboy_stream_h,request_process,[#{body_length => 136,cert => undefined,has_body => true, [etc...]

I really don’t understand what and why this process is closed and the link is lost :confused:

Most Liked

kokolegorille

kokolegorille

Hello et bienvenue,

Did You try to increase the timeout of the Repo?

put_assoc will do everything in a transaction, if it takes too much time, it will fail.

You can pass a timeout…

MyApp.Repo.update(timeout: 60_000)
jola

jola

Because this error comes up now and then, and it’s a confusing one, I’ll just clarify what it’s saying. Obviously the error is related to the database query, but it’s not caused by the database query. DBConnection is reporting that the client exited. The client, in this scenario, is the Phoenix request process that initiated the request.

So the Phoenix request process exited and therefore DBConnection errored. A common cause for the Phoenix request to exit is a timeout. Timeouts are not handled by Phoenix at all, rather by Cowboy, which is why Phoenix didn’t log an error. Cowboy will time out a request by default in 60s of inactivity, but there are other options at play as well.

You can find the options here Nine Nines: cowboy_http(3)

You did add http: [protocol_options: [idle_timeout: :infinity]], which was the most likely fix, are you sure it’s in the right config file?

I’m also curious what you see on the browser side (I’m assuming you’re initiating this from a browser). Are you getting any response at all?

Ayliane

Ayliane

Hi Jola, and thanks for your reply :slight_smile:

Yeah, i’m also suspecting Cowboy and I’m rather sure I added the idle_timeout in the right config file (config.exs, and just to be sure, also in my env specific files).

I do instantiate the request from a browser but it launches when the page is closed, so i’m not waiting for a response.

I have found a temporary fix : I’ve moved the handle_end_of_connexion(params) function in a worker, and everything works fine again but i’m really not satisfied with this workaround since I’m under the impression that i’m really missing an important point here ><

The point is that all the work done in this handle_end_of_connexion, including the database inserts are NOT taking 60secs. Everything is done in less than 30secs so my feeling is that it’s not the cowboy timeout.

Where Next?

Popular in Questions Top

lastday4you
I wanted to check elixir version in phoenix because i found that my elixir is 1.5 but when i use Enum.chunk_by it said the function is un...
New
Brian
What is the proper way to load a module from a file in to IEX? In the python world, doing something like this pretty standard: from ....
New
quazar
How to set Jason to encode all fields in ecto schema, I don’t care about security and implementing only is taking long list of attributes...
New
dokuzbir
Hello, I am trying to convert my lists to string without losing brackets.For start i have 3 map. They look like these buyer = %{ id: ...
New
nsuchy
Hi. I’ve noticed that Windows Powershell has it’s own IEX command and you cannot access Elixir’s IEX due to the conflict. This isn’t a cr...
New
vac
Hi, I'm quite new in Elixir and I'm trying to format a string to a PEM format. I have the certificate value like MIIDBTCCAe2...... and ...
New
myronmarston
The Elixir Typespec docs show the following syntax for keyword lists in typespecs: # ... | [key: type] # keyword lis...
New
chensan
I have a User schema with a :from_id field set to type :string: defmodule TweetBot.Repo.Migrations.CreateUsers do use Ecto.Migration ...
New
beno
I will often find my self writing things similar to: case some_value do nil -&gt; something() "" -&gt; something() _ -&gt; someth...
New
lucidguppy
I have a super simple question about elixir - how would I take a file like this foo bar baz and output a new file that enumerates th...
New

Other popular topics Top

JDanielMartinez
Hi! May someone helps me, please! I have two apps into an umbrella project: the first one is Database, which manages queries, and the se...
New
shahryarjb
Hello, I get Persian date from my client and convert it to normal calendar like this: def jalali_string_to_miladi_english_number(persi...
New
sergio
In Ruby, I can go: User.find_by(email: "foobar@email.com").update(email: "hello@email.com") How can I do something similar in Elixir? ...
New
itssasanka
Hi all, Trying to get some more clarity over utc_datetime and naive_datetime for Ecto: https://hexdocs.pm/ecto/Ecto.Schema.html#module-...
New
aalberti333
As the title describes, I’m trying to run Enum.map() over a list of key/value pairs, where the value is a map. My data looks like this: ...
New
sacepums
Hey guys. I'm new to elixir and im really stocked about it. But I ran into a bit of problem - I need to convert a date sting, for examp...
New
fayddelight
I tried installing elixir 1.11.2 erlang 23.3.4 via asdf in my zsh shell. Enabled the versions locally and globally. When I list them ...
New
stefanluptak
Hello everybody, usually, I use a 29" ultra-wide monitor for VSCode which can easily accomodate explorer (files panel) + file with code ...
New
skosch
To my knowledge, put_in, Map.update etc. all have the one limitation of not automatically creating intermediate keys when needed (for exa...
New
AstonJ
We’ve put together this wiki for Phoenix LiveView - please feel free to add any info you feel is worth including. What is Phoenix LiveV...
New

We're in Beta

About us Mission Statement