Merge branch 'master' into 10645-cr-mounts-display
[arvados.git] / sdk / ruby / lib / arvados / google_api_client.rb
1 require 'google/api_client'
2 require 'json'
3 require 'tempfile'
4
5 class Google::APIClient
6   def discovery_document(api, version)
7     api = api.to_s
8     discovery_uri = self.discovery_uri(api, version)
9     discovery_uri_hash = Digest::MD5.hexdigest(discovery_uri)
10     discovery_cache_path =
11       File.expand_path("~/.cache/arvados/discovery-#{discovery_uri_hash}.json")
12     @discovery_documents[discovery_uri_hash] ||=
13       disk_cached_discovery_document(discovery_cache_path) or
14       fetched_discovery_document(discovery_uri, discovery_cache_path)
15   end
16
17   private
18
19   def disk_cached_discovery_document(cache_path)
20     begin
21       if (Time.now - File.mtime(cache_path)) < 86400
22         open(cache_path) do |cache_file|
23           return JSON.load(cache_file)
24         end
25       end
26     rescue IOError, SystemCallError, JSON::JSONError
27       # Error reading the cache.  Act like it doesn't exist.
28     end
29     nil
30   end
31
32   def write_cached_discovery_document(cache_path, body)
33     cache_dir = File.dirname(cache_path)
34     cache_file = nil
35     begin
36       FileUtils.makedirs(cache_dir)
37       cache_file = Tempfile.new("discovery", cache_dir)
38       cache_file.write(body)
39       cache_file.flush
40       File.rename(cache_file.path, cache_path)
41     rescue IOError, SystemCallError
42       # Failure to write the cache is non-fatal.  Do nothing.
43     ensure
44       cache_file.close! unless cache_file.nil?
45     end
46   end
47
48   def fetched_discovery_document(uri, cache_path)
49     response = self.execute!(:http_method => :get,
50                              :uri => uri,
51                              :authenticated => false)
52     write_cached_discovery_document(cache_path, response.body)
53     JSON.load(response.body)
54   end
55 end