From d0276b24868711bbe32487c2d5114cc518066281 Mon Sep 17 00:00:00 2001 From: "James R. Griffin III" <1443986+jrgriffiniii@users.noreply.github.com> Date: Fri, 23 Feb 2024 13:45:56 -0500 Subject: [PATCH] Implementing connection pooling for HTTP clients for Mediaflux::Http::Request (#517) * Implementing connection pooling for HTTP clients for Mediaflux::Http::Request * Ensuring that the HTTP client is shutdown at the level of the Mediaflux::Http::Request Class destructor --- app/models/mediaflux/http/request.rb | 42 ++++++++++++++++++++-------- 1 file changed, 30 insertions(+), 12 deletions(-) diff --git a/app/models/mediaflux/http/request.rb b/app/models/mediaflux/http/request.rb index 65029d87..691912b0 100644 --- a/app/models/mediaflux/http/request.rb +++ b/app/models/mediaflux/http/request.rb @@ -2,6 +2,22 @@ module Mediaflux module Http class Request + # This ensures that, once the Class is out of scope, the Net::HTTP::Persistent connection is closed + class << self + def self.create_finalizer + proc { + @http_client.shutdown unless @http_client.nil? + } + end + + def initialize(**args) + super + + finalizer = self.class.create_finalizer + ObjectSpace.define_finalizer(self, finalizer) + end + end + # As this is an abstract class, this should be overridden to specify the Mediaflux API service def self.service raise(NotImplementedError, "#{self} is an abstract class, please override #{self}.service") @@ -60,6 +76,17 @@ def self.default_xml_namespace_uri "http://tigerdata.princeton.edu" end + # Constructs and memoizes a new instance of the Net::HTTP::Persistent object at the level of the Class + # @returns http_client [Net::HTTP::Persistent] HTTP client for transmitting requests to the Mediaflux server API + def self.find_or_create_http_client + @http_client ||= begin + @http_client = Net::HTTP::Persistent.new + # https is not working correctly on td-meta1 we should not need this, but we do... + @http_client.verify_mode = OpenSSL::SSL::VERIFY_NONE + @http_client + end + end + attr_reader :session_token # Constructor @@ -67,10 +94,7 @@ def self.default_xml_namespace_uri # @param session_token [String] the API token for the authenticated session # @param http_client [Net::HTTP::Persistent] HTTP client for transmitting requests to the Mediaflux server API def initialize(file: nil, session_token: nil, http_client: nil) - @http_client = http_client || Net::HTTP::Persistent.new - # https is not working correctly on td-meta1 we should not need this, but we do... - @http_client.verify_mode = OpenSSL::SSL::VERIFY_NONE - + @http_client = http_client || self.class.find_or_create_http_client @file = file @session_token = session_token end @@ -79,8 +103,6 @@ def initialize(file: nil, session_token: nil, http_client: nil) # @return [Net::HTTP] def resolve @http_response = @http_client.request self.class.uri, http_request - @http_client.shutdown - @http_response end # Determines whether or not the request has been resolved @@ -127,12 +149,8 @@ def response_error delegate :to_s, to: :response_xml def xml_payload( name: self.class.service) - @payloads ||= {} - @payloads[name] ||= begin - body = build_http_request_body(name: ) - body.to_xml - end - @payloads[name] + body = build_http_request_body(name: ) + xml_payload = body.to_xml end private