20259: Add documentation for banner and tooltip features
[arvados.git] / apps / workbench / app / models / arvados_resource_list.rb
index 6890b874513be7178cb19d848bc2820834dee922..75a9429a43739f7f3c024f496d316b1d4e69cf86 100644 (file)
@@ -1,3 +1,7 @@
+# Copyright (C) The Arvados Authors. All rights reserved.
+#
+# SPDX-License-Identifier: AGPL-3.0
+
 class ArvadosResourceList
   include ArvadosApiClientHelper
   include Enumerable
@@ -9,6 +13,17 @@ class ArvadosResourceList
     @fetch_multiple_pages = true
     @arvados_api_token = Thread.current[:arvados_api_token]
     @reader_tokens = Thread.current[:reader_tokens]
+    @results = nil
+    @count = nil
+    @offset = 0
+    @cond = nil
+    @eager = nil
+    @select = nil
+    @orderby_spec = nil
+    @filters = nil
+    @distinct = nil
+    @include_trash = nil
+    @limit = nil
   end
 
   def eager(bool=true)
@@ -16,6 +31,21 @@ class ArvadosResourceList
     self
   end
 
+  def distinct(bool=true)
+    @distinct = bool
+    self
+  end
+
+  def include_trash(option=nil)
+    @include_trash = option
+    self
+  end
+
+  def recursive(option=nil)
+    @recursive = option
+    self
+  end
+
   def limit(max_results)
     if not max_results.nil? and not max_results.is_a? Integer
       raise ArgumentError("argument to limit() must be an Integer or nil")
@@ -71,7 +101,7 @@ class ArvadosResourceList
         end
       end
     end
-    @cond.keys.select { |x| x.match /_kind$/ }.each do |kind_key|
+    @cond.keys.select { |x| x.match(/_kind$/) }.each do |kind_key|
       if @cond[kind_key].is_a? Class
         @cond = @cond.merge({ kind_key => 'arvados#' + arvados_api_client.class_kind(@cond[kind_key]) })
       end
@@ -79,6 +109,13 @@ class ArvadosResourceList
     self
   end
 
+  # with_count sets the 'count' parameter to 'exact' or 'none' -- see
+  # https://doc.arvados.org/api/methods.html#index
+  def with_count(count_param='exact')
+    @count = count_param
+    self
+  end
+
   def fetch_multiple_pages(f)
     @fetch_multiple_pages = f
     self
@@ -108,13 +145,18 @@ class ArvadosResourceList
 
   def each(&block)
     if not @results.nil?
-      @results.each &block
+      @results.each(&block)
     else
+      results = []
       self.each_page do |items|
         items.each do |i|
+          results << i
           block.call i
         end
       end
+      # Cache results only if all were retrieved (block didn't raise
+      # an exception).
+      @results = results
     end
     self
   end
@@ -148,14 +190,17 @@ class ArvadosResourceList
   end
 
   def items_available
+    results
     @items_available
   end
 
   def result_limit
+    results
     @result_limit
   end
 
   def result_offset
+    results
     @result_offset
   end
 
@@ -170,12 +215,19 @@ class ArvadosResourceList
     api_params = {
       _method: 'GET'
     }
+    api_params[:count] = @count if @count
     api_params[:where] = @cond if @cond
     api_params[:eager] = '1' if @eager
     api_params[:select] = @select if @select
     api_params[:order] = @orderby_spec if @orderby_spec
     api_params[:filters] = @filters if @filters
-
+    api_params[:distinct] = @distinct if @distinct
+    api_params[:include_trash] = @include_trash if @include_trash
+    api_params[:cluster_id] = Rails.configuration.ClusterID
+    if @fetch_multiple_pages
+      # Default limit to (effectively) api server's MAX_LIMIT
+      api_params[:limit] = 2**(0.size*8 - 1) - 1
+    end
 
     item_count = 0
     offset = @offset || 0
@@ -191,12 +243,12 @@ class ArvadosResourceList
                                    reader_tokens: @reader_tokens)
       items = arvados_api_client.unpack_api_response res
 
-      break if items.nil? or not items.any?
-
       @items_available = items.items_available if items.respond_to?(:items_available)
       @result_limit = items.limit if (@fetch_multiple_pages == false) and items.respond_to?(:limit)
       @result_offset = items.offset if (@fetch_multiple_pages == false) and items.respond_to?(:offset)
 
+      break if items.nil? or not items.any?
+
       item_count += items.size
       if items.respond_to?(:offset)
         offset = items.offset + items.size