Skip to content

Instantly share code, notes, and snippets.

@kadru
Last active July 12, 2024 01:24
Show Gist options
  • Save kadru/6764ebb005b6e8ae7bdd0a43d6c4afd1 to your computer and use it in GitHub Desktop.
Save kadru/6764ebb005b6e8ae7bdd0a43d6c4afd1 to your computer and use it in GitHub Desktop.
# frozen_string_literal: true
# Runs with
# ruby 3.3
# webmock 3.23
# minitest 5.24.1
require 'uri'
require 'net/http'
require 'json'
require 'webmock/minitest'
require 'minitest/autorun'
class EasyBrokerClient
HTTP_ACCEPT = 'application/json'
BASE_URL = 'https://api.stagingeb.com'
private_constant :HTTP_ACCEPT
private_constant :BASE_URL
def initialize(api_key:, page_limit: 50)
@authorization = api_key
@page_limit = page_limit
end
def properties_titles
page = 1
titles = []
loop do
response = get_properties(page)
titles += response['content'].map { _1.fetch('title') }
break if response.fetch('pagination').fetch('next_page').nil?
page += 1
end
titles
end
private
def get_properties(page)
response = Net::HTTP.get(
URI("#{BASE_URL}/v1/properties?limit=#{@page_limit}&page=#{page}"),
{ Accept: HTTP_ACCEPT,
"X-Authorization": @authorization }
)
JSON.parse response
end
end
class EasyBrokerClientTest < Minitest::Test
def setup
@api_key = 'fake_api_key'
@page_limit = 2
@easy_broker_client = EasyBrokerClient.new api_key: @api_key, page_limit: @page_limit
end
def test_properties_titles
stub_propiertes(api_key: @api_key, limit: @page_limit)
stub_propiertes(api_key: @api_key, limit: @page_limit, page: 2, next_page: nil)
assert_equal [
'Casa en Venta Amorada en Santiago Nuevo Leon',
'Beautiful property in Condesa.',
'Casa en Venta Amorada en Santiago Nuevo Leon',
'Beautiful property in Condesa.'
], @easy_broker_client.properties_titles
end
private
def stub_propiertes(
api_key:,
page: 1,
limit: 1,
total: 2,
next_page: "https://api.stagingeb.com/v1/properties?page=#{page + 1}"
)
stub_request(:get, "https://api.stagingeb.com/v1/properties?limit=#{limit}&page=#{page}")
.with(
headers: {
'Accept' => 'application/json',
'Accept-Encoding' => 'gzip;q=1.0,deflate;q=0.6,identity;q=0.3',
'X-Authorization' => api_key
}
)
.to_return(status: 200,
body: {
pagination: {
limit:,
page:,
total:,
next_page:
},
content: [
{
'title' => 'Casa en Venta Amorada en Santiago Nuevo Leon'
},
{
'title' => 'Beautiful property in Condesa.'
}
]
}.to_json)
end
end
# Print all properties titles
# Allow real connections
WebMock.allow_net_connect!
client = EasyBrokerClient.new api_key: 'l7u502p8v46ba3ppgvj5y2aad50lb9', page_limit: 50
# Is very slow because it proccess the api calls sequentially,
# I would like to improve it by implementing concurrently API calls
pp client.properties_titles
@kadru
Copy link
Author

kadru commented Jul 12, 2024

Using the gem async, it can perform the api requests concurrently, improving the execution time:

require "async" # puts this at the top of the file

# add this method to the EasyBrokerClient class
def properties_titles_async
    properties = get_properties(1)
    total = properties.fetch('pagination').fetch('total')
    connections = total / @page_limit
    connections += 1 if total.remainder(@page_limit).positive?

    properties = Sync do |parent|
      (1..connections).map do |int|
        parent.async do
          get_properties(int)
        end
      end.map(&:wait)
    end

    properties.map { _1.fetch('content').fetch('title') }
end
```

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment