elastics 0.1.1 → 0.2.0
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.
- checksums.yaml +4 -4
- data/.rspec +1 -0
- data/.travis.yml +7 -0
- data/README.md +80 -9
- data/Rakefile +3 -8
- data/elastics.gemspec +4 -1
- data/lib/elastics.rb +11 -0
- data/lib/elastics/active_record.rb +19 -4
- data/lib/elastics/active_record/helper_methods.rb +27 -26
- data/lib/elastics/active_record/instrumentation.rb +63 -7
- data/lib/elastics/active_record/model_schema.rb +22 -17
- data/lib/elastics/active_record/search_result.rb +49 -0
- data/lib/elastics/active_record/tasks_config.rb +25 -0
- data/lib/elastics/capistrano.rb +14 -0
- data/lib/elastics/client.rb +49 -22
- data/lib/elastics/client/cluster.rb +70 -0
- data/lib/elastics/railtie.rb +5 -4
- data/lib/elastics/tasks.rb +20 -19
- data/lib/elastics/tasks/config.rb +38 -0
- data/lib/elastics/tasks/indices.rb +72 -10
- data/lib/elastics/tasks/mappings.rb +11 -5
- data/lib/elastics/tasks/migrations.rb +42 -0
- data/lib/elastics/version.rb +1 -1
- data/lib/elastics/version_manager.rb +86 -0
- data/lib/tasks/elastics.rake +31 -8
- data/spec/lib/elastics/client/cluster_spec.rb +108 -0
- data/spec/spec_helper.rb +9 -0
- metadata +62 -7
- data/lib/elastics/active_record/log_subscriber.rb +0 -27
| @@ -0,0 +1,49 @@ | |
| 1 | 
            +
            module Elastics
         | 
| 2 | 
            +
              module ActiveRecord
         | 
| 3 | 
            +
                class SearchResult
         | 
| 4 | 
            +
                  attr_reader :result
         | 
| 5 | 
            +
             | 
| 6 | 
            +
                  def initialize(model, result, options = {})
         | 
| 7 | 
            +
                    @model = model
         | 
| 8 | 
            +
                    @result = result
         | 
| 9 | 
            +
                    @options = options
         | 
| 10 | 
            +
                  end
         | 
| 11 | 
            +
             | 
| 12 | 
            +
                  def hits
         | 
| 13 | 
            +
                    @hits ||= @result['hits'.freeze]
         | 
| 14 | 
            +
                  end
         | 
| 15 | 
            +
             | 
| 16 | 
            +
                  def ids
         | 
| 17 | 
            +
                    @ids ||= hits['hits'.freeze].map { |x| x['_id'.freeze].to_i }
         | 
| 18 | 
            +
                  end
         | 
| 19 | 
            +
             | 
| 20 | 
            +
                  def ids_to_find
         | 
| 21 | 
            +
                    @ids_to_find ||= begin
         | 
| 22 | 
            +
                      limit = @options[:limit]
         | 
| 23 | 
            +
                      limit ? ids[0...limit] : ids
         | 
| 24 | 
            +
                    end
         | 
| 25 | 
            +
                  end
         | 
| 26 | 
            +
             | 
| 27 | 
            +
                  def rest_ids
         | 
| 28 | 
            +
                    limit = @options[:limit]
         | 
| 29 | 
            +
                    limit ? ids[limit..-1] : []
         | 
| 30 | 
            +
                  end
         | 
| 31 | 
            +
             | 
| 32 | 
            +
                  def collection
         | 
| 33 | 
            +
                    @collection ||= @model.find_all_ordered ids_to_find
         | 
| 34 | 
            +
                  end
         | 
| 35 | 
            +
             | 
| 36 | 
            +
                  def relation
         | 
| 37 | 
            +
                    @model.where id: ids_to_find
         | 
| 38 | 
            +
                  end
         | 
| 39 | 
            +
             | 
| 40 | 
            +
                  def aggregations
         | 
| 41 | 
            +
                    @aggregations ||= @result['aggregations'.freeze]
         | 
