Improvements and bugfixes refs #2242.
[arvados.git] / apps / workbench / app / models / arvados_api_client.rb
index 21e86da7918664b79e8f43148450b3e68410d379..84735d9774c60f902896d3a15f5ae6850fb977c7 100644 (file)
@@ -9,8 +9,11 @@ class ArvadosApiClient
 
   @@client_mtx = Mutex.new
   @@api_client = nil
+  @@profiling_enabled = Rails.configuration.profiling_enabled rescue false
 
   def api(resources_kind, action, data=nil)
+    profile_checkpoint
+
     @@client_mtx.synchronize do
       if not @@api_client 
         @@api_client = HTTPClient.new
@@ -29,6 +32,9 @@ class ArvadosApiClient
     resources_kind = class_kind(resources_kind).pluralize if resources_kind.is_a? Class
     url = "#{self.arvados_v1_base}/#{resources_kind}#{action}"
 
+    # Clean up /arvados/v1/../../discovery/v1 to /discovery/v1
+    url.sub! '/arvados/v1/../../', '/'
+
     query = {"api_token" => api_token}
     if !data.nil?
       data.each do |k,v|
@@ -44,13 +50,18 @@ class ArvadosApiClient
       end
     else
       query["_method"] = "GET"
-    end 
+    end
+    if @@profiling_enabled
+      query["_profile"] = "true"
+    end
     
     header = {"Accept" => "application/json"}
 
+    profile_checkpoint { "Prepare request #{url} #{query[:uuid]} #{query[:where]}" }
     msg = @@api_client.post(url, 
                             query,
                             header: header)
+    profile_checkpoint 'API transaction'
 
     if msg.status_code == 401
       raise NotLoggedInException.new
@@ -66,15 +77,16 @@ class ArvadosApiClient
     if not resp.is_a? Hash
       raise InvalidApiResponseException.new json
     end
-    if resp[:errors]
-      #if resp[:errors][0] == 'Not logged in'
-      #  raise NotLoggedInException.new
-      #else
-      #  errors = resp[:errors]
-      #  errors = errors.join("\n\n") if errors.is_a? Array
-      #  raise "API errors:\n\n#{errors}\n"
-    #end
+    if msg.status_code != 200
+      errors = resp[:errors]
+      errors = errors.join("\n\n") if errors.is_a? Array
+      raise "#{errors} [API: #{msg.status_code}]"
+    end
+    if resp[:_profile]
+      Rails.logger.info "API client: " \
+      "#{resp.delete(:_profile)[:request_time]} request_time"
     end
+    profile_checkpoint 'Parse response'
     resp
   end
 
@@ -129,6 +141,10 @@ class ArvadosApiClient
     @arvados_schema ||= api 'schema', ''
   end
 
+  def discovery
+    @discovery ||= api '../../discovery/v1/apis/arvados/v1/rest', ''
+  end
+
   def kind_class(kind)
     kind.match(/^arvados\#(.+?)(_list|List)?$/)[1].pluralize.classify.constantize rescue nil
   end
@@ -136,4 +152,15 @@ class ArvadosApiClient
   def class_kind(resource_class)
     resource_class.to_s.underscore
   end
+
+  protected
+  def profile_checkpoint label=nil
+    return if !@@profiling_enabled
+    label = yield if block_given?
+    t = Time.now
+    if label and @profile_t0
+      Rails.logger.info "API client: #{t - @profile_t0} #{label}"
+    end
+    @profile_t0 = t
+  end
 end