TheWebs
TheWebs

Reputation: 12923

Threads in rails 4.1.9 (using Jruby 9.0.0.0 preview)

So I have a module that is trying to make use of multiple threads, one per site. It then trying to do a request on each thread. From there I am trying to say:

Create a thread for each site, make a post request to another site, if the response.code that comes back is a 500, wait 15 seconds and try again. Try only 5 times, upon the fifth failure - send an email

I am trying to do this in such a way that the code is easily testable with output having to validate that a thread is created. In other words, my tests only care about the response coming back from the request, I have integration tests that test the actual "wait 15 seconds ... " part.

What I have so far is:

module BlackBird
  module PublishToSites
    module User

      def self.publish_user(params)
        if Site.all != nil
          threads = []
          Site.all.each do |s|
            threads << Thread.new do
              publish(s, params)
            end
          end
          threads.each { |t| t.join }
        else
          # Send Email
          #  - Use No Sites Template
        end
      end

      private

      def self.publish(site, params)

        response = Typhoeus.post(
        s.site_api_url + 'users',
        :body => params.to_json,
        :headers => {
            "Authorization" => "Token #{s.site_api_key}",
            'Content-Type' => 'application/json'
          }
        )

        return deal_with_response(response)
      end

      def self.deal_with_response(response)
        if response.code == 200
        elsif response.code == 500
          # wait and try again after 15 seconds for a total of 5 times.
          # should we fail on the 5th try, use the email template: Recieved 500.
        end
    end
  end
end

Because this is running on the JVM I will have no issue with multithreading and things should generally run faster then the MRI, speed is of an essence here.

So How do I, once I reach the response.code == 500 section, actually say, wait 15 seconds, try again for a total of 5 times?

Upvotes: 0

Views: 60

Answers (1)

kares
kares

Reputation: 7166

since you do not have this code structured and the Thread.new is not just an implementation detail you will need to pass a counter and the "full" state around to the place where you want to "sleep and retry" e.g. :

  def self.publish(site, params, try = 0)

    response = Typhoeus.post(
    site.site_api_url + 'users',
    :body => params.to_json,
    :headers => {
        "Authorization" => "Token #{site.site_api_key}",
        'Content-Type' => 'application/json'
      }
    )

    return deal_with_response(response, site, params, try)
  end

  def self.deal_with_response(response, site, params, try = 0)
    if response.code == 200
    elsif response.code == 500
      # wait and try again after 15 seconds for a total of 5 times.
      # should we fail on the 5th try, use the email template: Recieved 500.
      if ( try += 1 ) < 5
        sleep(15)
        publish(site, params, try)
      else
        send_email "received response 500 for 5 times"
      end
    end
  end

be aware since you're joining on the created threads that the requests will wait potentially ~ 5x15 seconds before returning a response ... when there are 500 failures!

Upvotes: 1

Related Questions