class Stretcher::Server

Attributes

http[R]
logger[R]
uri[R]

Public Class Methods

build_client(uri_components, options={}) click to toggle source

Internal use only. Returns a properly configured HTTP client when initializing an instance

# File lib/stretcher/server.rb, line 7
def self.build_client(uri_components, options={})
  http = Faraday.new(:url => uri_components) do |builder|
    builder.response :multi_json, :content_type => /\bjson$/

    builder.request :multi_json

    builder.options[:timeout] = options[:read_timeout] || 30
    builder.options[:open_timeout] = options[:open_timeout] || 2

    if faraday_configurator = options[:faraday_configurator]
      faraday_configurator.call(builder)
    else
      builder.adapter :excon
    end
  end
  http.headers = {
    :accept =>  'application/json',
    :user_agent => "Stretcher Ruby Gem #{Stretcher::VERSION}",
    "Content-Type" => "application/json"
  }

  if uri_components.user || uri_components.password
    http.basic_auth(uri_components.user, uri_components.password)
  end

  http
end
build_logger(options) click to toggle source

Internal use only. Builds a logger when initializing an instance

# File lib/stretcher/server.rb, line 37
def self.build_logger(options)
  logger = options[:logger] || Logger.new(STDOUT)

  # We don't want to override the formatter if an external logger is used
  if !options[:logger]
    log_level = options[:log_level] || :warn
    logger.level = Logger.const_get(log_level.to_s.upcase)
    logger.formatter = proc do |severity, datetime, progname, msg|
      "[Stretcher][#{severity}]: #{msg}\n"
    end
  end
  
  logger
end
new(uri='http://localhost:9200', options={}) click to toggle source

Represents a Server context in elastic search. Use with_server when you want to use the block syntax. The options hash takes an optional instance of Logger under :logger.

server = Stretcher::Server.new('http://localhost:9200')

The default implementation here uses the net_http_persistent adapter for faraday. If you would like to use a different HTTP library, or alter other faraday config settings you may specify an optional :faraday_configurator argument, with a Proc as a value. This will be called once with the faraday builder.

