csdn-tire 0.5

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.
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