Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions Gemfile
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@ group :test do
gem 'rubocop'
gem 'standard'
gem 'simplecov', '>= 0.21.2', require: false
gem 'vcr'
gem 'webmock'
gem 'vcr', '>= 6.4'
gem 'webmock', '>= 3.14'
gem 'cucumber'
end

Expand Down
20 changes: 13 additions & 7 deletions Gemfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,14 @@ PATH
specs:
pubnub (6.0.2)
addressable (>= 2.0.0)
base64
concurrent-ruby (~> 1.3.4)
concurrent-ruby-edge (~> 0.7.1)
dry-validation (~> 1.0)
httpclient (~> 2.8, >= 2.8.3)
httpx (>= 1.0)
json (>= 2.2.0, < 3)
logger
ostruct
timers (>= 4.3.0)

GEM
Expand All @@ -17,7 +20,7 @@ GEM
public_suffix (>= 2.0.2, < 7.0)
ast (2.4.2)
awesome_print (1.9.2)
base64 (0.2.0)
base64 (0.3.0)
bigdecimal (3.1.8)
binding_of_caller (1.0.1)
debug_inspector (>= 1.2.0)
Expand Down Expand Up @@ -94,14 +97,18 @@ GEM
zeitwerk (~> 2.6)
ffi (1.17.0)
hashdiff (1.1.1)
httpclient (2.8.3)
http-2 (1.1.3)
httpx (1.7.8)
http-2 (>= 1.1.3)
interception (0.5)
json (2.7.2)
language_server-protocol (3.17.0.3)
lint_roller (1.1.0)
logger (1.7.0)
method_source (1.1.0)
mini_mime (1.1.5)
multi_test (1.1.0)
ostruct (0.6.3)
parallel (1.26.3)
parser (3.3.5.0)
ast (~> 2.4.1)
Expand Down Expand Up @@ -174,8 +181,7 @@ GEM
ffi (~> 1.1)
timers (4.3.5)
unicode-display_width (2.6.0)
vcr (6.3.1)
base64
vcr (6.4.0)
webmock (3.24.0)
addressable (>= 2.8.0)
crack (>= 0.3.2)
Expand All @@ -200,8 +206,8 @@ DEPENDENCIES
rubocop
simplecov (>= 0.21.2)
standard
vcr
webmock
vcr (>= 6.4)
webmock (>= 3.14)

BUNDLED WITH
2.4.20
4 changes: 3 additions & 1 deletion lib/pubnub.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,9 @@
require 'openssl'

require 'timers'
require 'httpclient'
require 'httpx'
require 'pubnub/http_response'
require 'pubnub/http_dispatcher'
require 'logger'
require 'dry-validation'
require 'cgi'
Expand Down
60 changes: 35 additions & 25 deletions lib/pubnub/client.rb
Original file line number Diff line number Diff line change
Expand Up @@ -268,11 +268,11 @@ def request_dispatcher(origin, event_type, sync)
if sync
@env[:req_dispatchers_pool][:sync][origin] ||= {}
@env[:req_dispatchers_pool][:sync][origin][event_type] ||=
setup_httpclient(event_type)
setup_httpx_session(event_type)
else
@env[:req_dispatchers_pool][:async][origin] ||= {}
@env[:req_dispatchers_pool][:async][origin][event_type] ||=
setup_httpclient(event_type)
setup_httpx_session(event_type)
end
end

Expand Down Expand Up @@ -359,33 +359,43 @@ def create_state_pools(event)
@env[:state][event.origin] ||= {}
end

def setup_httpclient(event_type)
hc = if ENV["HTTP_PROXY"]
HTTPClient.new(ENV["HTTP_PROXY"])
else
HTTPClient.new
end

case event_type
when :subscribe_event
hc.connect_timeout = @env[:s_open_timeout]
hc.send_timeout = @env[:s_send_timeout]
hc.receive_timeout = @env[:s_read_timeout]
unless @env[:disable_keepalive] || @env[:disable_subscribe_keepalive]
hc.keep_alive_timeout = @env[:idle_timeout]
hc.tcp_keepalive = true
def setup_httpx_session(event_type)
timeout_opts = case event_type
when :subscribe_event
{
connect_timeout: @env[:s_open_timeout],
write_timeout: @env[:s_send_timeout] || @env[:s_open_timeout],
read_timeout: @env[:s_read_timeout]
}
when :single_event
{
connect_timeout: @env[:open_timeout],
write_timeout: @env[:send_timeout] || @env[:open_timeout],
read_timeout: @env[:read_timeout]
}
end
when :single_event
hc.connect_timeout = @env[:open_timeout]
hc.send_timeout = @env[:send_timeout]
hc.receive_timeout = @env[:read_timeout]
unless @env[:disable_keepalive] || @env[:disable_non_subscribe_keepalive]
hc.keep_alive_timeout = @env[:idle_timeout]
hc.tcp_keepalive = true

