tiny-quick-gem 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (34) hide show
  1. checksums.yaml +7 -0
  2. data/searchkick-6.1.2/CHANGELOG.md +919 -0
  3. data/searchkick-6.1.2/LICENSE.txt +22 -0
  4. data/searchkick-6.1.2/README.md +2348 -0
  5. data/searchkick-6.1.2/lib/searchkick/bulk_reindex_job.rb +19 -0
  6. data/searchkick-6.1.2/lib/searchkick/controller_runtime.rb +40 -0
  7. data/searchkick-6.1.2/lib/searchkick/hash_wrapper.rb +41 -0
  8. data/searchkick-6.1.2/lib/searchkick/index.rb +480 -0
  9. data/searchkick-6.1.2/lib/searchkick/index_cache.rb +30 -0
  10. data/searchkick-6.1.2/lib/searchkick/index_options.rb +652 -0
  11. data/searchkick-6.1.2/lib/searchkick/indexer.rb +43 -0
  12. data/searchkick-6.1.2/lib/searchkick/log_subscriber.rb +57 -0
  13. data/searchkick-6.1.2/lib/searchkick/middleware.rb +19 -0
  14. data/searchkick-6.1.2/lib/searchkick/model.rb +120 -0
  15. data/searchkick-6.1.2/lib/searchkick/multi_search.rb +46 -0
  16. data/searchkick-6.1.2/lib/searchkick/process_batch_job.rb +20 -0
  17. data/searchkick-6.1.2/lib/searchkick/process_queue_job.rb +33 -0
  18. data/searchkick-6.1.2/lib/searchkick/query.rb +1372 -0
  19. data/searchkick-6.1.2/lib/searchkick/railtie.rb +7 -0
  20. data/searchkick-6.1.2/lib/searchkick/record_data.rb +147 -0
  21. data/searchkick-6.1.2/lib/searchkick/record_indexer.rb +174 -0
  22. data/searchkick-6.1.2/lib/searchkick/reindex_queue.rb +57 -0
  23. data/searchkick-6.1.2/lib/searchkick/reindex_v2_job.rb +17 -0
  24. data/searchkick-6.1.2/lib/searchkick/relation.rb +728 -0
  25. data/searchkick-6.1.2/lib/searchkick/relation_indexer.rb +184 -0
  26. data/searchkick-6.1.2/lib/searchkick/reranking.rb +28 -0
  27. data/searchkick-6.1.2/lib/searchkick/results.rb +359 -0
  28. data/searchkick-6.1.2/lib/searchkick/script.rb +11 -0
  29. data/searchkick-6.1.2/lib/searchkick/version.rb +3 -0
  30. data/searchkick-6.1.2/lib/searchkick/where.rb +11 -0
  31. data/searchkick-6.1.2/lib/searchkick.rb +388 -0
  32. data/searchkick-6.1.2/lib/tasks/searchkick.rake +37 -0
  33. data/tiny-quick-gem.gemspec +12 -0
  34. metadata +73 -0
