xapian_db 0.5.9 → 0.5.10

Sign up to get free protection for your applications and to get access to all the features.
data/CHANGELOG.md CHANGED
@@ -1,3 +1,11 @@
1
+ ##0.5.10 (April 6th, 2011)
2
+
3
+ Features:
4
+
5
+ - the beanstalk worker is now implemented as a daemon script (execute 'rails generate xapian_db:install' to install it)
6
+ - execute a block with auto indexing disabled (see 'Bulk inserts / updates / deletes' in teh README)
7
+ - updated the xapian source to version 1.2.5
8
+
1
9
  ##0.5.9 (March 25th, 2011)
2
10
 
3
11
  Fixes:
data/README.rdoc CHANGED
@@ -244,6 +244,19 @@ only if the block does not raise an exception.
244
244
  object2.save
245
245
  end
246
246
 
247
+ === Bulk inserts / updates / deletes
248
+
249
+ When you change a lot of models, it is not very efficient to update the xapian index on each insert / update / delete. Instead,
250
+ you can use the auto_indexing_disabled method with a block and rebuild the whole index afterwards:
251
+
252
+ XapianDb.auto_indexing_disabled do
253
+ Person.each do |person|
254
+ # change person
255
+ person.save
256
+ end
257
+ end
258
+ Person.rebuild_xapian_index
259
+
247
260
  == Production setup
248
261
 
249
262
  Since Xapian allows only one database instance to write to the index, the default setup of XapianDb will not work
@@ -282,21 +295,26 @@ The easiest way is to use macports or homebrew:
282
295
  gem 'beanstalk-client' # Add this to your Gemfile
283
296
  bundle install
284
297
 
285
- === 3. Configure your production environment in config/xapian_db.yml
298
+ === 3. Install the beanstalk worker script
299
+
300
+ rails generate xapian:db install
301
+
302
+ === 4. Configure your production environment in config/xapian_db.yml
286
303
 
287
304
  production:
288
305
  database: db/xapian_db/production
289
306
  writer: beanstalk
290
307
  beanstalk_daemon: localhost:11300
291
308
 
292
- === 4. start the beanstalk daemon
309
+ === 5. start the beanstalk daemon
293
310
 
294
311
  beanstalkd -d
295
312
 
296
- === 5. start the beanstalk worker from within your Rails app root directory
297
-
298
- rake RAILS_ENV=production xapian_db:beanstalk_worker
313
+ === 6. start the beanstalk worker from within your Rails app root directory
299
314
 
300
- <b>Important: Do not start multiple instances of this worker task!</b>
315
+ RAILS_ENV=production script/beanstalk_worker start
301
316
 
317
+ If everything is fine, you should find a file namend beanstalk_worker.pid in tmp/pids. If something
318
+ goes wrong, you'll find beanstalk_worker.log instead showing the stack trace.
302
319
 
320
+ <b>Important: Do not start multiple instances of this daemon!</b>
data/Rakefile CHANGED
@@ -9,7 +9,7 @@ def system!(cmd)
9
9
  system(cmd) or raise
10
10
  end
11
11
 
12
- ver = '1.2.4'
12
+ ver = '1.2.5'
13
13
  source_dir = 'xapian_source'
14
14
  core = "xapian-core-#{ver}"
15
15
  bindings = "xapian-bindings-#{ver}"
