Module: Chewy::RakeHelper

Defined in:
lib/chewy/rake_helper.rb

Constant Summary collapse

IMPORT_CALLBACK =

rubocop:disable Metrics/ParameterLists

lambda do |output, _name, start, finish, _id, payload| # rubocop:disable Metrics/ParameterLists
  duration = (finish - start).ceil
  stats = payload.fetch(:import, {}).map { |key, count| "#{key} #{count}" }.join(', ')
  output.puts "  Imported #{payload[:type]} for #{human_duration(duration)}, stats: #{stats}"
  if payload[:errors]
    payload[:errors].each do |action, errors|
      output.puts "    #{action.to_s.humanize} errors:"
      errors.each do |error, documents|
        output.puts "      `#{error}`"
        output.puts "        on #{documents.count} documents: #{documents}"
      end
    end
  end
end
JOURNAL_CALLBACK =

rubocop:disable Metrics/ParameterLists

lambda do |output, _, _, _, _, payload| # rubocop:disable Metrics/ParameterLists
  count = payload[:groups].values.map(&:size).sum
  targets = payload[:groups].keys.sort_by(&:derivable_name)
  output.puts "  Applying journal to #{targets}, #{count} entries, stage #{payload[:stage]}"
end

Class Method Summary collapse

Class Method Details

.all_indexesArray<Chewy::Index>

Eager loads and returns all the indexes defined in the application except the Chewy::Stash.

Returns:


202
203
204
205
# File 'lib/chewy/rake_helper.rb', line 202

def all_indexes
  Chewy.eager_load!
  Chewy::Index.descendants - [Chewy::Stash]
end

.journal_apply(time: nil, only: nil, except: nil, output: STDOUT) ⇒ Array<Chewy::Type>

Applies changes that were done after the specified time for the specified indexes/types or all of them.

Examples:

Chewy::RakeHelper.journal_apply(time: 1.minute.ago) # applies entries created for the last minute
Chewy::RakeHelper.journal_apply(time: 1.minute.ago, only: 'places') # applies only PlacesIndex::City and PlacesIndex::Country entries reated for the last minute
Chewy::RakeHelper.journal_apply(time: 1.minute.ago, only: 'places#city') # applies PlacesIndex::City entries reated for the last minute only
Chewy::RakeHelper.journal_apply(time: 1.minute.ago, except: PlacesIndex::Country) # applies everything, but PlacesIndex::Country entries reated for the last minute
Chewy::RakeHelper.journal_apply(time: 1.minute.ago, only: 'places', except: 'places#country') # applies PlacesIndex::City entries reated for the last minute only

Parameters:

Returns:

Raises:

  • (ArgumentError)

164
165
166
167
168
169
170
171
# File 'lib/chewy/rake_helper.rb', line 164

def journal_apply(time: nil, only: nil, except: nil, output: STDOUT)
  raise ArgumentError, 'Please specify the time to start with' unless time
  subscribed_task_stats(output) do
    output.puts "Applying journal entries created after #{time}"
    count = Chewy::Journal.new(types_from(only: only, except: except)).apply(time)
    output.puts 'No journal entries were created after the specified time' if count.zero?
  end
end

.journal_clean(time: nil, only: nil, except: nil, output: STDOUT) ⇒ Array<Chewy::Type>

Removes journal records created before the specified timestamp for the specified indexes/types or all of them.

Examples:

Chewy::RakeHelper.journal_clean # cleans everything
Chewy::RakeHelper.journal_clean(time: 1.minute.ago) # leaves only entries created for the last minute
Chewy::RakeHelper.journal_clean(only: 'places') # cleans only PlacesIndex::City and PlacesIndex::Country entries
Chewy::RakeHelper.journal_clean(only: 'places#city') # cleans PlacesIndex::City entries only
Chewy::RakeHelper.journal_clean(except: PlacesIndex::Country) # cleans everything, but PlacesIndex::Country entries
Chewy::RakeHelper.journal_clean(only: 'places', except: 'places#country') # cleans PlacesIndex::City entries only

Parameters:

  • time (Time, DateTime) (defaults to: nil)

    clean all the journal entries created before this time

  • only (Array<Chewy::Index, Chewy::Type, String>, Chewy::Index, Chewy::Type, String) (defaults to: nil)

    indexes or types to synchronize; if nothing is passed - uses all the types defined in the app

  • except (Array<Chewy::Index, Chewy::Type, String>, Chewy::Index, Chewy::Type, String) (defaults to: nil)

    indexes or types to exclude from processing

  • output (IO) (defaults to: STDOUT)

    output io for logging

Returns:


189
190
191
192
193
194
195
196
# File 'lib/chewy/rake_helper.rb', line 189