For instance: configurator = proc {|builder| builder.adapter :typhoeus Stretcher::Server.new(‘localhost:9200’, :faraday_configurator => configurator)

You may want to set one or both of :read_timeout and :open_timeout, for Faraday’s HTTP settings. The default is read_timeout: 30, open_timeout: 2, which can be quite long in many situations

# File lib/stretcher/server.rb, line 78
def initialize(uri='http://localhost:9200', options={})
  @request_mtx = Mutex.new
  @uri = uri.to_s
  @uri_components = URI.parse(@uri)
  @http = self.class.build_client(@uri_components, options)
  @logger = self.class.build_logger(options)
end
with_server(*args) { |s| ... } click to toggle source

Instantiate a new instance in a manner convenient for using the block syntax. Can be used interchangably with Stretcher::Server.new but will return the value of the block if present. See the regular constructor for full options.

# File lib/stretcher/server.rb, line 55
def self.with_server(*args)
  s = self.new(*args)
  yield s
end

Public Instance Methods

aliases(body=nil) click to toggle source

Implements the Aliases API Ex: server.aliases({actions: {add: {index: :my_index, alias: :my_alias}}}) as per: www.elasticsearch.org/guide/reference/api/admin-indices-aliases.html

# File lib/stretcher/server.rb, line 191
def aliases(body=nil)
  if body
    request(:post, path_uri("/_aliases"), {}, body)
  else
    request(:get, path_uri("/_aliases"))
  end
end
analyze(text, analysis_params) click to toggle source

Implements the Analyze API Ex:

server.analyze("Candles", analyzer: :snowball)
# => #<Hashie::Mash tokens=[#<Hashie::Mash end_offset=7 position=1 start_offset=0 token="candl" type="<ALPHANUM>">]>

as per: www.elasticsearch.org/guide/reference/api/admin-indices-analyze.html

# File lib/stretcher/server.rb, line 181
def analyze(text, analysis_params)
  request(:get, path_uri("/_analyze"), analysis_params) do |req|
    req.body = text
  end
end
bulk(data, options={}) click to toggle source

Perform a raw bulk operation. You probably want to use Stretcher::Index#bulk_index which properly formats a bulk index request.

# File lib/stretcher/server.rb, line 107
def bulk(data, options={})
  request(:post, path_uri("/_bulk"), options, data)
end
cluster(&block) click to toggle source

Returns the Stretcher::Cluster for this server Optionally takes a block, which will be passed a single arg with the Cluster object. The block returns the evaluated value of the block.

# File lib/stretcher/server.rb, line 100
def cluster(&block)
  cluster = Cluster.new(self, :logger => logger)
  block ? block.call(cluster) : cluster
end
get_alias(alias_name_or_prefix) click to toggle source
# File lib/stretcher/server.rb, line 199
def get_alias(alias_name_or_prefix)
  do_alias(alias_name_or_prefix)
end
index(name, &block) click to toggle source

Returns a Stretcher::Index object for the index name. Optionally takes a block, which will be passed a single arg with the Index obj The block syntax returns the evaluated value of the block

my_server.index(:foo) # => #<Stretcher::Index ...>
my_server.index(:foo) {|idx| 1+1} # => 2
# File lib/stretcher/server.rb, line 92
def index(name, &block)
  idx = Index.new(self, name, :logger => logger)
  block ? block.call(idx) : idx
end
legacy_mget(body) click to toggle source

legacy implementation of mget for backwards compat

# File lib/stretcher/server.rb, line 172
def legacy_mget(body)
  request(:get, path_uri("/_mget"), {}, body)
end
mget(docs=[], arg_opts={}) click to toggle source

Retrieves multiple documents, possibly from multiple indexes Takes an array of docs, returns an array of docs as per: www.elasticsearch.org/guide/reference/api/multi-get.html If you pass :exists => true as the second argument it will not return stubs for missing documents. :exists => false works in reverse

# File lib/stretcher/server.rb, line 156
def mget(docs=[], arg_opts={})
  #Legacy API
  return legacy_mget(docs) if docs.is_a?(Hash)
  
  opts = {:exists => true}.merge(arg_opts)
  
  res = request(:get, path_uri("/_mget"), {}, {:docs => docs})[:docs]
  if opts.has_key?(:exists)
    match = opts[:exists]
    res.select {|d| d[:exists] == match}
  else
    res
  end
end
msearch(body=[]) click to toggle source

Takes an array of msearch data as per www.elasticsearch.org/guide/reference/api/multi-search.html Should look something like:

data = [
  {"index" : "test"}
  {"query" : {"match_all" : {}}, "from" : 0, "size" : 10}
  {"index" : "test", "search_type" : "count"}
  {"query" : {"match_all" : {}}}
]
server.msearch(data)
# File lib/stretcher/server.rb, line 137
def msearch(body=[])
  raise ArgumentError, "msearch takes an array!" unless body.is_a?(Array)
  fmt_body = body.map {|l| MultiJson.dump(l) }.join("\n") << "\n"

  res = request(:get, path_uri("/_msearch"), {}, fmt_body, {}, :mashify => false)

  errors = res['responses'].map { |response| response['error'] }.compact
  if !errors.empty?
    raise RequestError.new(res), "Could not msearch #{errors.inspect}"
  end

  res['responses'].map {|r| SearchResults.new(r)}
end
path_uri(path=nil) click to toggle source

Full path to the server root dir

# File lib/stretcher/server.rb, line 209
def path_uri(path=nil)
  URI.join(@uri.to_s, "#{@uri_components.path}/#{path.to_s}").to_s
end
refresh() click to toggle source

Perform a refresh, making all indexed documents available

# File lib/stretcher/server.rb, line 204
def refresh
  do_refresh
end
request(method, path, params={}, body=nil, headers={}, options={}, &block) click to toggle source

Handy way to query the server, returning only the body Will raise an exception when the status is not in the 2xx range

# File lib/stretcher/server.rb, line 215
def request(method, path, params={}, body=nil, headers={}, options={}, &block)
  options = { :mashify => true }.merge(options)
  req = http.build_request(method)
  req.path = path
  req.params.update(Util.clean_params(params)) if params
  req.body = body
  req.headers.update(headers) if headers
  block.call(req) if block
  logger.debug { Util.curl_format(req) }

  @request_mtx.synchronize {
    env = req.to_env(http)
    check_response(http.app.call(env), options)
  }
end
stats() click to toggle source

Retrieves stats for this server

# File lib/stretcher/server.rb, line 112
def stats
  request :get, path_uri("/_stats")
end
status() click to toggle source

Retrieves status for this server

# File lib/stretcher/server.rb, line 117
def status
  request :get, path_uri("/_status")
end
up?() click to toggle source

Returns true if the server is currently reachable, raises an error otherwise

# File lib/stretcher/server.rb, line 122
def up?
  request(:get, path_uri)
  true
end

Private Instance Methods

check_response(res, options) click to toggle source

Internal use only Check response codes from request

# File lib/stretcher/server.rb, line 236
def check_response(res, options)
  if res.status >= 200 && res.status <= 299
    if(options[:mashify] && res.body.instance_of?(Hash))
      Hashie::Mash.new(res.body)
    else
      res.body
    end
  elsif [404, 410].include? res.status
    err_str = "Error processing request: (#{res.status})! #{res.env[:method]} URL: #{res.env[:url]}"
    err_str << "\n Resp Body: #{res.body}"
    raise RequestError::NotFound.new(res), err_str
  else
    err_str = "Error processing request (#{res.status})! #{res.env[:method]} URL: #{res.env[:url]}"
    err_str << "\n Resp Body: #{res.body}"
    raise RequestError.new(res), err_str
  end
end