keepalive_enabled = case event_type
when :subscribe_event
!(@env[:disable_keepalive] || @env[:disable_subscribe_keepalive])
when :single_event
!(@env[:disable_keepalive] || @env[:disable_non_subscribe_keepalive])
end

if keepalive_enabled
timeout_opts[:keep_alive_timeout] = @env[:idle_timeout]
end

options = { timeout: timeout_opts }
httpx = HTTPX.plugin(:persistent)

if ENV["HTTP_PROXY"]
options[:proxy] = { uri: ENV["HTTP_PROXY"] }
httpx = httpx.plugin(:proxy)
end

hc
session = httpx.with(**options)
HttpDispatcher.new(session, keepalive_enabled: keepalive_enabled)
end

def validate!(env)
Expand Down
2 changes: 1 addition & 1 deletion lib/pubnub/event.rb
Original file line number Diff line number Diff line change
Expand Up @@ -251,7 +251,7 @@ def error_envelope(parsed_response, error, req_res_objects)
when JSON::ParserError
error_category = Pubnub::Constants::STATUS_NON_JSON_RESPONSE
code = req_res_objects[:response].code
when HTTPClient::TimeoutError
when HTTPX::TimeoutError
error_category = Pubnub::Constants::STATUS_TIMEOUT
code = 408
when OpenSSL::SSL::SSLError
Expand Down
2 changes: 1 addition & 1 deletion lib/pubnub/event/formatter.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ class Event
# Module that holds formatters for events
module EFormatter
def format_envelopes(response, request)
if response.is_a?(HTTPClient::TimeoutError) || response.is_a?(OpenSSL::SSL::SSLError)
if response.is_a?(HTTPX::TimeoutError) || response.is_a?(OpenSSL::SSL::SSLError)
return error_envelope(nil,
response,
request: request,
Expand Down
40 changes: 40 additions & 0 deletions lib/pubnub/http_dispatcher.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
module Pubnub
class HttpDispatcher
attr_reader :tcp_keepalive

def initialize(httpx_session, keepalive_enabled: true)
@session = httpx_session
@tcp_keepalive = keepalive_enabled
end

def get(url, header: {})
execute { @session.get(url, headers: header) }
end

def post(url, body: '', header: {})
execute { @session.post(url, headers: header, body: body) }
end

def patch(url, body: '', header: {})
execute { @session.patch(url, headers: header, body: body) }
end

def delete(url, header: {})
execute { @session.delete(url, headers: header) }
end

def reset_all
@session.close
end

private

def execute
response = yield
if response.is_a?(HTTPX::ErrorResponse)
raise response.error
end
Pubnub::HttpResponse.new(response)
end
end
end
12 changes: 12 additions & 0 deletions lib/pubnub/http_response.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
module Pubnub
class HttpResponse
attr_reader :body, :code, :http_version
alias status_code code

def initialize(httpx_response)
@code = httpx_response.status
@body = httpx_response.body.to_s
@http_version = httpx_response.version
end
end
end
2 changes: 1 addition & 1 deletion lib/pubnub/pam.rb
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ def error_envelope(parsed_response, error, req_res_objects)
when JSON::ParserError
error_category = Pubnub::Constants::STATUS_NON_JSON_RESPONSE
code = req_res_objects[:response].code
when HTTPClient::TimeoutError
when HTTPX::TimeoutError
error_category = Pubnub::Constants::STATUS_TIMEOUT
code = 408
else
Expand Down
1 change: 1 addition & 0 deletions lib/pubnub/subscribe_event.rb
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@ def send_request(retries = 0)

begin
req = request_dispatcher.get(uri.to_s)

if retries > 0
@app.subscriber.announce_status(announcement_type: Pubnub::Constants::RECONNECTED_ANNOUNCEMENT,
event: @event,
Expand Down
5 changes: 4 additions & 1 deletion pubnub.gemspec
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,13 @@ Gem::Specification.new do |spec|
spec.required_ruby_version = '>= 3.0.0'

spec.add_dependency 'addressable', '>= 2.0.0'
spec.add_dependency 'base64'
spec.add_dependency 'logger'
spec.add_dependency 'ostruct'
spec.add_dependency 'concurrent-ruby', '~> 1.3.4'
spec.add_dependency 'concurrent-ruby-edge', '~> 0.7.1'
spec.add_dependency 'dry-validation', '~> 1.0'
spec.add_dependency 'httpclient', '~> 2.8', '>= 2.8.3'
spec.add_dependency 'httpx', '>= 1.0'
spec.add_dependency 'json', '>= 2.2.0', '< 3'
spec.add_dependency 'timers', '>= 4.3.0'
end
2 changes: 2 additions & 0 deletions spec/helpers/spec_helper.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
require "rr"
require "stringio"
require "webmock/rspec"
require "httpx/adapters/webmock"
require "vcr"
require "pry"
require "spec_expectations"
Expand Down Expand Up @@ -67,6 +68,7 @@ def loop_it(interval, time_limit)
config.include AsyncHelper
config.mock_framework = :rspec
config.tty = true
config.filter_run_excluding integration: true

logfile = File.open(File.expand_path("../../test.log", __FILE__), "a")
logfile.sync = true
Expand Down
1 change: 1 addition & 0 deletions spec/lib/client_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -278,5 +278,6 @@
eventually { expect(pubnub.env[:req_dispatchers_pool][:async]["ps.pndsn.com"][:single_event].tcp_keepalive).to eq false }
end
end

end
end
18 changes: 6 additions & 12 deletions spec/lib/events/grant_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -39,19 +39,13 @@
end
end

[
HTTPClient::ConnectTimeoutError,
HTTPClient::ReceiveTimeoutError,
HTTPClient::SendTimeoutError,
].each do |error_class|
it "forms valid ErrorEnvelope on #{error_class}" do
allow_any_instance_of(HTTPClient).to receive(:get).and_return error_class.new
it "forms valid ErrorEnvelope on HTTPX::TimeoutError" do
allow_any_instance_of(Pubnub::HttpDispatcher).to receive(:get).and_raise(HTTPX::TimeoutError.new(nil, "timeout"))

expect(envelope.is_a?(Pubnub::ErrorEnvelope)).to eq true
expect(envelope.status[:code]).to eq 408
expect(envelope.status[:category]).to eq Pubnub::Constants::STATUS_TIMEOUT
expect(envelope.status).to satisfies_schema Pubnub::Schemas::Envelope::StatusSchema.new
end
expect(envelope.is_a?(Pubnub::ErrorEnvelope)).to eq true
expect(envelope.status[:code]).to eq 408
expect(envelope.status[:category]).to eq Pubnub::Constants::STATUS_TIMEOUT
expect(envelope.status).to satisfies_schema Pubnub::Schemas::Envelope::StatusSchema.new
end
end
end
18 changes: 6 additions & 12 deletions spec/lib/events/timeout_handling_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -12,19 +12,13 @@
end
let(:envelope) { pubnub.time.value }

[
HTTPClient::ConnectTimeoutError,
HTTPClient::ReceiveTimeoutError,
HTTPClient::SendTimeoutError,
].each do |error_class|
it "forms valid ErrorEnvelope on #{error_class}" do
allow_any_instance_of(HTTPClient).to receive(:get).and_return error_class.new
it "forms valid ErrorEnvelope on HTTPX::TimeoutError" do
allow_any_instance_of(Pubnub::HttpDispatcher).to receive(:get).and_raise(HTTPX::TimeoutError.new(nil, "timeout"))

expect(envelope.is_a?(Pubnub::ErrorEnvelope)).to eq true
expect(envelope.status[:code]).to eq 408
expect(envelope.status[:category]).to eq Pubnub::Constants::STATUS_TIMEOUT
expect(envelope.status).to satisfies_schema Pubnub::Schemas::Envelope::StatusSchema.new
end
expect(envelope.is_a?(Pubnub::ErrorEnvelope)).to eq true
expect(envelope.status[:code]).to eq 408
expect(envelope.status[:category]).to eq Pubnub::Constants::STATUS_TIMEOUT
expect(envelope.status).to satisfies_schema Pubnub::Schemas::Envelope::StatusSchema.new
end
end
end
Loading