def journal_clean(time: nil, only: nil, except: nil, output: STDOUT)
  subscribed_task_stats(output) do
    output.puts "Cleaning journal entries created before #{time}" if time
    response = Chewy::Journal.new(types_from(only: only, except: except)).clean(time)
    count = response['deleted'] || response['_indices']['_all']['deleted']
    output.puts "Cleaned up #{count} journal entries"
  end
end

.normalize_index(identifier) ⇒ Object


211
212
213
214
# File 'lib/chewy/rake_helper.rb', line 211

def normalize_index(identifier)
  return identifier if identifier.is_a?(Class) && identifier < Chewy::Index
  "#{identifier.to_s.gsub(/identifier\z/i, '').camelize}Index".constantize
end

.normalize_indexes(*identifiers) ⇒ Object


207
208
209
# File 'lib/chewy/rake_helper.rb', line 207

def normalize_indexes(*identifiers)
  identifiers.flatten(1).map { |identifier| normalize_index(identifier) }
end

.reset(only: nil, except: nil, parallel: nil, output: STDOUT) ⇒ Array<Chewy::Index>

Performs zero-downtime reindexing of all documents for the specified indexes

Examples:

Chewy::RakeHelper.reset # resets everything
Chewy::RakeHelper.reset(only: 'cities') # resets only CitiesIndex
Chewy::RakeHelper.reset(only: ['cities', CountriesIndex]) # resets CitiesIndex and CountriesIndex
Chewy::RakeHelper.reset(except: CitiesIndex) # resets everything, but CitiesIndex
Chewy::RakeHelper.reset(only: ['cities', 'countries'], except: CitiesIndex) # resets only CountriesIndex

Parameters:

  • only (Array<Chewy::Index, String>, Chewy::Index, String) (defaults to: nil)

    index or indexes to reset; if nothing is passed - uses all the indexes defined in the app

  • except (Array<Chewy::Index, String>, Chewy::Index, String) (defaults to: nil)

    index or indexes to exclude from processing

  • parallel (true, Integer, Hash) (defaults to: nil)

    any acceptable parallel options for import

  • output (IO) (defaults to: STDOUT)

    output io for logging

Returns:


39
40
41
42
43
44
45
# File 'lib/chewy/rake_helper.rb', line 39

def reset(only: nil, except: nil, parallel: nil, output: STDOUT)
  subscribed_task_stats(output) do
    indexes_from(only: only, except: except).each do |index|
      reset_one(index, output, parallel: parallel)
    end
  end
end

.reset_all(*except) ⇒ Object


231
232
233
234
# File 'lib/chewy/rake_helper.rb', line 231

def reset_all(*except)
  ActiveSupport::Deprecation.warn '`Chewy::RakeHelper.reset_all` is deprecated and will be removed soon, use `Chewy::RakeHelper.reset` instead'
  reset(except: except)
end

.reset_index(*indexes) ⇒ Object


226
227
228
229
# File 'lib/chewy/rake_helper.rb', line 226

def reset_index(*indexes)
  ActiveSupport::Deprecation.warn '`Chewy::RakeHelper.reset_index` is deprecated and will be removed soon, use `Chewy::RakeHelper.reset` instead'
  reset(only: indexes)
end

.subscribed_task_stats(output = STDOUT) ⇒ Object


216
217
218
219
220
221
222
223
224
# File 'lib/chewy/rake_helper.rb', line 216

def subscribed_task_stats(output = STDOUT)
  start = Time.now
  ActiveSupport::Notifications.subscribed(JOURNAL_CALLBACK.curry[output], 'apply_journal.chewy') do
    ActiveSupport::Notifications.subscribed(IMPORT_CALLBACK.curry[output], 'import_objects.chewy') do
      yield
    end
  end
  output.puts "Total: #{human_duration(Time.now - start)}"
end

.sync(only: nil, except: nil, parallel: nil, output: STDOUT) ⇒ Array<Chewy::Type>

Performs synchronization for each passed index if it exists.

Examples:

Chewy::RakeHelper.sync # synchronizes everything
Chewy::RakeHelper.sync(only: 'places') # synchronizes only PlacesIndex::City and PlacesIndex::Country
Chewy::RakeHelper.sync(only: 'places#city') # synchronizes PlacesIndex::City only
Chewy::RakeHelper.sync(except: PlacesIndex::Country) # synchronizes everything, but PlacesIndex::Country
Chewy::RakeHelper.sync(only: 'places', except: 'places#country') # synchronizes PlacesIndex::City only

Parameters:

Returns:


128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
# File 'lib/chewy/rake_helper.rb', line 128

