File tree Expand file tree Collapse file tree 8 files changed +127
-4
lines changed Expand file tree Collapse file tree 8 files changed +127
-4
lines changed Original file line number Diff line number Diff line change @@ -99,6 +99,15 @@ def active?
9999 false
100100 end
101101
102+ def unprotected_ping
103+ # Call the underlying active? method without Semian protection
104+ # The super here refers to the original active? from the Trilogy adapter
105+ @raw_connection &.ping
106+ rescue => e
107+ Semian . logger &.debug ( "[trilogy_adapter] Unprotected ping failed: #{ e . message } " )
108+ false
109+ end
110+
102111 def with_resource_timeout ( temp_timeout )
103112 if @raw_connection . nil?
104113 prev_read_timeout = @config [ :read_timeout ] || 0
Original file line number Diff line number Diff line change @@ -126,14 +126,28 @@ def start_ping_thread
126126 end
127127
128128 def send_background_ping
129- return unless @resource &.respond_to? ( :ping )
129+ # Use unprotected_ping if available, otherwise fall back to ping
130+ return unless @resource
131+
132+ ping_method = if @resource . respond_to? ( :unprotected_ping )
133+ :unprotected_ping
134+ elsif @resource . respond_to? ( :ping )
135+ :ping
136+ else
137+ return
138+ end
130139
131140 # Send ungated ping (not affected by rejection)
132141 begin
133- @resource . ping
134- @pid_controller . record_ping ( :success )
135- rescue
142+ result = @resource . send ( ping_method )
143+ if result
144+ @pid_controller . record_ping ( :success )
145+ else
146+ @pid_controller . record_ping ( :failure )
147+ end
148+ rescue => e
136149 @pid_controller . record_ping ( :failure )
150+ Semian . logger &.debug ( "[#{ @name } ] Background ping failed: #{ e . message } " )
137151 end
138152 end
139153
Original file line number Diff line number Diff line change @@ -122,6 +122,28 @@ def handle_operation(operation, scope)
122122 @semian . send ( :acquire_semian_resource , adapter : :grpc , scope : scope ) { execute . call }
123123 end
124124 end
125+
126+ def unprotected_ping
127+ # For gRPC, we'll check if the channel is in a ready state
128+ # This doesn't make an actual RPC call but checks connection state
129+
130+ return false if @ch . nil?
131+
132+ # Get the channel connectivity state
133+ state = @ch . connectivity_state ( false )
134+
135+ # GRPC channel states:
136+ # IDLE (0) - channel is idle
137+ # CONNECTING (1) - channel is connecting
138+ # READY (2) - channel is ready for work
139+ # TRANSIENT_FAILURE (3) - channel has seen a failure
140+ # SHUTDOWN (4) - channel has been shut down
141+
142+ state == 2 # GRPC::Core::ConnectivityStates::READY
143+ rescue => e
144+ Semian . logger &.debug ( "[grpc] Unprotected ping failed: #{ e . message } " )
145+ false
146+ end
125147 end
126148end
127149
Original file line number Diff line number Diff line change @@ -80,6 +80,15 @@ def ping
8080 false
8181 end
8282
83+ def unprotected_ping
84+ return false if closed?
85+
86+ raw_ping
87+ rescue => e
88+ Semian . logger &.debug ( "[mysql2] Unprotected ping failed: #{ e . message } " )
89+ false
90+ end
91+
8392 def query ( *args )
8493 if query_whitelisted? ( *args )
8594 raw_query ( *args )
Original file line number Diff line number Diff line change @@ -124,6 +124,33 @@ def with_resource_timeout(timeout)
124124 end
125125 end
126126
127+ def unprotected_ping
128+ # Perform a simple HEAD request to check connectivity
129+ # First ensure we're connected
130+ return false unless started?
131+
132+ begin
133+ # Create a simple HEAD request
134+ req = Net ::HTTP ::Head . new ( "/" )
135+
136+ # Temporarily save semian state and disable it
137+ saved_semian_enabled = @semian_enabled
138+ @semian_enabled = false
139+
140+ # Make the request directly without going through Semian
141+ # We just need to verify we can reach the server
142+ request ( req )
143+
144+ # Any response (even error responses) means the server is reachable
145+ true
146+ rescue => e
147+ Semian . logger &.debug ( "[net_http] Unprotected ping failed: #{ e . message } " )
148+ false
149+ ensure
150+ @semian_enabled = saved_semian_enabled
151+ end
152+ end
153+
127154 private
128155
129156 def handle_error_responses ( result )
Original file line number Diff line number Diff line change @@ -139,6 +139,20 @@ def with_resource_timeout(temp_timeout)
139139 end
140140 end
141141
142+ def unprotected_ping
143+ # Send a PING command directly without Semian protection
144+ return false unless connected?
145+
146+ begin
147+ # Directly call the Redis PING command bypassing Semian's io wrapper
148+ raw_io { [ :ping ] }
149+ true
150+ rescue => e
151+ Semian . logger &.debug ( "[redis] Unprotected ping failed: #{ e . message } " )
152+ false
153+ end
154+ end
155+
142156 private
143157
144158 def resource_exceptions
Original file line number Diff line number Diff line change @@ -39,6 +39,11 @@ def semian_resource
3939 def semian_identifier
4040 _client . semian_identifier
4141 end
42+
43+ def unprotected_ping
44+ # Delegate to the underlying RedisClient's unprotected_ping
45+ _client . unprotected_ping
46+ end
4247 end
4348
4449 module RedisV5Client
Original file line number Diff line number Diff line change @@ -99,6 +99,17 @@ module RedisClient
9999 include Semian ::Adapter
100100 include RedisClientCommon
101101
102+ def unprotected_ping
103+ # Send a PING command directly without Semian protection
104+
105+ # Use call_v to bypass the normal flow
106+ result = call_v ( [ "PING" ] )
107+ result == "PONG"
108+ rescue => e
109+ Semian . logger &.debug ( "[redis_client] Unprotected ping failed: #{ e . message } " )
110+ false
111+ end
112+
102113 private
103114
104115 def resource_exceptions
@@ -129,6 +140,18 @@ module RedisClientPool
129140
130141 define_method ( :semian_resource , Semian ::Adapter . instance_method ( :semian_resource ) )
131142 define_method ( :clear_semian_resource , Semian ::Adapter . instance_method ( :clear_semian_resource ) )
143+
144+ def unprotected_ping
145+ # For pooled connections, use with to get a client and ping
146+
147+ with do |client |
148+ result = client . call_v ( [ "PING" ] )
149+ result == "PONG"
150+ end
151+ rescue => e
152+ Semian . logger &.debug ( "[redis_client_pool] Unprotected ping failed: #{ e . message } " )
153+ false
154+ end
132155 end
133156end
134157
You can’t perform that action at this time.
0 commit comments