csdn-tire 0.5

Sign up to get free protection for your applications and to get access to all the features.
data/lib/tire.rb ADDED
@@ -0,0 +1,26 @@
1
+ # -*- encoding : utf-8 -*-
2
+ require 'rest_client'
3
+ require 'multi_json'
4
+ require 'hashr'
5
+ require 'cgi'
6
+
7
+ require 'active_support/core_ext'
8
+
9
+ # Ruby 1.8 compatibility
10
+ require 'tire/rubyext/ruby_1_8' if defined?(RUBY_VERSION) && RUBY_VERSION < '1.9'
11
+ require 'tire/rubyext/to_json'
12
+ require 'tire/utils'
13
+ require 'tire/logger'
14
+ require 'tire/configuration'
15
+ require 'tire/http/response'
16
+ require 'tire/http/client'
17
+ require 'tire/search'
18
+ require 'tire/count'
19
+ require 'tire/state'
20
+ require 'tire/results/pagination'
21
+ require 'tire/index'
22
+ require 'tire/dsl'
23
+
24
+ module Tire
25
+ extend DSL
26
+ end
@@ -0,0 +1,31 @@
1
+ # -*- encoding : utf-8 -*-
2
+ module Tire
3
+
4
+ class Configuration
5
+
6
+ def self.nodes_count(n=2)
7
+ @nodes_count ||= n
8
+ end
9
+
10
+ def self.url(value=nil)
11
+ @url = (value ? value.to_s.gsub(%r|/*$|, '') : nil) || @url || ENV['ELASTICSEARCH_URL'] || "http://localhost:9200"
12
+ end
13
+
14
+ def self.client(klass=nil)
15
+ @client = klass || @client || HTTP::Client::RestClient
16
+ end
17
+
18
+ def self.logger(device=nil, options={})
19
+ return @logger = Logger.new(device, options) if device
20
+ @logger || nil
21
+ end
22
+
23
+ def self.reset(*properties)
24
+ reset_variables = properties.empty? ? instance_variables : instance_variables.map { |p| p.to_s} & \
25
+ properties.map { |p| "@#{p}" }
26
+ reset_variables.each { |v| instance_variable_set(v.to_sym, nil) }
27
+ end
28
+
29
+ end
30
+
31
+ end
data/lib/tire/count.rb ADDED
@@ -0,0 +1,24 @@
1
+ # -*- encoding : utf-8 -*-
2
+ module Tire
3
+ class SearchRequestFailed < StandardError; end
4
+
5
+ class Count < Search
6
+
7
+ def initialize(indices, types, payload)
8
+ @indices = Array(indices)
9
+ @types = Array(types).map { |type| Utils.escape(type) }
10
+ if payload.is_a?(String)
11
+ @payload = payload
12
+ else
13
+ @payload_hash = payload
14
+ end
15
+
16
+ @path = ['/', @indices.join(','), @types.join(','), '_count'].compact.join('/').squeeze('/')
17
+ end
18
+
19
+ def results
20
+ perform
21
+ return @json["totalHits"]
22
+ end
23
+ end
24
+ end
data/lib/tire/dsl.rb ADDED
@@ -0,0 +1,26 @@
1
+ # -*- encoding : utf-8 -*-
2
+ module Tire
3
+ module DSL
4
+
5
+ def configure(&block)
6
+ Configuration.class_eval(&block)
7
+ end
8
+
9
+ def index(name)
10
+ Index.new(name)
11
+ end
12
+
13
+ def search(names, types, payload)
14
+ Search.new(names, types, payload)
15
+ end
16
+
17
+ def count(names, types, payload)
18
+ Count.new(names, types, payload)
19
+ end
20
+
21
+ def state
22
+ State.new
23
+ end
24
+
25
+ end
26
+ end
@@ -0,0 +1,63 @@
1
+ # -*- encoding : utf-8 -*-
2
+ module Tire
3
+
4
+ module HTTP
5
+
6
+ module Client
7
+
8
+ class RestClient
9
+ ConnectionExceptions = [::RestClient::ServerBrokeConnection, ::RestClient::RequestTimeout]
10
+
11
+ def self.get(url, data=nil)
12
+ perform ::RestClient::Request.new(:method => :get, :url => url, :payload => data).execute
13
+ rescue *ConnectionExceptions
14
+ raise
15
+ rescue ::RestClient::Exception => e
16
+ Response.new e.http_body, e.http_code
17
+ end
18
+
19
+ def self.post(url, data)
20
+ perform ::RestClient.post(url, data)
21
+ rescue *ConnectionExceptions
22
+ raise
23
+ rescue ::RestClient::Exception => e
24
+ Response.new e.http_body, e.http_code
25
+ end
26
+
27
+ def self.put(url, data)
28
+ perform ::RestClient.put(url, data)
29
+ rescue *ConnectionExceptions
30
+ raise
31
+ rescue ::RestClient::Exception => e
32
+ Response.new e.http_body, e.http_code
33
+ end
34
+
35
+ def self.delete(url)
36
+ perform ::RestClient.delete(url)
37
+ rescue *ConnectionExceptions
38
+ raise
39
+ rescue ::RestClient::Exception => e
40
+ Response.new e.http_body, e.http_code
41
+ end
42
+
43
+ def self.head(url)
44
+ perform ::RestClient.head(url)
45
+ rescue *ConnectionExceptions
46
+ raise
47
+ rescue ::RestClient::Exception => e
48
+ Response.new e.http_body, e.http_code
49
+ end
50
+
51
+ private
52
+
53
+ def self.perform(response)
54
+ Response.new response.body, response.code, response.headers
55
+ end
56
+
57
+ end
58
+
59
+ end
60
+
61
+ end
62
+
63
+ end
@@ -0,0 +1,62 @@
1
+ # -*- encoding : utf-8 -*-
2
+ require 'curb'
3
+
4
+ module Tire
5
+
6
+ module HTTP
7
+
8
+ module Client
9
+
10
+ class Curb
11
+ @client = ::Curl::Easy.new
12
+ @client.resolve_mode = :ipv4
13
+
14
+ # @client.verbose = true
15
+
16
+ def self.get(url, data=nil)
17
+ @client.url = url
18
+
19
+ # FIXME: Curb cannot post bodies with GET requests?
20
+ # Roy Fielding seems to approve:
21
+ # <http://tech.groups.yahoo.com/group/rest-discuss/message/9962>
22
+ if data
23
+ @client.post_body = data
24
+ @client.http_post
25
+ else
26
+ @client.http_get
27
+ end
28
+ Response.new @client.body_str, @client.response_code
29
+ end
30
+
31
+ def self.post(url, data)
32
+ @client.url = url
33
+ @client.post_body = data
34
+ @client.http_post
35
+ Response.new @client.body_str, @client.response_code
36
+ end
37
+
38
+ def self.put(url, data)
39
+ @client.url = url
40
+ @client.http_put data
41
+ Response.new @client.body_str, @client.response_code
42
+ end
43
+
44
+ def self.delete(url)
45
+ @client.url = url
46
+ @client.http_delete
47
+ Response.new @client.body_str, @client.response_code
48
+ end
49
+
50
+ def self.head(url)
51
+ @client.url = url
52
+ @client.http_head
53
+ Response.new @client.body_str, @client.response_code
54
+ end
55
+
56
+ end
57
+
58
+ end
59
+
60
+ end
61
+
62
+ end
@@ -0,0 +1,28 @@
1
+ # -*- encoding : utf-8 -*-
2
+ module Tire
3
+
4
+ module HTTP
5
+
6
+ class Response
7
+ attr_reader :body, :code, :headers
8
+
9
+ def initialize(body, code, headers={})
10
+ @body, @code, @headers = body, code.to_i, headers
11
+ end
12
+
13
+ def success?
14
+ code > 0 && code < 400
15
+ end
16
+
17
+ def failure?
18
+ ! success?
19
+ end
20
+
21
+ def to_s
22
+ [code, body].join(' : ')
23
+ end
24
+ end
25
+
26
+ end
27
+
28
+ end
data/lib/tire/index.rb ADDED
@@ -0,0 +1,98 @@
1
+ # -*- encoding : utf-8 -*-
2
+ module Tire
3
+ class Index
4
+ include Utils
5
+
6
+ attr_reader :name, :response
7
+
8
+ def initialize(name)
9
+ @name = name
10
+ end
11
+
12
+ def url
13
+ "#{Configuration.url}/#{@name}"
14
+ end
15
+
16
+ def regist_shard(total = 6)
17
+ notes_count = Configuration.nodes_count
18
+ regist_json = MultiJson.encode(build_regist_options(total, notes_count))
19
+ @response = Configuration.client.put("#{url}/_shard", regist_json)
20
+ @response.success?
21
+
22
+ ensure
23
+ curl = %Q|curl -X PUT "#{url}/_shard" -d '#{regist_json}'|
24
+ logged('_regist_shard', curl)
25
+ end
26
+
27
+ def shard_info
28
+ @response = Configuration.client.get("#{url}/_shard")
29
+ if @response.failure?
30
+ STDERR.puts "[REQUEST FAILED] \n"
31
+ raise @response.to_s
32
+ end
33
+
34
+ MultiJson.decode(@response.body)
35
+ ensure
36
+ curl = %Q|curl -X GET #{url}/_shard|
37
+ logged('_regist_shard_info', curl)
38
+ end
39
+
40
+ def delete
41
+ @response = Configuration.client.delete url
42
+ @response.success?
43
+
44
+ ensure
45
+ curl = %Q|curl -X DELETE #{url}|
46
+ logged('DELETE', curl)
47
+ end
48
+
49
+ def mapping(type = "csdn")
50
+ @response = Configuration.client.get("#{url}/#{type}/_mapping")
51
+ MultiJson.decode(@response.body)
52
+ end
53
+
54
+ def create_mapping(type, options)
55
+ @options = options
56
+ @response = Configuration.client.put("#{url}/#{type}/_mapping", MultiJson.encode(options))
57
+ @response.success?
58
+
59
+ ensure
60
+ curl = %Q|curl -X PUT #{url}/#{type}/_mapping -d '#{MultiJson.encode(options)}'|
61
+ logged('CREATE MAPPING', curl)
62
+ end
63
+
64
+ def bulk(type, document)
65
+ @response = Configuration.client.put("#{url}/#{type}/_bulk", MultiJson.encode(document))
66
+ @response.success?
67
+
68
+ ensure
69
+ curl = %Q|curl -X PUT #{url}/#{type}/_pulk -d '#{MultiJson.encode(document)}'|
70
+ logged('BULK', curl)
71
+ end
72
+
73
+ def flush
74
+ @response = Configuration.client.put("#{url}/_flush", "")
75
+ @response.success?
76
+
77
+ ensure
78
+ curl = %Q|curl -X PUT #{url}/_flush|
79
+ logged('FLUSH', curl)
80
+ end
81
+
82
+ def refresh
83
+ @response = Configuration.client.put("#{url}/_refresh", "")
84
+ @response.success?
85
+
86
+ ensure
87
+ curl = %Q|curl -X PUT #{url}/_refresh|
88
+ logged('REFRESH', curl)
89
+ end
90
+
91
+ private
92
+
93
+ def build_regist_options(total, notes_count)
94
+ Hash[(0..total - 1).group_by{|x| x.modulo notes_count}.map{|key, value| ["cs#{key + 1}", value]}]
95
+ end
96
+
97
+ end
98
+ end
@@ -0,0 +1,61 @@
1
+ # -*- encoding : utf-8 -*-
2
+ module Tire
3
+ class Logger
4
+
5
+ def initialize(device, options={})
6
+ @device = if device.respond_to?(:write)
7
+ device
8
+ else
9
+ File.open(device, 'a')
10
+ end
11
+ @device.sync = true if @device.respond_to?(:sync)
12
+ @options = options
13
+ at_exit { @device.close unless @device.closed? } if @device.respond_to?(:closed?) && @device.respond_to?(:close)
14
+ end
15
+
16
+ def level
17
+ @options[:level] || 'info'
18
+ end
19
+
20
+ def write(message)
21
+ @device.write message
22
+ end
23
+
24
+ def log_request(endpoint, params=nil, curl='')
25
+ # 2001-02-12 18:20:42:32 [_search] (articles,users)
26
+ #
27
+ # curl -X POST ....
28
+ #
29
+ content = "# #{time}"
30
+ content += " [#{endpoint}]"
31
+ content += " (#{params.inspect})" if params
32
+ content += "\n#\n"
33
+ content += curl
34
+ content += "\n\n"
35
+ write content
36
+ end
37
+
38
+ def log_response(status, took=nil, json='')
39
+ # 2001-02-12 18:20:42:32 [200] (4 msec)
40
+ #
41
+ # {
42
+ # "took" : 4,
43
+ # "hits" : [...]
44
+ # ...
45
+ # }
46
+ #
47
+ content = "# #{time}"
48
+ content += " [#{status}]"
49
+ content += " (#{took} msec)" if took
50
+ content += "\n#\n" unless json.to_s !~ /\S/
51
+ json.to_s.each_line { |line| content += "# #{line}" } unless json.to_s !~ /\S/
52
+ content += "\n\n"
53
+ write content
54
+ end
55
+
56
+ def time
57
+ Time.now.strftime('%Y-%m-%d %H:%M:%S:%L')
58
+ end
59
+
60
+ end
61
+ end
@@ -0,0 +1,55 @@
1
+ # -*- encoding : utf-8 -*-
2
+ module Tire
3
+ module Results
4
+
5
+ # Adds support for WillPaginate and Kaminari
6
+ #
7
+ module Pagination
8
+
9
+ def total_entries
10
+ @total
11
+ end
12
+
13
+ def per_page
14
+ (@options[:per_page] || @options[:size] || 10 ).to_i
15
+ end
16
+
17
+ def total_pages
18
+ ( @total.to_f / per_page ).ceil
19
+ end
20
+
21
+ def current_page
22
+ if @options[:page]
23
+ @options[:page].to_i
24
+ else
25
+ (per_page + @options[:from].to_i) / per_page
26
+ end
27
+ end
28
+
29
+ def previous_page
30
+ current_page > 1 ? (current_page - 1) : nil
31
+ end
32
+
33
+ def next_page
34
+ current_page < total_pages ? (current_page + 1) : nil
35
+ end
36
+
37
+ def offset
38
+ per_page * (current_page - 1)
39
+ end
40
+
41
+ def out_of_bounds?
42
+ current_page > total_pages
43
+ end
44
+
45
+ # Kaminari support
46
+ #
47
+ alias :limit_value :per_page
48
+ alias :total_count :total_entries
49
+ alias :num_pages :total_pages
50
+ alias :offset_value :offset
51
+
52
+ end
53
+
54
+ end
55
+ end