promiscuous 0.17.0 → 0.18.0

Sign up to get free protection for your applications and to get access to all the features.
data/bin/promiscuous ADDED
@@ -0,0 +1,10 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'promiscuous/cli'
4
+ begin
5
+ Promiscuous::CLI.new.run
6
+ rescue => e
7
+ $stderr.puts e.backtrace.join("\n")
8
+ $stderr.puts '-' * 80
9
+ $stderr.puts e.message
10
+ end
@@ -0,0 +1,159 @@
1
+ require 'promiscuous'
2
+
3
+ class Promiscuous::CLI
4
+ def replicate(config_options={}, &block)
5
+ require 'eventmachine'
6
+ require 'em-synchrony'
7
+
8
+ EM.synchrony do
9
+ trap_signals
10
+ Promiscuous::Loader.load_descriptors if defined?(Rails)
11
+ force_backend :rubyamqp
12
+ block.call
13
+ end
14
+ end
15
+
16
+ def force_backend(backend)
17
+ Promiscuous::AMQP.disconnect
18
+ Promiscuous::Config.backend = backend
19
+ Promiscuous::AMQP.connect
20
+ end
21
+
22
+ def trap_signals
23
+ %w(SIGTERM SIGINT).each do |signal|
24
+ Signal.trap(signal) do
25
+ print_status "Exiting..."
26
+ Promiscuous::Worker.stop
27
+ EM.stop
28
+ end
29
+ end
30
+ end
31
+
32
+ def publish(options={})
33
+ replicate do
34
+ Promiscuous::Worker.replicate(options)
35
+ print_status "Replicating with #{Promiscuous::Publisher::Mongoid::Defer.klasses.count} publishers"
36
+ end
37
+ end
38
+
39
+ def subscribe(options={})
40
+ replicate do
41
+ Promiscuous::Worker.replicate(options)
42
+ print_status "Replicating with #{Promiscuous::Subscriber::AMQP.subscribers.count} subscribers"
43
+ end
44
+ end
45
+
46
+ def publish_sync(options={})
47
+ print_status "Replicating #{options[:criteria]}..."
48
+ criteria = eval(options[:criteria])
49
+
50
+ bar = ProgressBar.create(:format => '%t |%b>%i| %c/%C %e', :title => 'Publishing', :total => criteria.count)
51
+ criteria.each do |doc|
52
+ doc.promiscuous_sync(options)
53
+ bar.increment
54
+ end
55
+
56
+ print_status "Done. You may switch your subscriber worker back to regular mode, and delete the sync queues"
57
+ end
58
+
59
+ def subscribe_sync(options={})
60
+ replicate do
61
+ # Create the regular queue if needed, so we don't lose messages.
62
+ Promiscuous::AMQP.open_queue(Promiscuous::Subscriber::Worker.new.queue_bindings)
63
+
64
+ print_status "WARNING: --- SYNC MODE ----"
65
+ print_status "WARNING: Make sure you are not running the regular subscriber worker (it's racy)"
66
+ print_status "WARNING: --- SYNC MODE ----"
67
+ Promiscuous::Worker.replicate(options)
68
+ print_status "Replicating with #{Promiscuous::Subscriber::AMQP.subscribers.count} subscribers"
69
+ end
70
+ end
71
+
72
+ def parse_args(args)
73
+ options = {}
74
+
75
+ parser = OptionParser.new do |opts|
76
+ opts.banner = "Usage: promiscuous [options] action"
77
+
78
+ opts.separator ""
79
+ opts.separator "Actions:"
80
+ opts.separator " publish"
81
+ opts.separator " subscribe"
82
+ opts.separator ""
83
+ opts.separator "Options:"
84
+
85
+ opts.on "-s", "--sync", "Use a separate queue for sychronizing databases" do
86
+ options[:personality] = :sync
87
+ end
88
+
89
+ opts.on "-c", "--criteria CRITERIA", "Published criteria in sync mode (often a model)" do |criteria|
90
+ options[:criteria] = criteria
91
+ end
92
+
93
+ opts.on "-b", "--bareback", "Bareback mode aka continue on error. Use with extreme caution" do
94
+ options[:bareback] = true
95
+ end
96
+
97
+ opts.on "-r", "--require FILE", "File to require to load your app. Don't worry about it with rails" do |file|
98
+ options[:require] = file
99
+ end
100
+
101
+ opts.on("-h", "--help", "Show this message") do
102
+ puts opts
103
+ exit
104
+ end
105
+
106
+ opts.on("-V", "--version", "Show version") do
107
+ puts "Promiscuous #{Promiscuous::VERSION}"
108
+ puts "License MIT"
109
+ exit
110
+ end
111
+ end
112
+
113
+ args = args.dup
114
+ parser.parse!(args)
115
+
116
+ options[:action] = args.shift.try(:to_sym)
117
+ raise "Please specify an action (publish or subscribe)" unless options[:action].in? [:publish, :subscribe]
118
+
119
+ if options[:action] == :publish && options[:personality] == :sync
120
+ raise "Please specify a criteria" unless options[:criteria]
121
+ else
122
+ raise "Why are you specifying a criteria?" if options[:criteria]
123
+ end
124
+
125
+ options
126
+ end
127
+
128
+ def load_app(options={})
129
+ if options[:require]
130
+ require options[:require]
131
+ else
132
+ require 'rails'
133
+ require File.expand_path("./config/environment.rb")
134
+ ::Rails.application.eager_load!
135
+ end
136
+ end
137
+
138
+ def run
139
+ options = parse_args(ARGV)
140
+ load_app(options)
141
+ maybe_warn_bareback(options)
142
+
143
+ # calls publish, publish_sync, subscribe, subscribe_sync
144
+ __send__([options[:action], options[:personality]].compact.join('_'), options)
145
+ end
146
+
147
+ def maybe_warn_bareback(options)
148
+ if options[:bareback]
149
+ print_status "WARNING: --- BAREBACK MODE ----"
150
+ print_status "WARNING: You are replicating without protection, you can get corrupted in no time"
151
+ print_status "WARNING: --- BAREBACK MODE ----"
152
+ end
153
+ end
154
+
155
+ def print_status(msg)
156
+ Promiscuous.info msg
157
+ $stderr.puts msg
158
+ end
159
+ end
@@ -15,7 +15,7 @@ module Promiscuous::Common::Worker
15
15
  end