| 42 | 
            +
                  end
         | 
| 43 | 
            +
             | 
| 44 | 
            +
                  def total
         | 
| 45 | 
            +
                    hits['total'.freeze]
         | 
| 46 | 
            +
                  end
         | 
| 47 | 
            +
                end
         | 
| 48 | 
            +
              end
         | 
| 49 | 
            +
            end
         | 
| @@ -0,0 +1,25 @@ | |
| 1 | 
            +
            module Elastics
         | 
| 2 | 
            +
              module ActiveRecord
         | 
| 3 | 
            +
                module TasksConfig
         | 
| 4 | 
            +
                  def base_paths
         | 
| 5 | 
            +
                    @base_paths ||= if defined?(Rails)
         | 
| 6 | 
            +
                      [File.join(Rails.root, 'db', 'elastics')]
         | 
| 7 | 
            +
                    else
         | 
| 8 | 
            +
                      super
         | 
| 9 | 
            +
                    end
         | 
| 10 | 
            +
                  end
         | 
| 11 | 
            +
             | 
| 12 | 
            +
                  def client
         | 
| 13 | 
            +
                    @client ||= ::ActiveRecord::Base.elastics
         | 
| 14 | 
            +
                  end
         | 
| 15 | 
            +
             | 
| 16 | 
            +
                  def version_manager
         | 
| 17 | 
            +
                    @version_manager ||= ::ActiveRecord::Base.elastics_version_manager
         | 
| 18 | 
            +
                  end
         | 
| 19 | 
            +
             | 
| 20 | 
            +
                  def config
         | 
| 21 | 
            +
                    @config ||= ::ActiveRecord::Base.elastics_config
         | 
| 22 | 
            +
                  end
         | 
| 23 | 
            +
                end
         | 
| 24 | 
            +
              end
         | 
| 25 | 
            +
            end
         | 
| @@ -0,0 +1,14 @@ | |
| 1 | 
            +
            Capistrano::Configuration.instance.load do
         | 
| 2 | 
            +
              namespace :elastics do
         | 
| 3 | 
            +
                %w(create drop migrate reindex).each do |method|
         | 
| 4 | 
            +
                  desc "rake elastics:#{method}"
         | 
| 5 | 
            +
                  task method, roles: :elastics, only: {primary: true} do
         | 
| 6 | 
            +
                    bundle_cmd = fetch(:bundle_cmd, 'bundle')
         | 
| 7 | 
            +
                    env = fetch(:rack_env, fetch(:rails_env, 'production'))
         | 
| 8 | 
            +
                    run "cd #{current_path} && " \
         | 
| 9 | 
            +
                      "#{bundle_cmd} exec rake elastics:#{method}[#{ENV['INDICES']}] #{ENV['ES_OPTIONS']} " \
         | 
| 10 | 
            +
                      "RAILS_ENV=#{env}"
         | 
| 11 | 
            +
                  end
         | 
| 12 | 
            +
                end
         | 
| 13 | 
            +
              end
         | 
| 14 | 
            +
            end
         | 
    
        data/lib/elastics/client.rb
    CHANGED
    
    | @@ -4,12 +4,18 @@ module Elastics | |
| 4 4 | 
             
              class Client
         | 
| 5 5 | 
             
                HEADERS = {'Content-Type' => 'application/json'}
         | 
| 6 6 |  | 
| 7 | 
            +
                autoload :Cluster, 'elastics/client/cluster'
         | 
| 8 | 
            +
             | 
| 7 9 | 
             
                attr_writer :index, :type
         | 
| 8 10 | 
             
                attr_reader :client
         | 
| 9 11 |  | 
| 10 12 | 
             
                def initialize(defaults = {})
         | 
| 11 | 
            -
                   | 
| 12 | 
            -
             | 
| 13 | 
            +
                  if defaults[:host].is_a?(Array)
         | 
| 14 | 
            +
                    extend Cluster
         | 
| 15 | 
            +
                    initialize_cluster(defaults)
         | 