@@ -0,0 +1,57 @@
1
+ # based on https://gist.github.com/mnutt/566725
2
+ module Searchkick
3
+ class LogSubscriber < ActiveSupport::LogSubscriber
4
+ def self.runtime=(value)
5
+ Thread.current[:searchkick_runtime] = value
6
+ end
7
+
8
+ def self.runtime
9
+ Thread.current[:searchkick_runtime] ||= 0
10
+ end
11
+
12
+ def self.reset_runtime
13
+ rt = runtime
14
+ self.runtime = 0
15
+ rt
16
+ end
17
+
18
+ def search(event)
19
+ self.class.runtime += event.duration
20
+ return unless logger.debug?
21
+
22
+ payload = event.payload
23
+ name = "#{payload[:name]} (#{event.duration.round(1)}ms)"
24
+
25
+ index = payload[:query][:index].is_a?(Array) ? payload[:query][:index].join(",") : payload[:query][:index]
26
+ type = payload[:query][:type]
27
+ request_params = payload[:query].except(:index, :type, :body, :opaque_id)
28
+
29
+ params = []
30
+ request_params.each do |k, v|
31
+ params << "#{CGI.escape(k.to_s)}=#{CGI.escape(v.to_s)}"
32
+ end
33
+
34
+ debug " #{color(name, YELLOW, bold: true)} #{index}#{type ? "/#{type.join(',')}" : ''}/_search#{params.any? ? '?' + params.join('&') : nil} #{payload[:query][:body].to_json}"
35
+ end
36
+
37
+ def request(event)
38
+ self.class.runtime += event.duration
39
+ return unless logger.debug?
40
+
41
+ payload = event.payload
42
+ name = "#{payload[:name]} (#{event.duration.round(1)}ms)"
43
+
44
+ debug " #{color(name, YELLOW, bold: true)} #{payload.except(:name).to_json}"
45
+ end
46
+
47
+ def multi_search(event)
48
+ self.class.runtime += event.duration
49
+ return unless logger.debug?
50
+
51
+ payload = event.payload
52
+ name = "#{payload[:name]} (#{event.duration.round(1)}ms)"
53
+
54
+ debug " #{color(name, YELLOW, bold: true)} _msearch #{payload[:body]}"
55
+ end
56
+ end
57
+ end
@@ -0,0 +1,19 @@
1
+ require "faraday"
2
+
3
+ module Searchkick
4
+ class Middleware < Faraday::Middleware
5
+ def call(env)
6
+ path = env[:url].path.to_s
7
+ if path.end_with?("/_search")
8
+ env[:request][:timeout] = Searchkick.search_timeout
9
+ elsif path.end_with?("/_msearch")
10
+ # assume no concurrent searches for timeout for now
11
+ searches = env[:request_body].count("\n") / 2
12
+ # do not allow timeout to exceed Searchkick.timeout
13
+ timeout = [Searchkick.search_timeout * searches, Searchkick.timeout].min
14
+ env[:request][:timeout] = timeout
15
+ end
16
+ @app.call(env)
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,120 @@
1
+ module Searchkick
2
+ module Model
3
+ def searchkick(**options)
4
+ options = Searchkick.model_options.deep_merge(options)
5
+
6
+ if options[:conversions]
7
+ Searchkick.warn("The `conversions` option is deprecated in favor of `conversions_v2`, which provides much better search performance. Upgrade to `conversions_v2` or rename `conversions` to `conversions_v1`")
8
+ end
9
+
10
+ if options.key?(:conversions_v1)
11
+ options[:conversions] = options.delete(:conversions_v1)
12
+ end
13
+
14
+ unknown_keywords = options.keys - [:_all, :_type, :batch_size, :callbacks, :callback_options, :case_sensitive, :conversions, :conversions_v2, :deep_paging, :default_fields,
15
+ :filterable, :geo_shape, :highlight, :ignore_above, :index_name, :index_prefix, :inheritance, :job_options, :knn, :language,
16
+ :locations, :mappings, :match, :max_result_window, :merge_mappings, :routing, :searchable, :search_synonyms, :settings, :similarity,
17
+ :special_characters, :stem, :stemmer, :stem_conversions, :stem_exclusion, :stemmer_override, :suggest, :synonyms, :text_end,
18
+ :text_middle, :text_start, :unscope, :word, :word_end, :word_middle, :word_start]
19
+ raise ArgumentError, "unknown keywords: #{unknown_keywords.join(", ")}" if unknown_keywords.any?
20
+
21
+ raise "Only call searchkick once per model" if respond_to?(:searchkick_index)
22
+
23
+ Searchkick.models << self
24
+
25
+ options[:_type] ||= -> { searchkick_index.klass_document_type(self, true) }
26
+ options[:class_name] = model_name.name
27
+
28
+ callbacks = options.key?(:callbacks) ? options[:callbacks] : :inline
29
+ unless [:inline, true, false, :async, :queue].include?(callbacks)
30
+ raise ArgumentError, "Invalid value for callbacks"
31
+ end
32
+ callback_options = (options[:callback_options] || {}).dup
33
+ callback_options[:if] = [-> { Searchkick.callbacks?(default: callbacks) }, callback_options[:if]].compact.flatten(1)
34
+
35
+ base = self
36
+
37
+ mod = Module.new
38
+ include(mod)
39
+ mod.module_eval do
40
+ def reindex(method_name = nil, mode: nil, refresh: false, ignore_missing: nil, job_options: nil)
41
+ self.class.searchkick_index.reindex([self], method_name: method_name, mode: mode, refresh: refresh, ignore_missing: ignore_missing, job_options: job_options, single: true)
42
+ end unless base.method_defined?(:reindex)
43
+
44
+ def similar(**options)
45
+ self.class.searchkick_index.similar_record(self, **options)
46
+ end unless base.method_defined?(:similar)
47
+
48
+ def search_data
49
+ data = respond_to?(:to_hash) ? to_hash : serializable_hash
50
+ data.delete("id")
51
+ data.delete("_id")
52
+ data.delete("_type")
53
+ data
54
+ end unless base.method_defined?(:search_data)
55
+
56
+ def should_index?
57
+ true
58
+ end unless base.method_defined?(:should_index?)
59
+ end
60
+
61
+ class_eval do
62
+ cattr_reader :searchkick_options, :searchkick_klass, instance_reader: false
63
+
64
+ class_variable_set :@@searchkick_options, options.dup
65
+ class_variable_set :@@searchkick_klass, self
66
+ class_variable_set :@@searchkick_index_cache, Searchkick::IndexCache.new
67
+
68
+ class << self
69
+ def searchkick_search(term = "*", **options, &block)
70
+ if Searchkick.relation?(self)
71
+ raise Searchkick::Error, "search must be called on model, not relation"
72
+ end
73
+
74
+ Searchkick.search(term, model: self, **options, &block)
75
+ end
76
+ alias_method Searchkick.search_method_name, :searchkick_search if Searchkick.search_method_name
77
+
78
+ def searchkick_index(name: nil)
79
+ index_name = name || searchkick_klass.searchkick_index_name
80
+ index_name = index_name.call if index_name.respond_to?(:call)
81
+ index_cache = class_variable_get(:@@searchkick_index_cache)
82
+ index_cache.fetch(index_name) { Searchkick::Index.new(index_name, searchkick_options) }
83
+ end
84
+ alias_method :search_index, :searchkick_index unless method_defined?(:search_index)
85
+
86
+ def searchkick_reindex(method_name = nil, **options)
87
+ searchkick_index.reindex(self, method_name: method_name, **options)
88
+ end
89
+ alias_method :reindex, :searchkick_reindex unless method_defined?(:reindex)
90
+
91
+ def searchkick_index_options
92
+ searchkick_index.index_options
93
+ end
94
+
95
+ def searchkick_index_name
96
+ @searchkick_index_name ||= begin
97
+ options = class_variable_get(:@@searchkick_options)
98
+ if options[:index_name]
99
+ options[:index_name]
100
+ elsif options[:index_prefix].respond_to?(:call)
101
+ -> { [options[:index_prefix].call, model_name.plural, Searchkick.env, Searchkick.index_suffix].compact.join("_") }
102
+ else
103
+ [options.key?(:index_prefix) ? options[:index_prefix] : Searchkick.index_prefix, model_name.plural, Searchkick.env, Searchkick.index_suffix].compact.join("_")
104
+ end
105
+ end
106
+ end
107
+ end
108
+
109
+ # always add callbacks, even when callbacks is false
110
+ # so Model.callbacks block can be used
111
+ if respond_to?(:after_commit)
112
+ after_commit :reindex, **callback_options
113
+ elsif respond_to?(:after_save)
114
+ after_save :reindex, **callback_options
115
+ after_destroy :reindex, **callback_options
116
+ end
117
+ end
118
+ end
119
+ end
120
+ end
@@ -0,0 +1,46 @@
1
+ module Searchkick
2
+ class MultiSearch
3
+ attr_reader :queries
4
+
5
+ def initialize(queries, opaque_id: nil)
6
+ @queries = queries
7
+ @opaque_id = opaque_id
8
+ end
9
+
10
+ def perform
11
+ if queries.any?
12
+ perform_search(queries)
13
+ end
14
+ end
15
+
16
+ private
17
+
18
+ def perform_search(search_queries, perform_retry: true)
19
+ params = {
20
+ body: search_queries.flat_map { |q| [q.params.except(:body), q.body] }
21
+ }
22
+ params[:opaque_id] = @opaque_id if @opaque_id
23
+ responses = client.msearch(params)["responses"]
24
+
25
+ retry_queries = []
26
+ search_queries.each_with_index do |query, i|
27
+ if perform_retry && query.retry_misspellings?(responses[i])
28
+ query.send(:prepare) # okay, since we don't want to expose this method outside Searchkick
29
+ retry_queries << query
30
+ else
31
+ query.handle_response(responses[i])
32
+ end
33
+ end
34
+
35
+ if retry_queries.any?
36
+ perform_search(retry_queries, perform_retry: false)
37
+ end
38
+
39
+ search_queries
40
+ end
41
+
42
+ def client
43
+ Searchkick.client
44
+ end
45
+ end
46
+ end
@@ -0,0 +1,20 @@
1
+ module Searchkick
2
+ class ProcessBatchJob < Searchkick.parent_job.constantize
3
+ queue_as { Searchkick.queue_name }
4
+
5
+ def perform(class_name:, record_ids:, index_name: nil)
6
+ model = Searchkick.load_model(class_name)
7
+ index = model.searchkick_index(name: index_name)
8
+
9
+ items =
10
+ record_ids.map do |r|
11
+ parts = r.split(/(?<!\|)\|(?!\|)/, 2)
12
+ .map { |v| v.gsub("||", "|") }
13
+ {id: parts[0], routing: parts[1]}
14
+ end
15
+
16
+ relation = Searchkick.scope(model)
17
+ RecordIndexer.new(index).reindex_items(relation, items, method_name: nil, ignore_missing: nil)
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,33 @@
1
+ module Searchkick
2
+ class ProcessQueueJob < Searchkick.parent_job.constantize
3
+ queue_as { Searchkick.queue_name }
4
+
5
+ def perform(class_name:, index_name: nil, inline: false, job_options: nil)
6
+ model = Searchkick.load_model(class_name)
7
+ index = model.searchkick_index(name: index_name)
8
+ limit = model.searchkick_options[:batch_size] || 1000
9
+ job_options = (model.searchkick_options[:job_options] || {}).merge(job_options || {})
10
+
11
+ loop do
12
+ record_ids = index.reindex_queue.reserve(limit: limit)
13
+ if record_ids.any?
14
+ batch_options = {
15
+ class_name: class_name,
16
+ record_ids: record_ids.uniq,
17
+ index_name: index_name
18
+ }
19
+
20
+ if inline
21
+ # use new.perform to avoid excessive logging
22
+ Searchkick::ProcessBatchJob.new.perform(**batch_options)
23
+ else
24
+ Searchkick::ProcessBatchJob.set(job_options).perform_later(**batch_options)
25
+ end
26
+
27
+ # TODO when moving to reliable queuing, mark as complete
28
+ end
29
+ break unless record_ids.size == limit
30
+ end
31
+ end
32
+ end
33
+ end