Method: MassRecord::Actions#execute_queued_queries

Defined in:
lib/mass_record.rb

#execute_queued_queries(key: { operation:"operation", table:"table", object:"object" }, synonyms: { insert: [:create, :new, :add, :insert, :post], update: [:update,:edit,:modify,:put,:patch], select: [:read,:select,:get], save: [:save], delete: [:delete] }, folder: { queued:path[:queued_queries], errored:path[:errored_queries], completed:path[:completed_queries] }, file_tag: Time.now.strftime("%Y%m%d%H%M%S%L").to_s) ⇒ Object



119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
# File 'lib/mass_record.rb', line 119

def execute_queued_queries key:{
    operation:"operation", 
    table:"table", 
    object:"object"
  },synonyms:{
    insert: [:create, :new, :add, :insert, :post],
    update: [:update,:edit,:modify,:put,:patch],
    select: [:read,:select,:get],
    save:   [:save],
    delete: [:delete]
  },folder:{
    queued:path[:queued_queries],
    errored:path[:errored_queries],
    completed:path[:completed_queries]
  },file_tag:Time.now.strftime("%Y%m%d%H%M%S%L").to_s
  self.individual_count, self.mass_count, errored_objects = 0,0,[]

  files = Dir.foreach(folder[:queued]).collect{|x| x}.keep_if{|y|y=~/\.json$/i}
  json_objects = []

  # rename to avoid double processing
  files.each{|x| File.rename "#{folder[:queued]}/#{x}","#{folder[:queued]}/#{x}.processing"}

  # load all the json
  files.each do |file|
    File.open("#{folder[:queued]}/#{file}.processing",'r') do |f|
      json = JSON.parse(f.read)
      json_objects += json
    end
  end

  # validate all objects
  validation_results = mass_validate json_objects
  logger.debug "#{validation_results[:passed_orders].count} valid objects of #{json_objects.count} total objects".black.on_white
  json_objects = validation_results[:passed_orders]

  # get all operations and tables in use
  operations = json_objects.collect{|x| x[key[:operation]].to_sym}.to_set.to_a
  logger.debug "Operations: #{operations.pretty_inspect}".black.on_white rescue logger.debug "Error logging operations"

  # construct mass queries
  errors = {}
  operations.each do |op|
    if synonyms[:insert].include? op
      errors[:insert] = mass_insert_by_table json_objects.select{|x| synonyms[:insert].include? x[key[:operation]].to_sym.downcase}, key:key
    elsif synonyms[:update].include? op
      errors[:update] = mass_update_by_table json_objects.select{|x| synonyms[:update].include? x[key[:operation]].to_sym.downcase}, key:key
    elsif synonyms[:save].include? op # needs to intelligently determine if the order already exists, insert if not, update if so
      errors[:save] = mass_save_by_table json_objects.select{|x| :save == x[key[:operation]].to_sym.downcase}, key:key
    elsif synonyms[:delete].include? op
    elsif synonyms[:select].include? op
    else
    end
  end

  # Collect mass errors and the associated objects
  errors_present = errors.any?{|op,tables| tables.has_key? :run_time or tables.any?{|table,col_sets| !col_sets.blank?}}
  errored_objects = collect_errored_objects found_in:errors, from:json_objects, key:key, synonyms:synonyms if errors_present

  # Retry objects from the failed queries on an individual query basis
  individual_errors = errors_present ? (query_per_object errored_objects, key:key, synonyms:synonyms) : []

  # Collect individual errors and their associated objects with the option for custom handling
  individually_errored_objects = collect_individually_errored_objects from:errored_objects, based_on:individual_errors, key:key
  individual_errors += (collect_run_time_errors found_in:errors) + validation_results[:failed_orders]
  default_error_handling = handle_individual_errors_callback errors:individual_errors, errored_objects:individually_errored_objects, all_objects:json_objects

  # Save failed objects, archive all objects, and log out a summary
  if default_error_handling 
    # Save a new file with just the errored objects in the errored folder 
    # (which will be all the objects if there is not a 1 to 1 ratio between the errors and errored objects)
    # THEN save a new file with ALL the objects in the completed folder
    if json_objects.count > 0
      if individual_errors.count == individually_errored_objects.count
        File.open("#{folder[:errored]}/errored_only_#{file_tag}.json",'w'){|f| f.write individually_errored_objects.to_json} if individual_errors.count > 0
        File.open("#{folder[:completed]}/#{file_tag}.json",'w'){|f| f.write json_objects.to_json}
      else
        File.open("#{folder[:errored]}/all_#{file_tag}.json",'w'){|f| f.write json_objects.to_json}
      end
    end

    # Delete all the original files
    file_names = files.collect{|x| "#{folder[:queued]}/#{x}.processing"}
    File.delete(*file_names)

    # Log out a summary of what happened
    logger.info "\nProcessed #{pluralize((json_objects.count),'object')} with #{pluralize((individual_errors.count),'error')}".black.on_white
    logger.info "\tMass Queries:\t\t#{self.mass_count} for #{pluralize((json_objects.count - errored_objects.count),'object')}\n\tRecovery Queries:\t#{self.individual_count} for #{pluralize(errored_objects.count,'object')}\n\tErrors:\t\t\t#{individual_errors.count}".black.on_white if individual_errors.count > 0 or logger.debug?
    individual_errors.each_with_index{|x,i| logger.info "\t\t(#{i}) #{x.to_s[0..90]}...".black.on_white} if individual_errors.count > 0 or logger.debug?
  end
  return individual_errors
end