@@ -0,0 +1,17 @@
1
+ require 'rails/generators'
2
+
3
+ module XapianDb
4
+ module Generators
5
+ class InstallGenerator < Rails::Generators::Base
6
+ source_root File.expand_path("../templates", __FILE__)
7
+
8
+ desc "Creates a beanstalk worker script."
9
+
10
+ def copy_script
11
+ copy_file "beanstalk_worker", "script/beanstalk_worker"
12
+ chmod "script/beanstalk_worker", 0755
13
+ end
14
+
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,71 @@
1
+ #!/usr/bin/env ruby
2
+ # encoding: utf-8
3
+
4
+ require "bundler/setup"
5
+ require 'rails'
6
+ require 'daemons'
7
+ require "xapian_db"
8
+ require 'yaml'
9
+ require 'rails/railtie' # execute xapian_db railtie
10
+
11
+ # daemon script to manage the beanstalk worker daemon
12
+ # @author Gernot Kogler
13
+ module XapianDb
14
+ class BeanstalkWorker
15
+
16
+ def process_requests
17
+
18
+ Rails.logger.info "XapianDb beanstalk worker: initializing..."
19
+
20
+ url = XapianDb::Config.beanstalk_daemon_url
21
+ beanstalk = Beanstalk::Pool.new([url])
22
+ worker = XapianDb::IndexWriters::BeanstalkWorker.new
23
+ Rails.logger.info "XapianDb beanstalk worker: ready"
24
+
25
+ loop do
26
+ begin
27
+ job = beanstalk.reserve
28
+ params = YAML::load job.body
29
+ Rails.logger.info "XapianDb beanstalk worker: executing task #{params}"
30
+ task = params.delete :task
31
+ worker.send task, params
32
+ rescue Exception => ex
33
+ Rails.logger.error "XapianDb beanstalk worker: could not process #{job.body} (#{ex})"
34
+ end
35
+
36
+ begin
37
+ job.delete
38
+ rescue Exception => ex
39
+ Rails.logger.error "XapianDb beanstalk worker: could delete job #{job.body} (#{ex})"
40
+ end
41
+
42
+ end
43
+ end
44
+ end
45
+ end
46
+
47
+ # =========================================================================================
48
+ # daemon setup
49
+ # =========================================================================================
50
+ dir = File.expand_path(File.join(File.dirname(__FILE__), '..'))
51
+ pids_dir = File.join(dir, 'tmp', 'pids')
52
+ FileUtils.makedirs pids_dir unless File.exists?(pids_dir)
53
+
54
+ daemon_options = {
55
+ :multiple => false,
56
+ :dir_mode => :normal,
57
+ :dir => pids_dir,
58
+ :backtrace => true
59
+ }
60
+
61
+ Daemons.run_proc('beanstalk_worker', daemon_options) do
62
+ if ARGV.include?('--')
63
+ ARGV.slice! 0..ARGV.index('--')
64
+ else
65
+ ARGV.clear
66
+ end
67
+
68
+ Dir.chdir dir
69
+ require File.expand_path(File.join(File.dirname(__FILE__), '..', 'config', 'environment'))
70
+ XapianDb::BeanstalkWorker.new.process_requests
71
+ end
@@ -0,0 +1,29 @@
1
+ # encoding: utf-8
2
+
3
+ # This writer is a dummy writer that simply does nothing.
4
+ # @author Gernot Kogler
5
+
6
+ module XapianDb
7
+ module IndexWriters
8
+
9
+ class NoOpWriter
10
+
11
+ # Update an object in the index
12
+ # @param [Object] obj An instance of a class with a blueprint configuration
13
+ def index(obj); end
14
+
15
+ # Remove an object from the index
16
+ # @param [Object] obj An instance of a class with a blueprint configuration
17
+ def unindex(obj); end
18
+
19
+ # Reindex all objects of a given class
20
+ # @param [Class] klass The class to reindex
21
+ # @param [Hash] options Options for reindexing
22
+ # @option options [Boolean] :verbose (false) Should the reindexing give status informations?
23
+ def reindex_class(klass, options={})
24
+ raise "rebuild_xapian_index is not supported inside a block with auto indexing disabled"
25
+ end
26
+
27
+ end
28
+ end
29
+ end
@@ -9,11 +9,16 @@ module XapianDb
9
9
  # @author Gernot Kogler
10
10
  class Railtie < ::Rails::Railtie
11
11
 
12
- # Require our rake tasks
12
+ # require our rake tasks
13
13
  rake_tasks do
14
14
  load "#{File.dirname(__FILE__)}/../../tasks/beanstalk_worker.rake"
15
15
  end
16
16
 
17
+ # require our generators
18
+ generators do
19
+ require "#{File.dirname(__FILE__)}/../generators/install_generator.rb"
20
+ end
21
+
17
22
  config.before_configuration do
18
23
 
19
24
  # Read the database configuration file if there is one
@@ -49,24 +54,24 @@ module XapianDb
49
54
  load blueprints_file_path if File.exist?(blueprints_file_path)
50
55
  end
51
56
 
52
- private
57
+ private
53
58
 
54
- # use the config options from the config file
55
- def self.configure_from(env_config)
56
- @database_path = env_config["database"] || ":memory:"
57
- @adapter = env_config["adapter"] || :active_record
58
- @writer = env_config["writer"] || :direct
59
- @beanstalk_daemon = env_config["beanstalk_daemon"]
60
- @language = env_config["language"]
61
- end
59
+ # use the config options from the config file
60
+ def self.configure_from(env_config)
61
+ @database_path = env_config["database"] || ":memory:"
62
+ @adapter = env_config["adapter"] || :active_record
63
+ @writer = env_config["writer"] || :direct
64
+ @beanstalk_daemon = env_config["beanstalk_daemon"]
65
+ @language = env_config["language"]
66
+ end
62
67
 
63
- # set default config options
64
- def self.configure_defaults
65
- Rails.env == "test" ? @database_path = ":memory:" : @database_path = "db/xapian_db/#{Rails.env}"
66
- @adapter = :active_record
67
- @writer = :direct
68
- @beanstalk_daemon = nil
69
- end
68
+ # set default config options
69
+ def self.configure_defaults
70
+ Rails.env == "test" ? @database_path = ":memory:" : @database_path = "db/xapian_db/#{Rails.env}"
71
+ @adapter = :active_record
72
+ @writer = :direct
73
+ @beanstalk_daemon = nil
74
+ end
70
75
 
