From f52d4dc12af0270b9e558219901677ca7e0cac37 Mon Sep 17 00:00:00 2001 From: ruslandoga Date: Wed, 12 Mar 2025 13:02:46 +0300 Subject: [PATCH 1/2] try looking deeper into the socket to see if still connected --- lib/ch/connection.ex | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/lib/ch/connection.ex b/lib/ch/connection.ex index 09ba17e7..4fcf6f99 100644 --- a/lib/ch/connection.ex +++ b/lib/ch/connection.ex @@ -395,7 +395,7 @@ defmodule Ch.Connection do # reconnect once. If the re-connect failed, return the old # connection and let the error bubble up to the caller. defp maybe_reconnect(conn) do - if HTTP.open?(conn) do + if HTTP.open?(conn) and internal_open?(conn.socket) do conn else opts = HTTP.get_private(conn, :connect_options) @@ -412,6 +412,25 @@ defmodule Ch.Connection do end end + require Record + Record.defrecordp(:sslsocket, Record.extract(:sslsocket, from_lib: "ssl/src/ssl_api.hrl")) + + @spec internal_open?(:gen_tcp.socket() | :ssl.sslsocket()) :: boolean + defp internal_open?(socket) do + peername_result = + case socket do + # plain + _ when is_port(socket) -> :inet.peername(socket) + # ssl + sslsocket() -> :ssl.peername(socket) + end + + case peername_result do + {:ok, {_host, _port}} -> true + {:error, reason} when reason in [:einval, :enotconn] -> false + end + end + defp do_connect(opts) do scheme = String.to_existing_atom(opts[:scheme] || "http") address = opts[:hostname] || "localhost" From 93348550dc951ba490b558ebba4bb9fbba09d440 Mon Sep 17 00:00:00 2001 From: ruslandoga Date: Wed, 12 Mar 2025 13:05:42 +0300 Subject: [PATCH 2/2] add todo --- lib/ch/connection.ex | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/ch/connection.ex b/lib/ch/connection.ex index 4fcf6f99..61d7219d 100644 --- a/lib/ch/connection.ex +++ b/lib/ch/connection.ex @@ -415,6 +415,7 @@ defmodule Ch.Connection do require Record Record.defrecordp(:sslsocket, Record.extract(:sslsocket, from_lib: "ssl/src/ssl_api.hrl")) + # TODO :socket @spec internal_open?(:gen_tcp.socket() | :ssl.sslsocket()) :: boolean defp internal_open?(socket) do peername_result =