def sync(only: nil, except: nil, parallel: nil, output: STDOUT)
  subscribed_task_stats(output) do
    types_from(only: only, except: except).each_with_object([]) do |type, synced_types|
      output.puts "Synchronizing #{type}"
      output.puts "  #{type} doesn't support outdated synchronization" unless type.supports_outdated_sync?
      time = Time.now
      sync_result = type.sync(parallel: parallel)
      if !sync_result
        output.puts "  Something went wrong with the #{type} synchronization"
      elsif sync_result[:count] > 0
        output.puts "  Missing documents: #{sync_result[:missing]}" if sync_result[:missing].present?
        output.puts "  Outdated documents: #{sync_result[:outdated]}" if sync_result[:outdated].present?
        synced_types.push(type)
      else
        output.puts "  Skipping #{type}, up to date"
      end
      output.puts "  Took #{human_duration(Time.now - time)}"
    end
  end
end

.update(only: nil, except: nil, parallel: nil, output: STDOUT) ⇒ Array<Chewy::Type>

Performs full update for each passed type if the corresponding index exists.

Examples:

Chewy::RakeHelper.update # updates everything
Chewy::RakeHelper.update(only: 'places') # updates only PlacesIndex::City and PlacesIndex::Country
Chewy::RakeHelper.update(only: 'places#city') # updates PlacesIndex::City only
Chewy::RakeHelper.update(except: PlacesIndex::Country) # updates everything, but PlacesIndex::Country
Chewy::RakeHelper.update(only: 'places', except: 'places#country') # updates PlacesIndex::City only

Parameters:

Returns:


100
101
102
103
104
105
106
107
108
109
110
111
112
# File 'lib/chewy/rake_helper.rb', line 100

def update(only: nil, except: nil, parallel: nil, output: STDOUT)
  subscribed_task_stats(output) do
    types_from(only: only, except: except).group_by(&:index).each_with_object([]) do |(index, types), update_types|
      if index.exists?
        output.puts "Updating #{index}"
        types.each { |type| type.import(parallel: parallel) }
        update_types.concat(types)
      else
        output.puts "Skipping #{index}, it does not exists (use rake chewy:reset[#{index.derivable_name}] to create and update it)"
      end
    end
  end
end

.update_all(*except) ⇒ Object


241
242
243
244
# File 'lib/chewy/rake_helper.rb', line 241

def update_all(*except)
  ActiveSupport::Deprecation.warn '`Chewy::RakeHelper.update_all` is deprecated and will be removed soon, use `Chewy::RakeHelper.update` instead'
  update(except: except)
end

.update_index(*indexes) ⇒ Object


236
237
238
239
# File 'lib/chewy/rake_helper.rb', line 236

def update_index(*indexes)
  ActiveSupport::Deprecation.warn '`Chewy::RakeHelper.update_index` is deprecated and will be removed soon, use `Chewy::RakeHelper.update` instead'
  update(only: indexes)
end

.upgrade(only: nil, except: nil, parallel: nil, output: STDOUT) ⇒ Array<Chewy::Index>

Performs zero-downtime reindexing of all documents for the specified indexes only if a particular index specification was changed.

Examples:

Chewy::RakeHelper.upgrade # resets everything
Chewy::RakeHelper.upgrade(only: 'cities') # resets only CitiesIndex
Chewy::RakeHelper.upgrade(only: ['cities', CountriesIndex]) # resets CitiesIndex and CountriesIndex
Chewy::RakeHelper.upgrade(except: CitiesIndex) # resets everything, but CitiesIndex
Chewy::RakeHelper.upgrade(only: ['cities', 'countries'], except: CitiesIndex) # resets only CountriesIndex

Parameters:

  • only (Array<Chewy::Index, String>, Chewy::Index, String) (defaults to: nil)

    index or indexes to reset; if nothing is passed - uses all the indexes defined in the app

  • except (Array<Chewy::Index, String>, Chewy::Index, String) (defaults to: nil)

    index or indexes to exclude from processing

  • parallel (true, Integer, Hash) (defaults to: nil)

    any acceptable parallel options for import

  • output (IO) (defaults to: STDOUT)

    output io for logging

Returns:


62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
# File 'lib/chewy/rake_helper.rb', line 62

def upgrade(only: nil, except: nil, parallel: nil, output: STDOUT)
  subscribed_task_stats(output) do
    indexes = indexes_from(only: only, except: except)

    changed_indexes = indexes.select do |index|
      index.specification.changed?
    end

    if changed_indexes.present?
      indexes.each do |index|
        if changed_indexes.include?(index)
          reset_one(index, output, parallel: parallel)
        else
          output.puts "Skipping #{index}, the specification didn't change"
        end
      end
    else
      output.puts 'No index specification was changed'
    end

    changed_indexes
  end
end