71
76
  end
72
77
  end
data/lib/xapian_db.rb CHANGED
@@ -88,14 +88,14 @@ module XapianDb
88
88
  # Update an object in the index
89
89
  # @param [Object] obj An instance of a class with a blueprint configuration
90
90
  def self.index(obj)
91
- writer = @transactional_writer || XapianDb::Config.writer
91
+ writer = @block_writer || XapianDb::Config.writer
92
92
  writer.index obj
93
93
  end
94
94
 
95
95
  # Remove an object from the index
96
96
  # @param [Object] obj An instance of a class with a blueprint configuration
97
97
  def self.unindex(obj)
98
- writer = @transactional_writer || XapianDb::Config.writer
98
+ writer = @block_writer || XapianDb::Config.writer
99
99
  writer.unindex obj
100
100
  end
101
101
 
@@ -122,27 +122,47 @@ module XapianDb
122
122
 
123
123
  # Execute a block as a transaction
124
124
  def self.transaction(&block)
125
- # Temporarily use the transactional writer
126
- @transactional_writer = XapianDb::IndexWriters::TransactionalWriter.new
125
+ writer = XapianDb::IndexWriters::TransactionalWriter.new
126
+ execute_block :writer => writer, :error_message => "error in XapianDb transaction block, transaction aborted" do
127
+ block.call
128
+ writer.commit_using XapianDb::Config.writer
129
+ end
130
+ end
131
+
132
+ # Execute a block and do not update the index
133
+ def self.auto_indexing_disabled(&block)
134
+ execute_block :writer => XapianDb::IndexWriters::NoOpWriter.new do
135
+ block.call
136
+ end
137
+
138
+ end
139
+
140
+ # execute a block of code with a given writer and handle errors
141
+ # @param [Hash] opts Options
142
+ # @option opts [Object] :writer An index writer
143
+ # @option opts [String] :error_message the error message to log if an error occurs
144
+ def self.execute_block(opts, &block)
145
+ @block_writer = opts[:writer]
127
146
  begin
128
147
  block.call
129
- @transactional_writer.commit_using XapianDb::Config.writer
130
148
  rescue Exception => ex
131
- msg = "error in XapianDb transaction block: #{ex}, transaction aborted"
132
- if defined?(Rails)
133
- Rails.logger.error msg
134
- else
135
- puts msg
149
+ if opts[:error_message]
150
+ if defined?(Rails)
151
+ Rails.logger.error opts[:error_message]
152
+ else
153
+ puts opts[:error_message]
154
+ end
136
155
  end
156
+ raise
137
157
  ensure
138
- # release the transactional writer
139
- @transactional_writer = nil
158
+ # release the block writer
159
+ @block_writer = nil
140
160
  end
141
161
  end
142
162
 
143
163
  end
144
164
 
145
- do_not_require = %w(update_stopwords.rb railtie.rb base_adapter.rb beanstalk_writer.rb utilities.rb)
165
+ do_not_require = %w(update_stopwords.rb railtie.rb base_adapter.rb beanstalk_writer.rb utilities.rb install_generator.rb)
146
166
  files = Dir.glob("#{File.dirname(__FILE__)}/**/*.rb").reject{|path| do_not_require.include?(File.basename(path))}
147
167
  # Require these first
148
168
  require "#{File.dirname(__FILE__)}/xapian_db/utilities"
@@ -11,16 +11,18 @@ require 'yaml'
11
11
 
12
12
  namespace :xapian_db do
13
13
 
14
- desc "Run the beanstalk worker process to update the xapian index"
14
+ DEPRECATION_WARNING = "beanstalk_worker.rake is deprecated, use script/beanstalk_worker instead"
15
+ desc DEPRECATION_WARNING
15
16
  task :beanstalk_worker do
16
17
 
17
18
  url = XapianDb::Config.beanstalk_daemon_url
18
19
  beanstalk = Beanstalk::Pool.new([url])
19
20
  worker = XapianDb::IndexWriters::BeanstalkWorker.new
21
+ puts DEPRECATION_WARNING
20
22
  puts "XapianDb beanstalk worker is serving on #{url}..."
21
23
  loop do
22
- job = beanstalk.reserve
23
24
  begin
25
+ job = beanstalk.reserve
24
26
  params = YAML::load job.body
25
27
  Rails.logger.info "XapianDb beanstalk worker: executing task #{params}"
26
28
  task = params.delete :task
@@ -28,7 +30,13 @@ namespace :xapian_db do
28
30
  rescue Exception => ex
29
31
  Rails.logger.error "XapianDb beanstalk worker: could not process #{job.body} (#{ex})"
30
32
  end
