ruby-trello icon indicating copy to clipboard operation
ruby-trello copied to clipboard

Caching of results

Open cowboygneox opened this issue 11 years ago • 8 comments

Forgive me if this exists and I couldn't find it, but I think it would be awesome if an HTTP cache of some sort existed with the client so that we could traverse object relationships without making the same HTTP calls over and over.

Ex: I have a card, I would like to be able to call card.actions multiple times for various reasons, but the response of actions should be cached so that the HTTP call isn't made again.

Anyone else have thoughts on this?

Thank you very much for this gem. It follows the Trello API very well, and once I figured that out, I had no problem working with it.

cowboygneox avatar Oct 25 '14 15:10 cowboygneox

I just added this to TInternet. It doubled the speed of my script. I could make a pull request if it's adequate:

module Trello
  Request = Struct.new "Request", :verb, :uri, :headers, :body
  Response = Struct.new "Response", :code, :headers, :body

  class TInternet
    class << self
      require "rest_client"

      @@cache = {}

      def execute(request)
        try_execute request
      end

      private

      def try_execute(request)
        begin
          if request
            result = execute_core request
            Response.new(200, {}, result)
          end
        rescue RestClient::Exception => e
          Response.new(e.http_code, {}, e.http_body)
        end
      end

      def execute_core(request)
        if request.verb.to_s == 'get' && !@@cache[request.uri.to_s].nil?
          @@cache[request.uri.to_s]
        else
          puts "#{request.verb} #{request.uri.to_s}"

          RestClient.proxy = ENV['HTTP_PROXY'] if ENV['HTTP_PROXY']
          response = RestClient::Request.execute(
            :method => request.verb, 
            :url => request.uri.to_s, 
            :headers => request.headers, 
            :payload => request.body, 
            :timeout => 10
          )

          if request.verb.to_s == 'get'
            @@cache[request.uri.to_s] = response
          end

          response
        end
      end
    end
  end
end

cowboygneox avatar Oct 25 '14 16:10 cowboygneox

My changes obviously would work poorly if you POSTed data and then did a GET, so maybe the Trello::Client should have a caching parameter?

cowboygneox avatar Oct 25 '14 16:10 cowboygneox

While I generally love this idea, I agree with your point about doing a GET after a POST. For that reason I don't think this is sufficient. However, if you'd be willing to take a look at resolving this problem, I'd like to have the ability to enable something like this in a future gem release.

jeremytregunna avatar Nov 05 '14 17:11 jeremytregunna

I'm on it. I'll see if I can find time this weekend.

cowboygneox avatar Nov 06 '14 04:11 cowboygneox

I like this concept, but might consider it an extension, rather than built-in to the gem itself. Switching to an http client like Faraday offers the possibility for library to allow gem users to modify the request/response cycle through middleware. Gems like ocktokit and github use this approach; anyone using these clients can insert faraday-http-cache faraday middleware for http caching or something else for their own in-memory store if desired.

Thoughts on introducing this to ruby-trello?

rossta avatar Oct 27 '15 23:10 rossta

:+1: to that idea.

jeremytregunna avatar Oct 28 '15 15:10 jeremytregunna

I (obviously) think this should be a feature in the gem. The accessibility of this gem would be greatly benefitted from it. Granted, it can be a difficult task to have full caching, but even if there was an option to enable it for GET requests, that would dramatically improve its speed.

Also, I could just do a better job of keeping the objects I want in memory, so as I write this, I'm seeing that this is certainly gold-plating, but you already have an awesome gem, why not decorate it a bit?

cowboygneox avatar Oct 29 '15 11:10 cowboygneox

I think it could be safely enabled in a client if you give it something like cache: true, expire_in: 1.minute. I really want to be able to just add a line somewhere and get the functionality. Its fiddly enough trying to make less requests already.

hakunin avatar Dec 17 '15 13:12 hakunin