Class: ClickhouseRuby::Connection
- Inherits:
-
Object
- Object
- ClickhouseRuby::Connection
- Defined in:
- lib/clickhouse_ruby/connection.rb
Overview
Single HTTP connection wrapper for ClickHouse communication
Provides a thin wrapper around Net::HTTP with:
-
SSL/TLS with verification ON by default (security best practice)
-
Configurable timeouts
-
Keep-alive support
-
Health check via ping
Defined Under Namespace
Classes: DecompressedResponse
Constant Summary collapse
- NETWORK_ERROR_MAPPING =
Error mapping for network issues to ClickhouseRuby exceptions Each entry maps an exception class to a lambda that creates the appropriate error
{ OpenSSL::SSL::SSLError => lambda { |e, _conn| SSLError.new("SSL connection failed: #{e.message}", original_error: e) }, Errno::ECONNREFUSED => lambda { |e, conn| ConnectionNotEstablished.new("Connection refused to #{conn.host}:#{conn.port}: #{e.message}", original_error: e) }, Errno::EHOSTUNREACH => lambda { |e, conn| ConnectionNotEstablished.new("Host unreachable #{conn.host}:#{conn.port}: #{e.message}", original_error: e) }, SocketError => lambda { |e, conn| ConnectionNotEstablished.new("Socket error to #{conn.host}:#{conn.port}: #{e.message}", original_error: e) }, Net::OpenTimeout => lambda { |e, conn| ConnectionTimeout.new("Connection timeout to #{conn.host}:#{conn.port}", original_error: e) }, Net::ReadTimeout => lambda { |e, _conn| ConnectionTimeout.new("Read timeout: #{e.message}", original_error: e) }, Net::WriteTimeout => lambda { |e, _conn| ConnectionTimeout.new("Write timeout: #{e.message}", original_error: e) }, Errno::ECONNRESET => lambda { |e, _conn| ConnectionError.new("Connection reset: #{e.message}", original_error: e) }, Errno::EPIPE => lambda { |e, _conn| ConnectionError.new("Broken pipe: #{e.message}", original_error: e) }, IOError => lambda { |e, _conn| ConnectionError.new("IO error: #{e.message}", original_error: e) }, }.freeze
- NETWORK_ERRORS =
All exception classes that should be caught and mapped
NETWORK_ERROR_MAPPING.keys.freeze
Instance Attribute Summary collapse
-
#connected ⇒ Boolean
(also: #connected?)
readonly
Whether the connection is currently open.
-
#database ⇒ String
readonly
The database name.
-
#host ⇒ String
readonly
The ClickHouse host.
-
#last_used_at ⇒ Time?
readonly
When the connection was last used.
-
#port ⇒ Integer
readonly
The ClickHouse port.
-
#use_ssl ⇒ Boolean
readonly
Whether SSL is enabled.
-
#username ⇒ String?
readonly
Username for authentication.
Instance Method Summary collapse
-
#connect ⇒ self
Establishes the HTTP connection.
-
#disconnect ⇒ self
Closes the HTTP connection.
-
#get(path, headers = {}) ⇒ Net::HTTPResponse
Executes an HTTP GET request.
-
#healthy? ⇒ Boolean
Returns whether the connection is healthy.
-
#initialize(host:, port: 8123, database: "default", username: nil, password: nil, use_ssl: false, ssl_verify: true, ssl_ca_path: nil, connect_timeout: 10, read_timeout: 60, write_timeout: 60, compression: nil, compression_threshold: 1024) ⇒ Connection
constructor
Creates a new connection.
-
#inspect ⇒ String
Returns a string representation of the connection.
-
#ping ⇒ Boolean
Checks if ClickHouse is reachable and responsive.
-
#post(path, body, headers = {}) ⇒ Net::HTTPResponse
Executes an HTTP POST request.
-
#reconnect ⇒ self
Reconnects by closing and reopening the connection.
-
#stale?(max_idle_seconds = 300) ⇒ Boolean
Returns whether the connection has been idle too long.
Constructor Details
#initialize(host:, port: 8123, database: "default", username: nil, password: nil, use_ssl: false, ssl_verify: true, ssl_ca_path: nil, connect_timeout: 10, read_timeout: 60, write_timeout: 60, compression: nil, compression_threshold: 1024) ⇒ Connection
Creates a new connection
110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 |
# File 'lib/clickhouse_ruby/connection.rb', line 110 def initialize( host:, port: 8123, database: "default", username: nil, password: nil, use_ssl: false, ssl_verify: true, ssl_ca_path: nil, connect_timeout: 10, read_timeout: 60, write_timeout: 60, compression: nil, compression_threshold: 1024 ) @host = host @port = port @database = database @username = username @password = password @use_ssl = use_ssl @ssl_verify = ssl_verify @ssl_ca_path = ssl_ca_path @connect_timeout = connect_timeout @read_timeout = read_timeout @write_timeout = write_timeout @compression = compression @compression_threshold = compression_threshold @http = nil @connected = false @last_used_at = nil @mutex = Mutex.new end |
Instance Attribute Details
#connected ⇒ Boolean (readonly) Also known as: connected?
89 90 91 |
# File 'lib/clickhouse_ruby/connection.rb', line 89 def connected @connected end |
#database ⇒ String (readonly)
80 81 82 |
# File 'lib/clickhouse_ruby/connection.rb', line 80 def database @database end |
#host ⇒ String (readonly)
74 75 76 |
# File 'lib/clickhouse_ruby/connection.rb', line 74 def host @host end |
#last_used_at ⇒ Time? (readonly)
93 94 95 |
# File 'lib/clickhouse_ruby/connection.rb', line 93 def last_used_at @last_used_at end |
#port ⇒ Integer (readonly)
77 78 79 |
# File 'lib/clickhouse_ruby/connection.rb', line 77 def port @port end |
#use_ssl ⇒ Boolean (readonly)
86 87 88 |
# File 'lib/clickhouse_ruby/connection.rb', line 86 def use_ssl @use_ssl end |
#username ⇒ String? (readonly)
83 84 85 |
# File 'lib/clickhouse_ruby/connection.rb', line 83 def username @username end |
Instance Method Details
#connect ⇒ self
Establishes the HTTP connection
150 151 152 153 154 155 156 157 158 159 160 161 162 163 |
# File 'lib/clickhouse_ruby/connection.rb', line 150 def connect @mutex.synchronize do return self if @connected && @http&.started? with_error_handling do @http = build_http @http.start @connected = true @last_used_at = Time.now end end self end |
#disconnect ⇒ self
Closes the HTTP connection
168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 |
# File 'lib/clickhouse_ruby/connection.rb', line 168 def disconnect @mutex.synchronize do if @http&.started? begin @http.finish rescue StandardError nil end end @http = nil @connected = false end self end |
#get(path, headers = {}) ⇒ Net::HTTPResponse
Executes an HTTP GET request
231 232 233 234 235 236 237 238 239 240 241 242 243 |
# File 'lib/clickhouse_ruby/connection.rb', line 231 def get(path, headers = {}) ensure_connected request = Net::HTTP::Get.new(path) request["Accept"] = "application/json" request["User-Agent"] = "ClickhouseRuby/#{ClickhouseRuby::VERSION} Ruby/#{RUBY_VERSION}" request.basic_auth(@username, @password || "") if @username headers.each { |k, v| request[k] = v } execute_request(request) end |
#healthy? ⇒ Boolean
Returns whether the connection is healthy
260 261 262 |
# File 'lib/clickhouse_ruby/connection.rb', line 260 def healthy? @connected && @http&.started? end |
#inspect ⇒ String
Returns a string representation of the connection
277 278 279 280 281 |
# File 'lib/clickhouse_ruby/connection.rb', line 277 def inspect scheme = @use_ssl ? "https" : "http" status = @connected ? "connected" : "disconnected" "#<#{self.class.name} #{scheme}://#{@host}:#{@port} #{status}>" end |
#ping ⇒ Boolean
Checks if ClickHouse is reachable and responsive
248 249 250 251 252 253 254 255 |
# File 'lib/clickhouse_ruby/connection.rb', line 248 def ping connect unless connected? response = get("/ping") response.code == "200" && response.body&.strip == "Ok." rescue StandardError false end |
#post(path, body, headers = {}) ⇒ Net::HTTPResponse
Executes an HTTP POST request
200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 |
# File 'lib/clickhouse_ruby/connection.rb', line 200 def post(path, body, headers = {}) ensure_connected request = Net::HTTP::Post.new(path) # Set default headers request["Content-Type"] = "application/x-www-form-urlencoded" request["Accept"] = "application/json" request["User-Agent"] = "ClickhouseRuby/#{ClickhouseRuby::VERSION} Ruby/#{RUBY_VERSION}" # Add compression headers if enabled request["Accept-Encoding"] = "gzip" if @compression == "gzip" # Add authentication request.basic_auth(@username, @password || "") if @username # Merge custom headers headers.each { |k, v| request[k] = v } # Handle request body compression setup_body(request, body) response = execute_request(request) decompress_response(response) end |
#reconnect ⇒ self
Reconnects by closing and reopening the connection
187 188 189 190 |
# File 'lib/clickhouse_ruby/connection.rb', line 187 def reconnect disconnect connect end |
#stale?(max_idle_seconds = 300) ⇒ Boolean
Returns whether the connection has been idle too long
268 269 270 271 272 |
# File 'lib/clickhouse_ruby/connection.rb', line 268 def stale?(max_idle_seconds = 300) return true unless @last_used_at Time.now - @last_used_at > max_idle_seconds end |