31
- job.delete
33
+
34
+ begin
35
+ job.delete
36
+ rescue Exception => ex
37
+ Rails.logger.error "XapianDb beanstalk worker: could delete job #{job.body} (#{ex})"
38
+ end
39
+
32
40
  end
33
41
 
34
42
  end
metadata CHANGED
@@ -5,8 +5,8 @@ version: !ruby/object:Gem::Version
5
5
  segments:
6
6
  - 0
7
7
  - 5
8
- - 9
9
- version: 0.5.9
8
+ - 10
9
+ version: 0.5.10
10
10
  platform: ruby
11
11
  authors:
12
12
  - Gernot Kogler
@@ -14,13 +14,28 @@ autorequire:
14
14
  bindir: bin
15
15
  cert_chain: []
16
16
 
17
- date: 2011-03-25 00:00:00 +01:00
17
+ date: 2011-04-06 00:00:00 +02:00
18
18
  default_executable:
19
19
  dependencies:
20
20
  - !ruby/object:Gem::Dependency
21
- name: rspec
21
+ name: daemons
22
22
  prerelease: false
23
23
  requirement: &id001 !ruby/object:Gem::Requirement
24
+ none: false
25
+ requirements:
26
+ - - ">="
27
+ - !ruby/object:Gem::Version
28
+ segments:
29
+ - 1
30
+ - 0
31
+ - 10
32
+ version: 1.0.10
33
+ type: :runtime
34
+ version_requirements: *id001
35
+ - !ruby/object:Gem::Dependency
36
+ name: rspec
37
+ prerelease: false
38
+ requirement: &id002 !ruby/object:Gem::Requirement
24
39
  none: false
25
40
  requirements:
26
41
  - - ">="
@@ -31,11 +46,11 @@ dependencies:
31
46
  - 1
32
47
  version: 2.3.1
33
48
  type: :development
34
- version_requirements: *id001
49
+ version_requirements: *id002
35
50
  - !ruby/object:Gem::Dependency
36
51
  name: simplecov
37
52
  prerelease: false
38
- requirement: &id002 !ruby/object:Gem::Requirement
53
+ requirement: &id003 !ruby/object:Gem::Requirement
39
54
  none: false
40
55
  requirements:
41
56
  - - ">="
@@ -46,11 +61,11 @@ dependencies:
46
61
  - 7
47
62
  version: 0.3.7
48
63
  type: :development
49
- version_requirements: *id002
64
+ version_requirements: *id003
50
65
  - !ruby/object:Gem::Dependency
51
66
  name: beanstalk-client
52
67
  prerelease: false
53
- requirement: &id003 !ruby/object:Gem::Requirement
68
+ requirement: &id004 !ruby/object:Gem::Requirement
54
69
  none: false
55
70
  requirements:
56
71
  - - ">="
@@ -61,7 +76,7 @@ dependencies:
61
76
  - 0
62
77
  version: 1.1.0
63
78
  type: :development
64
- version_requirements: *id003
79
+ version_requirements: *id004
65
80
  description: XapianDb is a ruby gem that combines features of nosql databases and fulltext indexing. It is based on Xapian, an efficient and powerful indexing library
66
81
  email: gernot.kogler (at) garaio (dot) com
67
82
  executables: []
@@ -71,6 +86,8 @@ extensions:
71
86
  extra_rdoc_files: []
72
87
 
73
88
  files:
89
+ - lib/generators/install_generator.rb
90
+ - lib/generators/templates/beanstalk_worker
74
91
  - lib/xapian_db/adapters/active_record_adapter.rb
75
92
  - lib/xapian_db/adapters/base_adapter.rb
76
93
  - lib/xapian_db/adapters/datamapper_adapter.rb
@@ -81,6 +98,7 @@ files:
81
98
  - lib/xapian_db/index_writers/beanstalk_worker.rb
82
99
  - lib/xapian_db/index_writers/beanstalk_writer.rb
83
100
  - lib/xapian_db/index_writers/direct_writer.rb
101
+ - lib/xapian_db/index_writers/no_op_writer.rb
84
102
  - lib/xapian_db/index_writers/transactional_writer.rb
85
103
  - lib/xapian_db/indexer.rb
86
104
  - lib/xapian_db/query_parser.rb
@@ -106,8 +124,8 @@ files:
106
124
  - lib/xapian_db/utilities.rb
107
125
  - lib/xapian_db.rb
108
126
  - tasks/beanstalk_worker.rake
109
- - xapian_source/xapian-bindings-1.2.4.tar.gz
110
- - xapian_source/xapian-core-1.2.4.tar.gz
127
+ - xapian_source/xapian-bindings-1.2.5.tar.gz
128
+ - xapian_source/xapian-core-1.2.5.tar.gz
111
129
  - LICENSE
112
130
  - README.rdoc
113
131
  - CHANGELOG.md
Binary file