| 16 | 
            +
                  else
         | 
| 17 | 
            +
                    @host = defaults[:host] || '127.0.0.1:9200'
         | 
| 18 | 
            +
                  end
         | 
| 13 19 | 
             
                  @index  = defaults[:index]
         | 
| 14 20 | 
             
                  @type   = defaults[:type]
         | 
| 15 21 | 
             
                  @client = HTTPClient.new
         | 
| @@ -28,45 +34,60 @@ module Elastics | |
| 28 34 | 
             
                  @type  = type  || nil
         | 
| 29 35 | 
             
                end
         | 
| 30 36 |  | 
| 31 | 
            -
                def  | 
| 32 | 
            -
                  str = " | 
| 33 | 
            -
                  if index = params[:index] | 
| 34 | 
            -
                    str  | 
| 35 | 
            -
                    type | 
| 36 | 
            -
                    str  | 
| 37 | 
            +
                def request_path(params)
         | 
| 38 | 
            +
                  str = ""
         | 
| 39 | 
            +
                  if index = params[:index] || @index
         | 
| 40 | 
            +
                    str << "/#{index}"
         | 
| 41 | 
            +
                    type = params[:type] || @type
         | 
| 42 | 
            +
                    str << "/#{type}" if type
         | 
| 37 43 | 
             
                  end
         | 
| 38 44 | 
             
                  path = params[:id]
         | 
| 39 | 
            -
                  str  | 
| 45 | 
            +
                  str << "/#{path}" if path
         | 
| 40 46 | 
             
                  str
         | 
| 41 47 | 
             
                end
         | 
| 42 48 |  | 
| 43 49 | 
             
                def request(params)
         | 
| 44 | 
            -
                   | 
| 50 | 
            +
                  method = params[:method] || :get
         | 
| 45 51 | 
             
                  body = params[:data].try!(:to_json)
         | 
| 46 | 
            -
                  res =  | 
| 52 | 
            +
                  res = http_request(method, request_path(params), params[:query], body, params)
         | 
| 47 53 | 
             
                  status = res.status
         | 
| 48 54 | 
             
                  return JSON.parse(res.body) if 300 > status
         | 
| 49 | 
            -
                   | 
| 50 | 
            -
             | 
| 51 | 
            -
             | 
| 52 | 
            -
                   | 
| 53 | 
            -
                  raise Error | 
| 55 | 
            +
                  result = JSON.parse(res.body) rescue nil
         | 
| 56 | 
            +
                  err_msg = "#{res.reason}: #{result && result['error'] || '-'}"
         | 
| 57 | 
            +
                  # NotFound is raised only for valid responses from ElasticSearch
         | 
| 58 | 
            +
                  raise NotFound, err_msg if 404 == status && result
         | 
| 59 | 
            +
                  raise Error, err_msg
         | 
| 54 60 | 
             
                end
         | 
| 55 61 |  | 
| 56 62 | 
             
                # shortcuts
         | 