16
16
 
17
17
  def bareback?
18
- !!ENV['BAREBACK']
18
+ !!options[:bareback]
19
19
  end
20
20
 
21
21
  included { attr_accessor :stop, :options }
@@ -1,7 +1,5 @@
1
1
  module Promiscuous
2
2
  class Railtie < Rails::Railtie
3
- rake_tasks { load 'promiscuous/railtie/replicate.rake' }
4
-
5
3
  initializer 'load promiscuous' do
6
4
  config.after_initialize do
7
5
  Promiscuous::Loader.load_descriptors(:publishers)
@@ -6,7 +6,7 @@ module Promiscuous::Subscriber::Mongoid::Versioning
6
6
 
7
7
  def atomic_selector
8
8
  if use_atomic_promiscuous_selector
9
- super.merge({ '$or' => [{'_psv' => { '$lt' => self._psv }},
9
+ super.merge({ '$or' => [{'_psv' => { '$lte' => self._psv }},
10
10
  {'_psv' => { '$exists' => false }}]})
11
11
  else
12
12
  super
@@ -1,3 +1,3 @@
1
1
  module Promiscuous
2
- VERSION = '0.17.0'
2
+ VERSION = '0.18.0'
3
3
  end
@@ -3,11 +3,11 @@ module Promiscuous::Worker
3
3
  self.workers = []
4
4
 
5
5
  def self.replicate(options={})
6
- publish = options[:only].nil? || options[:only] == :publish
7
- subscribe = options[:only].nil? || options[:only] == :subscribe
6
+ options[:action] ||= [:publish, :subscribe]
7
+ actions = [options[:action]].flatten
8
8
 
9
- self.workers << Promiscuous::Publisher::Worker.new(options) if publish
10
- self.workers << Promiscuous::Subscriber::Worker.new(options) if subscribe
9
+ self.workers << Promiscuous::Publisher::Worker.new(options) if :publish.in? actions
10
+ self.workers << Promiscuous::Subscriber::Worker.new(options) if :subscribe.in? actions
11
11
  self.workers.each { |w| w.replicate }
12
12
  end
13
13
 
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: promiscuous
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.17.0
4
+ version: 0.18.0
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -10,7 +10,7 @@ authors:
10
10
  autorequire:
11
11
  bindir: bin
12
12
  cert_chain: []
13
- date: 2012-12-12 00:00:00.000000000 Z
13
+ date: 2012-12-19 00:00:00.000000000 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: activesupport
@@ -112,13 +112,14 @@ description: Replicate your Mongoid/ActiveRecord models across your applications
112
112
  email:
113
113
  - nicolas@viennot.biz
114
114
  - kareem@doubleonemedia.com
115
- executables: []
115
+ executables:
116
+ - promiscuous
116
117
  extensions: []
117
118
  extra_rdoc_files: []
118
119
  files:
119
120
  - lib/promiscuous/amqp/null.rb
120
- - lib/promiscuous/amqp/bunny.rb
121
121
  - lib/promiscuous/amqp/rubyamqp.rb
122
+ - lib/promiscuous/amqp/bunny.rb
122
123
  - lib/promiscuous/common/lint.rb
123
124
  - lib/promiscuous/common/lint/base.rb
124
125
  - lib/promiscuous/common/class_helpers.rb
@@ -148,8 +149,6 @@ files:
148
149
  - lib/promiscuous/publisher/ephemeral.rb
149
150
  - lib/promiscuous/publisher/mongoid.rb
150
151
  - lib/promiscuous/publisher/worker.rb
151
- - lib/promiscuous/railtie.rb
152
- - lib/promiscuous/railtie/replicate.rake
153
152
  - lib/promiscuous/subscriber/active_record.rb
154
153
  - lib/promiscuous/subscriber/envelope.rb
155
154
  - lib/promiscuous/subscriber/error.rb
@@ -176,12 +175,15 @@ files:
176
175
  - lib/promiscuous/common.rb
177
176
  - lib/promiscuous/config.rb
178
177
  - lib/promiscuous/amqp.rb
179
- - lib/promiscuous/worker.rb
180
178
  - lib/promiscuous/ephemeral.rb
181
179
  - lib/promiscuous/subscriber.rb
182
180
  - lib/promiscuous/publisher.rb
181
+ - lib/promiscuous/cli.rb
182
+ - lib/promiscuous/railtie.rb
183
+ - lib/promiscuous/worker.rb
183
184
  - lib/promiscuous/version.rb
184
185
  - lib/promiscuous.rb
186
+ - bin/promiscuous
185
187
  - README.md
186
188
  homepage: http://github.com/crowdtap/promiscuous
187
189
  licenses: []
@@ -1,87 +0,0 @@
1
- namespace :promiscuous do
2
- # Note These rake tasks can be loaded without Rails
3
-
4
- def trap_signals
5
- %w(SIGTERM SIGINT).each do |signal|
6
- Signal.trap(signal) do
7
- Promiscuous.info "Exiting..."
8
- Promiscuous::Worker.stop
9
- EM.stop
10
- end
11
- end
12
- end
13
-
14
- def print_status(msg)
15
- Promiscuous.info msg
16
- $stderr.puts msg
17
- end
18
-
19
- def force_backend(backend)
20
- Promiscuous::AMQP.disconnect
21
- Promiscuous::Config.backend = backend
22
- Promiscuous::AMQP.connect
23
- end
24
-
25
- def replicate(config_options={}, &block)
26
- require 'eventmachine'
27
- require 'em-synchrony'
28
-
29
- EM.synchrony do
30
- trap_signals
31
- Promiscuous::Loader.load_descriptors if defined?(Rails)
32
- force_backend :rubyamqp
33
- block.call
34
- end
35
- end
36
-
37
- desc 'Run the publisher worker'
38
- task :publish => :environment do
39
- replicate do
40
- Promiscuous::Worker.replicate :only => :publish
41
- print_status "Replicating with #{Promiscuous::Publisher::Mongoid::Defer.klasses.count} publishers"
42
- end
43
- end
44
-
45
- desc 'Run the subscriber worker'
46
- task :subscribe => :environment do
47
- replicate do
48
- Promiscuous::Worker.replicate :only => :subscribe
49
- print_status "Replicating with #{Promiscuous::Subscriber::AMQP.subscribers.count} subscribers"
50
- end
51
- end
52
-
53
- namespace :synchronized do
54
- desc 'Synchronize a collection'
55
- task :publish, [:criteria] => :environment do |t, args|
56
- raise "Usage: rake promiscuous:synchronized:publish[Model]" unless args.criteria
57
-
58
- criteria = eval(args.criteria)
59
- count = criteria.count
60
- print_status "Replicating #{args.criteria}..."
61
-
62
- bar = ProgressBar.create(:format => '%t |%b>%i| %c/%C %e',
63
- :title => 'Publishing',
64
- :total => count)
65
- criteria.each do |doc|
66
- doc.promiscuous_sync :personality => :sync
67
- bar.increment
68
- end
69
-
70
- print_status "Done. You may switch your subscriber worker back to regular mode, and delete the sync queues"
71
- end
72
-
73
- desc 'Subscribe to a collection synchronization'
74
- task :subscribe => :environment do |t|
75
- replicate do
76
- # Create the regular queue if needed, so we don't lose messages.
77
- Promiscuous::AMQP.open_queue(Promiscuous::Subscriber::Worker.new.queue_bindings)
78
-
79
- print_status "WARNING: --- SYNC MODE ----"
80
- print_status "WARNING: Make sure you are not running the regular subscriber worker (it's racy)"
81
- print_status "WARNING: --- SYNC MODE ----"
82
- Promiscuous::Worker.replicate :personality => :sync, :only => :subscribe
83
- print_status "Replicating with #{Promiscuous::Subscriber::AMQP.subscribers.count} subscribers"
84
- end
85
- end
86
- end
87
- end