How to prevent singleton behavior?

301 views
Skip to first unread message

BobC

unread,
Aug 24, 2011, 11:26:16 AM8/24/11
to HTTParty Gem
I am using HTTParty 0.7.8 in a threaded manner, but it seems the
HTTParty object is a singleton that is shared among all instances -
too new to Ruby to say for certain. Here's a test I run:

require 'Httparty'
threads = Array.new(2)
for i in (0..1)
threads[i] = Thread.new do
http = HTTParty
puts "#### thread " + i.to_s + " - http id:
#{http.object_id}"
end
threads[i].join
end

The id of http for both threads is same.

My threads each call out to different servers, but the requests are
stepping on each other. I have added a method (remove_headers) to
clear the headers in module ClassMethods, but this is not entirely
solving my problem

def remove_headers
default_options[:headers] = {}
end

Like I said, I am too new to Ruby to know how to solve this - any
ideas?

Thanks,

--Bob

Sandro

unread,
Aug 24, 2011, 2:22:49 PM8/24/11
to HTTParty Gem
You may want to use Typhoeus (https://github.com/pauldix/typhoeus/)
which was created with parallel requests in mind. Otherwise, try
including the module into multiple classes.

class Thread1Requestor; include HTTParty; end
class Thread2Requestor; include HTTParty; end

2.times { |i| Thread.new { Object.const_get("Thread#{i}
Requestor").do_your_business } }

Seeing as you're new to Ruby, you may want to read up on Ruby threads
and the GIL: (http://www.igvita.com/2008/11/13/concurrency-is-a-myth-
in-ruby/). The threads in your code may not be affected though, as net
requests won't be using the CPU while waiting for a response.

BobC

unread,
Aug 26, 2011, 8:51:36 PM8/26/11
to HTTParty Gem
Thanks for the idea. I am first going to try the dynamic class method.
I changed your concept to better match my needs, but am having some
general Ruby problems. This is off topic for HTTParty, but in case
you're interested, here's the code I am struggling with. I'll work on
it some more next week to see if I can get beyond the error "wrong
constant name TestModule::Thread1Requestor (NameError)"

Thanks,

--Bob

module TestModule
class Thread1Requestor
def worker
include HTTParty
http = HTTParty
puts "#### http id: #{http.object_id}"
end
end
class Thread2Requestor
def worker
include HTTParty
http = HTTParty
puts "#### http id: #{http.object_id}"
end
end

class ThreadTester
def run
threads = Array.new(2)
for i in (1..2)
threads[i] = Thread.new do
puts "#### thread " + i.to_s
obj = Object.const_get("TestModule::Thread#{i}
Requestor").new
obj.worker
end
threads[i].join
end
end
end
end

tester = TestModule::ThreadTester.new
tester.run

Sandro

unread,
Aug 26, 2011, 9:39:29 PM8/26/11
to HTTParty Gem
Forget about object_ids, if you really want a new one, try NewHTTParty
= HTTParty.dup, but this isn't the way HTTParty is meant to be used.
HTTParty is a module, not really a singleton. It's meant to be mixed
into classes.

I posted the below code as a gist at https://gist.github.com/1174840.
I hope it helps.

require 'rubygems'
require 'httparty'
require 'benchmark'
require 'thread'

class Google
include HTTParty
base_uri 'http://google.com'

def self.benchmark
puts "#{name} took #{Benchmark.realtime { get('/') }}"
end
end

class TheChangeLog
include HTTParty
base_uri 'http://thechangelog.com/'

def self.benchmark
puts "#{name} took #{Benchmark.realtime { get('/') }}"
end
end

def non_threaded
Google.benchmark
TheChangeLog.benchmark
end

def threaded
threads = []
threads << Thread.new { Google.benchmark }
threads << Thread.new { TheChangeLog.benchmark}
threads.each {|t| t.join}
end

def run(type)
puts "Running #{type.to_s.capitalize}"
total = Benchmark.realtime { send(type) }
puts "Total time: #{total}\n\n"
end

run(:non_threaded)
run(:threaded)

Sandro

unread,
Aug 26, 2011, 9:52:19 PM8/26/11
to HTTParty Gem
I just took a second look at your example. Remember, the join method
is blocking. You're joining one thread at a time which means you
haven't even created your second thread before you sit and wait for
the first one to finish. It looks like you're using threads
synchronously, as in not using them at all. You need to create all of
your threads first, then join at the end.

On Aug 26, 7:39 pm, Sandro <sandro.turri...@gmail.com> wrote:
> Forget about object_ids, if you really want a new one, try NewHTTParty
> = HTTParty.dup, but this isn't the way HTTParty is meant to be used.
> HTTParty is a module, not really a singleton. It's meant to be mixed
> into classes.
>
> I posted the below code as a gist athttps://gist.github.com/1174840.
Reply all
Reply to author
Forward
0 new messages