| 57 | 
            -
                [:put, :post | 
| 63 | 
            +
                [:put, :post].each do |method|
         | 
| 58 64 | 
             
                  define_method(method) do |params|
         | 
| 59 65 | 
             
                    params[:method] = method
         | 
| 60 66 | 
             
                    request params
         | 
| 61 67 | 
             
                  end
         | 
| 62 68 | 
             
                end
         | 
| 63 69 |  | 
| 64 | 
            -
                def  | 
| 70 | 
            +
                def delete!(params)
         | 
| 71 | 
            +
                  params[:method] = :delete
         | 
| 72 | 
            +
                  request params
         | 
| 73 | 
            +
                end
         | 
| 74 | 
            +
             | 
| 75 | 
            +
                def delete(params)
         | 
| 76 | 
            +
                  delete!(params)
         | 
| 77 | 
            +
                rescue NotFound
         | 
| 78 | 
            +
                end
         | 
| 79 | 
            +
             | 
| 80 | 
            +
                def get!(params)
         | 
| 65 81 | 
             
                  params = {id: params} unless params.is_a?(Hash)
         | 
| 66 82 | 
             
                  params[:method] = :get
         | 
| 67 83 | 
             
                  request(params)
         | 
| 68 84 | 
             
                end
         | 
| 69 85 |  | 
| 86 | 
            +
                def get(params)
         | 
| 87 | 
            +
                  get!(params)
         | 
| 88 | 
            +
                rescue NotFound
         | 
| 89 | 
            +
                end
         | 
| 90 | 
            +
             | 
| 70 91 | 
             
                def set(id, data)
         | 
| 71 92 | 
             
                  request(id: id, data: data, method: :put)
         | 
| 72 93 | 
             
                end
         | 
| @@ -88,10 +109,16 @@ module Elastics | |
| 88 109 | 
             
                end
         | 
| 89 110 |  | 
| 90 111 | 
             
                def index_exists?(index)
         | 
| 91 | 
            -
                  get(index: index, type: nil, id: :_mapping)
         | 
| 92 | 
            -
                  true
         | 
| 93 | 
            -
                rescue NotFound
         | 
| 94 | 
            -
                  false
         | 
| 112 | 
            +
                  !!get(index: index, type: nil, id: :_mapping)
         | 
| 95 113 | 
             
                end
         | 
| 114 | 
            +
             | 
| 115 | 
            +
                private
         | 
| 116 | 
            +
                  # Endpoint for low-level request. For easy host highjacking & instrumentation.
         | 
| 117 | 
            +
                  # Params are not used directly but kept for instrumentation purpose.
         | 
| 118 | 
            +
                  # You probably don't want to use this method directly.
         | 
| 119 | 
            +
                  def http_request(method, path, query, body, params = nil, host = @host)
         | 
| 120 | 
            +
                    uri = "http://#{host}#{path}"
         | 
| 121 | 
            +
                    @client.request(method, uri, query, body, HEADERS)
         | 
| 122 | 
            +
                  end
         | 
| 96 123 | 
             
              end
         | 
| 97 124 | 
             
            end
         | 
| @@ -0,0 +1,70 @@ | |
| 1 | 
            +
            require 'timeout'
         | 
| 2 | 
            +
            require 'thread'
         | 
| 3 | 
            +
            require 'thread_safe'
         | 
| 4 | 
            +
             | 
| 5 | 
            +
            module Elastics
         | 
| 6 | 
            +
              class Client
         | 
| 7 | 
            +
                module Cluster
         | 
| 8 | 
            +
                  class NoAliveHosts < Error; end
         | 
| 9 | 
            +
             | 
| 10 | 
            +
                  private
         | 
| 11 | 
            +
                    def initialize_cluster(defaults)
         | 
| 12 | 
            +
                      @hosts = ThreadSafe::Array.new defaults[:host]
         | 
| 13 | 
            +
                      @dead_hosts = ThreadSafe::Hash.new
         | 
| 14 | 
            +
                      @connect_timeout = defaults[:connect_timeout] || 10
         | 
| 15 | 
            +
                      @resurrect_timeout = defaults[:resurrect_timeout] || 10
         | 
| 16 | 
            +
                      @current_host_n = 0
         | 
| 17 | 
            +
                      @cluster_mutex = Mutex.new
         | 
| 18 | 
            +
                    end
         | 
| 19 | 
            +
             | 
| 20 | 
            +
                    def http_request(method, path, query, body, params = nil)
         | 
| 21 | 
            +
                      host = next_cluster_host
         | 
| 22 | 
            +
                      Timeout.timeout(@connect_timeout) do
         | 
| 23 | 
            +
                        super(method, path, query, body, params, host)
         | 
| 24 | 
            +
                      end
         | 
| 25 | 
            +
                    rescue Timeout::Error, HTTPClient::ConnectTimeoutError
         | 
| 26 | 
            +
                      add_dead_host(host)
         | 
| 27 | 
            +
                      retry
         | 
| 28 | 
            +
                    end
         | 
| 29 | 
            +
             | 
| 30 | 
            +
                  # TODO: check Enumerable#cycle for thread-safety and use it if possible
         | 
| 31 | 
            +
                  def next_cluster_host
         | 
| 32 | 
            +
                    if @resurrect_at
         | 
| 33 | 
            +
                      time = Time.now.to_i
         | 
| 34 | 
            +
                      resurrect_cluster(time) if @resurrect_at <= time
         | 
| 35 | 
            +
                    end
         | 
| 36 | 
            +
                    host_n = @current_host_n
         | 
| 37 | 
            +
                    loop do
         | 
| 38 | 
            +
                      host = @hosts[host_n]
         | 
| 39 | 
            +
                      if !host
         | 
| 40 | 
            +
                        raise NoAliveHosts if host_n == 0
         | 
| 41 | 
            +
                        host_n = 0
         | 
| 42 | 
            +
                      else
         | 
| 43 | 
            +
                        @current_host_n = host_n + 1
         | 
| 44 | 
            +
                        return host
         | 
| 45 | 
            +
                      end
         | 
| 46 | 
            +
                    end
         | 
| 47 | 
            +
                  end
         | 
| 48 | 
            +
             | 
| 49 | 
            +
                  def resurrect_cluster(time = Time.now.to_i)
         | 
| 50 | 
            +
                    @cluster_mutex.synchronize do
         | 
| 51 | 
            +
                      @dead_hosts.delete_if do |host, resurrect_at|
         | 
| 52 | 
            +
                        # skip the rest because values are sorted
         | 
| 53 | 
            +
                        if time < resurrect_at
         | 
| 54 | 
            +
                          @resurrect_at = resurrect_at
         | 
| 55 | 
            +
                          break
         | 
| 56 | 
            +
                        end
         | 
| 57 | 
            +
                        @hosts << host
         | 
| 58 | 
            +
                      end
         | 
| 59 | 
            +
                    end
         | 
| 60 | 
            +
                  end
         | 
| 61 | 
            +
             | 
| 62 | 
            +
                  def add_dead_host(host, resurrect_at = nil)
         | 
| 63 | 
            +
                    resurrect_at ||= Time.now.to_i + @resurrect_timeout
         | 
| 64 | 
            +
                    @hosts.delete(host)
         | 
| 65 | 
            +
                    @dead_hosts[host] = resurrect_at
         | 
| 66 | 
            +
                    @resurrect_at ||= resurrect_at
         | 
| 67 | 
            +
                  end
         | 
| 68 | 
            +
                end
         | 
| 69 | 
            +
              end
         | 
| 70 | 
            +
            end
         | 
    
        data/lib/elastics/railtie.rb
    CHANGED
    
    | @@ -3,14 +3,15 @@ require 'elastics/active_record' | |
| 3 3 | 
             
            module Elastics
         | 
| 4 4 | 
             
              class Railtie < Rails::Railtie
         | 
| 5 5 | 
             
                initializer 'elastics.configure_rails_initialization' do
         | 
| 6 | 
            -
                   | 
| 7 | 
            -
                  unless ::ActiveRecord::LogSubscriber < ActiveRecord::LogSubscriber
         | 
| 8 | 
            -
                    ::ActiveRecord::LogSubscriber.send :include, ActiveRecord::LogSubscriber
         | 
| 9 | 
            -
                  end
         | 
| 6 | 
            +
                  ActiveRecord.install
         | 
| 10 7 | 
             
                end
         | 
| 11 8 |  | 
| 12 9 | 
             
                rake_tasks do
         | 
| 13 10 | 
             
                  load 'tasks/elastics.rake'
         | 
| 14 11 | 
             
                end
         | 
| 12 | 
            +
             | 
| 13 | 
            +
                config.to_prepare do
         | 
| 14 | 
            +
                  Elastics.reset_models
         | 
| 15 | 
            +
                end
         | 
| 15 16 | 
             
              end
         | 
| 16 17 | 
             
            end
         | 
    
        data/lib/elastics/tasks.rb
    CHANGED
    
    | @@ -1,35 +1,36 @@ | |
| 1 | 
            +
            require 'active_support'
         | 
| 2 | 
            +
            require 'active_support/core_ext'
         | 
| 3 | 
            +
             | 
| 1 4 | 
             
            module Elastics
         | 
| 2 5 | 
             
              module Tasks
         | 
| 6 | 
            +
                require 'elastics/tasks/config'
         | 
| 7 | 
            +
                include Config
         | 
| 8 | 
            +
             | 
| 3 9 | 
             
                require 'elastics/tasks/indices'
         | 
| 4 10 | 
             
                include Indices
         | 
| 5 11 |  | 
| 6 12 | 
             
                require 'elastics/tasks/mappings'
         | 
| 7 13 | 
             
                include Mappings
         | 
| 8 14 |  | 
| 9 | 
            -
                 | 
| 10 | 
            -
             | 
| 11 | 
            -
                attr_writer :base_paths, :client, :config
         | 
| 12 | 
            -
             | 
| 13 | 
            -
                def base_paths
         | 
| 14 | 
            -
                  @base_paths ||= [File.join(Rails.root, 'db', 'elastics')]
         | 
| 15 | 
            -
                end
         | 
| 15 | 
            +
                require 'elastics/tasks/migrations'
         | 
| 16 | 
            +
                include Migrations
         | 
| 16 17 |  | 
| 17 | 
            -
                 | 
| 18 | 
            -
                   | 
| 19 | 
            -
                   | 
| 20 | 
            -
                  put_mappings
         | 
| 18 | 
            +
                if defined?(::ActiveRecord) && defined?(::Elastics::ActiveRecord)
         | 
| 19 | 
            +
                  require 'elastics/active_record/tasks_config'
         | 
| 20 | 
            +
                  include ActiveRecord::TasksConfig
         | 
| 21 21 | 
             
                end
         | 
| 22 22 |  | 
| 23 | 
            -
                 | 
| 24 | 
            -
                  @client ||= ::ActiveRecord::Base.elastics
         | 
| 25 | 
            -
                end
         | 
| 26 | 
            -
             | 
| 27 | 
            -
                def config
         | 
| 28 | 
            -
                  @config ||= ::ActiveRecord::Base.elastics_config
         | 
| 29 | 
            -
                end
         | 
| 23 | 
            +
                extend self
         | 
| 30 24 |  | 
| 31 25 | 
             
                def log(*args)
         | 
| 32 | 
            -
                   | 
| 26 | 
            +
                  puts(*args)
         | 
| 33 27 | 
             
                end
         | 
| 28 | 
            +
             | 
| 29 | 
            +
                private
         | 
| 30 | 
            +
                  def each_filtered(collection, filter, &block)
         | 
| 31 | 
            +
                    filter = filter && filter.map(&:to_s)
         | 
| 32 | 
            +
                    collection = collection.select { |x| filter.include?(x) } if filter
         | 
| 33 | 
            +
                    collection.each &block
         | 
| 34 | 
            +
                  end
         | 
| 34 35 | 
             
              end
         | 
| 35 36 | 
             
            end
         | 
| @@ -0,0 +1,38 @@ | |
| 1 | 
            +
            module Elastics
         | 
| 2 | 
            +
              module Tasks
         | 
| 3 | 
            +
                # Module contains basic configuration methods.
         | 
| 4 | 
            +
                # You should setup Elastics::Task yourself unless you you use ActiveRecord.
         | 
| 5 | 
            +
                module Config
         | 
| 6 | 
            +
                  attr_writer :base_paths
         | 
| 7 | 
            +
             | 
| 8 | 
            +
                  def base_paths
         | 
| 9 | 
            +
                    @base_paths ||= Dir.pwd
         | 
| 10 | 
            +
                  end
         | 
| 11 | 
            +
             | 
| 12 | 
            +
                  def client
         | 
| 13 | 
            +
                    @client ||= Client.new config.slice(:host, :port)
         | 
| 14 | 
            +
                  end
         | 
| 15 | 
            +
             | 
| 16 | 
            +
                  def client=(val)
         | 
| 17 | 
            +
                    @version_manager = nil
         | 
| 18 | 
            +
                    @client = val
         | 
| 19 | 
            +
                  end
         | 
| 20 | 
            +
             | 
| 21 | 
            +
                  def version_manager
         | 
| 22 | 
            +
                    @version_manager ||= VersionManager.new(client, config.slice(
         | 
| 23 | 
            +
                      :service_index,
         | 
| 24 | 
            +
                      :index_prefix,
         | 
| 25 | 
            +
                    ))
         | 
| 26 | 
            +
                  end
         | 
| 27 | 
            +
             | 
| 28 | 
            +
                  def config
         | 
| 29 | 
            +
                    @config ||= {}
         | 
| 30 | 
            +
                  end
         | 
| 31 | 
            +
             | 
| 32 | 
            +
                  def config=(val)
         | 
| 33 | 
            +
                    @version_manager = nil
         | 
| 34 | 
            +
                    @config = val
         | 
| 35 | 
            +
                  end
         | 
| 36 | 
            +
                end
         | 
| 37 | 
            +
              end
         | 
| 38 | 
            +
            end
         | 
| @@ -1,5 +1,9 @@ | |
| 1 1 | 
             
            module Elastics
         | 
| 2 2 | 
             
              module Tasks
         | 
| 3 | 
            +
                # Most of methods accepts `options` hash with:
         | 
| 4 | 
            +
                # - `:indices` - array of indices to perform action on
         | 
| 5 | 
            +
                # - `:version` - mapping version to use in method
         | 
| 6 | 
            +
                #
         | 
| 3 7 | 
             
                module Indices
         | 
| 4 8 | 
             
                  attr_writer :indices_path
         | 
| 5 9 |  | 
| @@ -13,7 +17,6 @@ module Elastics | |
| 13 17 | 
             
                      each_with_object({}) do |file, hash|
         | 
| 14 18 | 
             
                        name = File.basename file, '.yml'
         | 
| 15 19 | 
             
                        data = YAML.load_file(file)
         | 
| 16 | 
            -
                        name = "#{config[:index_prefix]}#{name}"
         | 
| 17 20 | 
             
                        hash[name] = data[Rails.env] || data
         | 
| 18 21 | 
             
                      end
         | 
| 19 22 | 
             
                  end
         | 
| @@ -22,20 +25,79 @@ module Elastics | |
| 22 25 | 
             
                    @indices ||= config[:index] ? [config[:index]] : indices_settings.keys
         | 
| 23 26 | 
             
                  end
         | 
| 24 27 |  | 
| 25 | 
            -
                  def  | 
| 26 | 
            -
                     | 
| 27 | 
            -
             | 
| 28 | 
            -
             | 
| 28 | 
            +
                  def versioned_index_name(*args)
         | 
| 29 | 
            +
                    version_manager.index_name *args
         | 
| 30 | 
            +
                  end
         | 
| 31 | 
            +
             | 
| 32 | 
            +
                  def purge(keep_data = false)
         | 
| 33 | 
            +
                    unless keep_data
         | 
| 34 | 
            +
                      drop_indices
         | 
| 35 | 
            +
                      drop_indices version: :next
         | 
| 36 | 
            +
                    end
         | 
| 37 | 
            +
                    index = version_manager.service_index
         | 
| 38 | 
            +
                    log "Deleting index #{index}"
         | 
| 39 | 
            +
                    version_manager.reset
         | 
| 40 | 
            +
                    client.delete index: index
         | 
| 41 | 
            +
                  end
         | 
| 42 | 
            +
             | 
| 43 | 
            +
                  def drop_indices(options = {})
         | 
| 44 | 
            +
                    version = options.fetch :version, :current
         | 
| 45 | 
            +
                    each_filtered(indices, options[:indices]) do |index|
         | 
| 46 | 
            +
                      versioned_index = versioned_index_name(index, version)
         | 
| 47 | 
            +
                      log "Deleting index #{index} (#{versioned_index})"
         | 
| 48 | 
            +
                      client.delete index: versioned_index
         | 
| 29 49 | 
             
                    end
         | 
| 30 50 | 
             
                  end
         | 
| 31 51 |  | 
| 32 | 
            -
                  def create_indices
         | 
| 33 | 
            -
                     | 
| 34 | 
            -
             | 
| 35 | 
            -
                       | 
| 36 | 
            -
             | 
| 52 | 
            +
                  def create_indices(options = {})
         | 
| 53 | 
            +
                    version = options.fetch :version, :current
         | 
| 54 | 
            +
                    each_filtered(indices, options[:indices]) do |index|
         | 
| 55 | 
            +
                      versioned_index = versioned_index_name(index, version)
         | 
| 56 | 
            +
                      exists = client.index_exists?(versioned_index)
         | 
| 57 | 
            +
                      log_msg = "Creating index #{index} (#{versioned_index})"
         | 
| 58 | 
            +
                      log_msg << ' - Skipping: exists' if exists
         | 
| 59 | 
            +
                      log log_msg
         | 
| 60 | 
            +
                      unless exists
         | 
| 61 | 
            +
                        client.put(index: versioned_index, data: indices_settings[index])
         | 
| 37 62 | 
             
                      end
         | 
| 38 63 | 
             
                    end
         | 
| 64 | 
            +
                    manage_aliases :add, options if version.to_s == 'current'
         | 
| 65 | 
            +
                  end
         | 
| 66 | 
            +
             | 
| 67 | 
            +
                  # Action can be :add or :remove.
         | 
| 68 | 
            +
                  def manage_aliases(action, options = {})
         | 
| 69 | 
            +
                    version = options.fetch :version, :current
         | 
| 70 | 
            +
                    post_aliases(options) do |index|
         | 
| 71 | 
            +
                      alias_action(action, index, version)
         | 
| 72 | 
            +
                    end
         | 
| 73 | 
            +
                  end
         | 
| 74 | 
            +
             | 
| 75 | 
            +
                  def forward_aliases(options = {})
         | 
| 76 | 
            +
                    new_versions = {}
         | 
| 77 | 
            +
                    post_aliases options do |index|
         | 
| 78 | 
            +
                      new_versions[index] = version_manager.next_version index
         | 
| 79 | 
            +
                      [
         | 
| 80 | 
            +
                        alias_action(:remove, index, :current),
         | 
| 81 | 
            +
                        alias_action(:add, index, :next),
         | 
| 82 | 
            +
                      ]
         | 
| 83 | 
            +
                    end
         | 
| 84 | 
            +
                    drop_indices(options.merge version: :current) if options.fetch(:drop, true)
         | 
| 85 | 
            +
                    new_versions.each do |index, version|
         | 
| 86 | 
            +
                      version_manager.set index, current: version
         | 
| 87 | 
            +
                    end
         | 
| 88 | 
            +
                  end
         | 
| 89 | 
            +
             | 
| 90 | 
            +
                  def alias_action(action, index, version)
         | 
| 91 | 
            +
                    {action => {
         | 
| 92 | 
            +
                      index: versioned_index_name(index, version),
         | 
| 93 | 
            +
                      alias: versioned_index_name(index, :alias),
         | 
| 94 | 
            +
                    }}
         | 
| 95 | 
            +
                  end
         | 
| 96 | 
            +
             | 
| 97 | 
            +
                  def post_aliases(options = {}, &block)
         | 
| 98 | 
            +
                    actions = each_filtered(indices, options[:indices]).map(&block).flatten
         | 
| 99 | 
            +
                    log "Posting aliases: #{actions.inspect}"
         | 
| 100 | 
            +
                    client.post id: :_aliases, data: {actions: actions} if actions.any?
         | 
| 39 101 | 
             
                  end
         | 
| 40 102 | 
             
                end
         | 
| 41 103 | 
             
              end
         |