promiscuous 0.91.0 → 0.92.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/promiscuous.rb +1 -1
- data/lib/promiscuous/amqp.rb +1 -1
- data/lib/promiscuous/amqp/fake.rb +0 -3
- data/lib/promiscuous/amqp/file.rb +81 -0
- data/lib/promiscuous/amqp/null.rb +0 -3
- data/lib/promiscuous/cli.rb +35 -25
- data/lib/promiscuous/config.rb +8 -3
- data/lib/promiscuous/error.rb +1 -2
- data/lib/promiscuous/key.rb +1 -12
- data/lib/promiscuous/mongoid.rb +7 -0
- data/lib/promiscuous/publisher/context/base.rb +4 -4
- data/lib/promiscuous/publisher/context/middleware.rb +2 -23
- data/lib/promiscuous/publisher/model/ephemeral.rb +5 -1
- data/lib/promiscuous/publisher/model/mock.rb +9 -7
- data/lib/promiscuous/publisher/model/mongoid.rb +3 -1
- data/lib/promiscuous/publisher/operation.rb +1 -1
- data/lib/promiscuous/publisher/operation/atomic.rb +44 -32
- data/lib/promiscuous/publisher/operation/base.rb +14 -9
- data/lib/promiscuous/publisher/operation/ephemeral.rb +14 -0
- data/lib/promiscuous/publisher/operation/mongoid.rb +4 -12
- data/lib/promiscuous/subscriber/message_processor/base.rb +17 -1
- data/lib/promiscuous/subscriber/message_processor/regular.rb +94 -48
- data/lib/promiscuous/subscriber/model/active_record.rb +25 -0
- data/lib/promiscuous/subscriber/model/base.rb +17 -13
- data/lib/promiscuous/subscriber/model/mongoid.rb +20 -1
- data/lib/promiscuous/subscriber/model/observer.rb +4 -0
- data/lib/promiscuous/subscriber/operation/base.rb +14 -16
- data/lib/promiscuous/subscriber/operation/bootstrap.rb +7 -1
- data/lib/promiscuous/subscriber/operation/regular.rb +6 -0
- data/lib/promiscuous/subscriber/worker.rb +6 -2
- data/lib/promiscuous/subscriber/worker/eventual_destroyer.rb +85 -0
- data/lib/promiscuous/subscriber/worker/message.rb +9 -15
- data/lib/promiscuous/subscriber/worker/message_synchronizer.rb +24 -78
- data/lib/promiscuous/subscriber/worker/runner.rb +6 -2
- data/lib/promiscuous/subscriber/worker/stats.rb +11 -7
- data/lib/promiscuous/version.rb +1 -1
- metadata +66 -63
- data/lib/promiscuous/error/already_processed.rb +0 -5
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: d772f9b9786ef7ee6787030113bf9ec5934717d5
|
4
|
+
data.tar.gz: 163c9cb61d4b359f1e6766effef9baccdfd8c229
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 6cacc43f226549868f963abbad29e7ba7249a1bbc1c4eb3e0b8014275935ca37e7455a73b48e36d7c0c56906308ab334c104bbf136a7cd2c7345ee976161eead
|
7
|
+
data.tar.gz: 6f59e694ed2c89e2ebe9a6c73995c4b6e4987ee1f43d171f55f3783b9698c4974aff8ef684d22dd8e652956d943081b952f8bb313d492016629b9564a1447727
|
data/lib/promiscuous.rb
CHANGED
@@ -13,7 +13,7 @@ module Promiscuous
|
|
13
13
|
require_for 'rails', 'promiscuous/railtie'
|
14
14
|
require_for 'resque', 'promiscuous/resque'
|
15
15
|
require_for 'sidekiq', 'promiscuous/sidekiq'
|
16
|
-
|
16
|
+
require_for 'mongoid', 'promiscuous/mongoid'
|
17
17
|
|
18
18
|
extend Promiscuous::Autoload
|
19
19
|
autoload :Common, :Publisher, :Subscriber, :Observer, :Worker, :Ephemeral,
|
data/lib/promiscuous/amqp.rb
CHANGED
@@ -0,0 +1,81 @@
|
|
1
|
+
class Promiscuous::AMQP::File
|
2
|
+
def connect
|
3
|
+
end
|
4
|
+
|
5
|
+
def disconnect
|
6
|
+
end
|
7
|
+
|
8
|
+
def connected?
|
9
|
+
true
|
10
|
+
end
|
11
|
+
|
12
|
+
def new_connection(options={})
|
13
|
+
end
|
14
|
+
|
15
|
+
def publish(options={})
|
16
|
+
options[:on_confirm].try(:call)
|
17
|
+
raise NotImplemented
|
18
|
+
end
|
19
|
+
|
20
|
+
module Subscriber
|
21
|
+
attr_accessor :lock, :prefetch_wait, :num_pending
|
22
|
+
|
23
|
+
def subscribe(options={}, &block)
|
24
|
+
file_name, worker_index, num_workers = Promiscuous::Config.subscriber_amqp_url.split(':')
|
25
|
+
|
26
|
+
worker_index = worker_index.to_i
|
27
|
+
num_workers = num_workers.to_i
|
28
|
+
|
29
|
+
file = File.open(file_name, 'r')
|
30
|
+
|
31
|
+
@prefetch = Promiscuous::Config.prefetch
|
32
|
+
@num_pending = 0
|
33
|
+
@lock = Mutex.new
|
34
|
+
@prefetch_wait = ConditionVariable.new
|
35
|
+
|
36
|
+
@thread = Thread.new do
|
37
|
+
file.each_with_index do |line, i|
|
38
|
+
if num_workers > 0
|
39
|
+
next if ((i+worker_index) % num_workers) != 0
|
40
|
+
end
|
41
|
+
|
42
|
+
return if @stop
|
43
|
+
|
44
|
+
@lock.synchronize do
|
45
|
+
@prefetch_wait.wait(@lock) until @num_pending < @prefetch
|
46
|
+
@num_pending += 1
|
47
|
+
end
|
48
|
+
|
49
|
+
block.call(Metadata.new(self), line.chomp)
|
50
|
+
end
|
51
|
+
|
52
|
+
@lock.synchronize do
|
53
|
+
@prefetch_wait.wait(@lock) until @num_pending == 0
|
54
|
+
end
|
55
|
+
|
56
|
+
# will shutdown the CLI gracefully
|
57
|
+
Process.kill("SIGTERM", Process.pid)
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
def recover
|
62
|
+
end
|
63
|
+
|
64
|
+
def disconnect
|
65
|
+
@stop = true
|
66
|
+
end
|
67
|
+
|
68
|
+
class Metadata
|
69
|
+
def initialize(sub)
|
70
|
+
@sub = sub
|
71
|
+
end
|
72
|
+
|
73
|
+
def ack
|
74
|
+
@sub.lock.synchronize do
|
75
|
+
@sub.num_pending -= 1
|
76
|
+
@sub.prefetch_wait.signal
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
data/lib/promiscuous/cli.rb
CHANGED
@@ -3,22 +3,28 @@ class Promiscuous::CLI
|
|
3
3
|
|
4
4
|
def trap_debug_signals
|
5
5
|
Signal.trap 'SIGUSR2' do
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
print_status
|
6
|
+
# Using a thread because we cannot acquire mutexes in a trap context in
|
7
|
+
# ruby 2.0
|
8
|
+
Thread.new do
|
9
|
+
Thread.list.each do |thread|
|
10
|
+
next if Thread.current == thread
|
11
|
+
|
12
|
+
print_status '----[ Threads ]----' + '-' * (100-19)
|
13
|
+
if thread.backtrace
|
14
|
+
print_status "Thread #{thread} #{thread['label']}"
|
15
|
+
print_status thread.backtrace.join("\n")
|
16
|
+
else
|
17
|
+
print_status "Thread #{thread} #{thread['label']} -- no backtrace"
|
18
|
+
end
|
13
19
|
end
|
14
|
-
end
|
15
20
|
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
21
|
+
if @worker && @worker.respond_to?(:message_synchronizer)
|
22
|
+
if blocked_messages = @worker.message_synchronizer.try(:blocked_messages)
|
23
|
+
print_status '----[ Pending Dependencies ]----' + '-' * (100-32)
|
24
|
+
blocked_messages.reverse_each { |msg| print_status msg }
|
25
|
+
end
|
26
|
+
print_status '-' * 100
|
20
27
|
end
|
21
|
-
print_status '-' * 100
|
22
28
|
end
|
23
29
|
end
|
24
30
|
end
|
@@ -26,14 +32,18 @@ class Promiscuous::CLI
|
|
26
32
|
def trap_exit_signals
|
27
33
|
%w(SIGTERM SIGINT).each do |signal|
|
28
34
|
Signal.trap(signal) do
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
@stop
|
34
|
-
|
35
|
-
|
36
|
-
|
35
|
+
# Using a thread because we cannot acquire mutexes in a trap context in
|
36
|
+
# ruby 2.0
|
37
|
+
Thread.new do
|
38
|
+
print_status "Exiting..."
|
39
|
+
if @stop
|
40
|
+
@worker.try(:show_stop_status)
|
41
|
+
else
|
42
|
+
@stop = true
|
43
|
+
@worker.try(:stop)
|
44
|
+
@worker = nil
|
45
|
+
end
|
46
|
+
end.join
|
37
47
|
end
|
38
48
|
end
|
39
49
|
end
|
@@ -144,12 +154,12 @@ class Promiscuous::CLI
|
|
144
154
|
Promiscuous::Config.no_deps = true
|
145
155
|
end
|
146
156
|
|
147
|
-
opts.on "-
|
148
|
-
|
157
|
+
opts.on "-x", "--ignore-exceptions", "Ignore exceptions and continue to process messages" do
|
158
|
+
Promiscuous::Config.ignore_exceptions = true
|
149
159
|
end
|
150
160
|
|
151
|
-
opts.on "-
|
152
|
-
|
161
|
+
opts.on "-l", "--require FILE", "File to require to load your app. Don't worry about it with rails" do |file|
|
162
|
+
options[:require] = file
|
153
163
|
end
|
154
164
|
|
155
165
|
opts.on "-p", "--prefetch [NUM]", "Number of messages to prefetch" do |prefetch|
|
data/lib/promiscuous/config.rb
CHANGED
@@ -3,9 +3,10 @@ module Promiscuous::Config
|
|
3
3
|
:publisher_amqp_url, :subscriber_amqp_url, :publisher_exchange,
|
4
4
|
:subscriber_exchanges, :queue_name, :queue_options, :redis_url,
|
5
5
|
:redis_urls, :redis_stats_url, :stats_interval,
|
6
|
-
:socket_timeout, :heartbeat, :no_deps, :hash_size,
|
6
|
+
:socket_timeout, :heartbeat, :no_deps, :hash_size,
|
7
7
|
:prefetch, :recovery_timeout, :logger, :subscriber_threads,
|
8
|
-
:version_field, :error_notifier, :recovery_on_boot
|
8
|
+
:version_field, :error_notifier, :recovery_on_boot,
|
9
|
+
:on_stats, :ignore_exceptions, :consistency, :max_retries, :generation
|
9
10
|
|
10
11
|
def self.backend=(value)
|
11
12
|
@@backend = value
|
@@ -53,7 +54,6 @@ module Promiscuous::Config
|
|
53
54
|
self.heartbeat ||= 60
|
54
55
|
self.no_deps ||= false
|
55
56
|
self.hash_size ||= 2**20 # one million keys ~ 200Mb.
|
56
|
-
self.recovery ||= false
|
57
57
|
self.prefetch ||= self.bootstrap ? 10000000 : 1000
|
58
58
|
self.recovery_timeout ||= 10
|
59
59
|
self.logger ||= defined?(Rails) ? Rails.logger : Logger.new(STDERR).tap { |l| l.level = Logger::WARN }
|
@@ -61,6 +61,11 @@ module Promiscuous::Config
|
|
61
61
|
self.error_notifier ||= proc {}
|
62
62
|
self.version_field ||= '_v'
|
63
63
|
self.recovery_on_boot = true if self.recovery_on_boot.nil?
|
64
|
+
self.on_stats ||= proc { |rate, latency| }
|
65
|
+
self.ignore_exceptions ||= false
|
66
|
+
self.consistency ||= :eventual
|
67
|
+
self.max_retries ||= 10
|
68
|
+
self.generation ||= 1
|
64
69
|
end
|
65
70
|
|
66
71
|
def self.configure(&block)
|
data/lib/promiscuous/error.rb
CHANGED
@@ -1,6 +1,5 @@
|
|
1
1
|
module Promiscuous::Error
|
2
2
|
extend Promiscuous::Autoload
|
3
3
|
autoload :Base, :Connection, :Publisher, :Subscriber, :Recovery,
|
4
|
-
:Dependency, :MissingContext, :
|
5
|
-
:LockUnavailable, :LostLock
|
4
|
+
:Dependency, :MissingContext, :LockUnavailable, :LostLock
|
6
5
|
end
|
data/lib/promiscuous/key.rb
CHANGED
@@ -1,21 +1,10 @@
|
|
1
1
|
class Promiscuous::Key
|
2
|
-
def initialize(role, nodes=[]
|
2
|
+
def initialize(role, nodes=[])
|
3
3
|
@role = role
|
4
4
|
@nodes = nodes
|
5
|
-
@no_join = no_join
|
6
5
|
end
|
7
6
|
|
8
7
|
def join(*nodes)
|
9
|
-
# --- backward compatiblity code ---
|
10
|
-
# TODO remove code
|
11
|
-
if nodes == ['global', nil, nil]
|
12
|
-
return self.class.new(@role, @nodes + nodes, :no_join)
|
13
|
-
end
|
14
|
-
if @no_join
|
15
|
-
return self.class.new(@role, @nodes)
|
16
|
-
end
|
17
|
-
# --- backward compatiblity code ---
|
18
|
-
|
19
8
|
self.class.new(@role, @nodes + nodes)
|
20
9
|
end
|
21
10
|
|
@@ -24,11 +24,11 @@ class Promiscuous::Publisher::Context::Base
|
|
24
24
|
end
|
25
25
|
end
|
26
26
|
|
27
|
-
attr_accessor :name, :read_operations, :extra_dependencies, :
|
27
|
+
attr_accessor :name, :read_operations, :extra_dependencies, :current_user
|
28
28
|
|
29
|
-
def initialize(
|
30
|
-
@name =
|
31
|
-
@
|
29
|
+
def initialize(name=nil, options={})
|
30
|
+
@name = name.try(:to_s) || 'anonymous'
|
31
|
+
@current_user = options[:current_user]
|
32
32
|
@read_operations = []
|
33
33
|
@extra_dependencies = []
|
34
34
|
@transaction_managers = {}
|
@@ -4,12 +4,8 @@ class Promiscuous::Publisher::Context::Middleware < Promiscuous::Publisher::Cont
|
|
4
4
|
|
5
5
|
def process_action(*args)
|
6
6
|
full_name = "#{self.class.controller_path}/#{self.action_name}"
|
7
|
-
|
8
|
-
Promiscuous::Publisher::Context::Middleware.with_context(full_name,
|
9
|
-
end
|
10
|
-
|
11
|
-
def render(*args)
|
12
|
-
Promiscuous::Publisher::Context::Middleware.without_context { super }
|
7
|
+
current_user = self.current_user if self.respond_to?(:current_user)
|
8
|
+
Promiscuous::Publisher::Context::Middleware.with_context(full_name, :current_user => current_user) { super }
|
13
9
|
end
|
14
10
|
end
|
15
11
|
|
@@ -26,23 +22,6 @@ class Promiscuous::Publisher::Context::Middleware < Promiscuous::Publisher::Cont
|
|
26
22
|
Promiscuous.disabled = old_disabled
|
27
23
|
end
|
28
24
|
|
29
|
-
def self.without_context
|
30
|
-
# This is different from the method without_promiscuous in convenience.rb
|
31
|
-
# That's used for render() and things that are *not* supposed to write.
|
32
|
-
# We actually force promiscuous to instrument queries, and make sure that
|
33
|
-
# we don't do any writes we shouldn't.
|
34
|
-
old_disabled, Promiscuous.disabled = Promiscuous.disabled?, false
|
35
|
-
old_current, self.current = self.current, nil
|
36
|
-
yield
|
37
|
-
rescue Exception => e
|
38
|
-
$promiscuous_last_exception = e if e.is_a? Promiscuous::Error::Base
|
39
|
-
pretty_print_exception(e) unless e.is_a? ActionView::MissingTemplate
|
40
|
-
raise e
|
41
|
-
ensure
|
42
|
-
self.current = old_current
|
43
|
-
Promiscuous.disabled = old_disabled
|
44
|
-
end
|
45
|
-
|
46
25
|
def self.pretty_print_exception(e)
|
47
26
|
return if $promiscuous_pretty_print_exception_once == :disable || ENV['RAILS_ENV'] == 'production'
|
48
27
|
return if e.is_a?(SystemExit)
|
@@ -33,13 +33,17 @@ module Promiscuous::Publisher::Model::Ephemeral
|
|
33
33
|
operation = :update unless self.new_record
|
34
34
|
operation = :destroy if self.destroyed
|
35
35
|
|
36
|
-
|
36
|
+
save_operation(operation)
|
37
37
|
|
38
38
|
self.new_record = false
|
39
39
|
true
|
40
40
|
end
|
41
41
|
alias :save! :save
|
42
42
|
|
43
|
+
def save_operation(operation)
|
44
|
+
Promiscuous::Publisher::Operation::Ephemeral.new(:instance => self, :operation => operation).execute
|
45
|
+
end
|
46
|
+
|
43
47
|
def update_attributes(attrs)
|
44
48
|
attrs.each { |attr, value| __send__("#{attr}=", value) }
|
45
49
|
save
|
@@ -22,15 +22,17 @@ module Promiscuous::Publisher::Model::Mock
|
|
22
22
|
end
|
23
23
|
end
|
24
24
|
|
25
|
-
|
26
|
-
|
27
|
-
include Promiscuous::Publisher::Model::Ephemeral::PromiscuousMethodsEphemeral
|
25
|
+
def save_operation(operation)
|
26
|
+
payload = nil
|
28
27
|
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
28
|
+
Promiscuous::Publisher::Context::Middleware.with_context("mocking #{self.class}") do
|
29
|
+
op = Promiscuous::Publisher::Operation::Ephemeral.new(:instance => self, :operation => operation)
|
30
|
+
# TODO FIX the mocks to populate app name, also we need to hook before the
|
31
|
+
# json dump.
|
32
|
+
payload = op.generate_payload
|
33
33
|
end
|
34
|
+
|
35
|
+
Promiscuous::Subscriber::Worker::Message.new(payload).process
|
34
36
|
end
|
35
37
|
|
36
38
|
module ClassMethods
|
@@ -23,7 +23,9 @@ module Promiscuous::Publisher::Model::Mongoid
|
|
23
23
|
|
24
24
|
def sync(options={}, &block)
|
25
25
|
raise "Use promiscuous.sync on the parent instance" if @instance.embedded?
|
26
|
-
|
26
|
+
|
27
|
+
# We can use the ephemeral because both are mongoid and ephemerals are atomic operations.
|
28
|
+
Promiscuous::Publisher::Operation::Ephemeral.new(:instance => @instance, :operation => :update).execute
|
27
29
|
end
|
28
30
|
|
29
31
|
def attribute(attr)
|
@@ -35,10 +35,47 @@ class Promiscuous::Publisher::Operation::Atomic < Promiscuous::Publisher::Operat
|
|
35
35
|
end
|
36
36
|
end
|
37
37
|
|
38
|
-
def
|
39
|
-
|
38
|
+
def do_database_query(query)
|
39
|
+
case operation
|
40
|
+
when :create
|
41
|
+
# We don't stash the version in the document as we can't have races
|
42
|
+
# on the same document.
|
43
|
+
when :update
|
44
|
+
increment_version_in_document
|
45
|
+
# We are now in the possession of an instance that matches the original
|
46
|
+
# selector. We need to make sure the db query will operate on it,
|
47
|
+
# instead of the original selector.
|
48
|
+
use_id_selector(:use_atomic_version_selector => true)
|
49
|
+
# We need to use an atomic versioned selector to make sure that
|
50
|
+
# if we lose the lock for a long period of time, we don't mess up
|
51
|
+
# the record. Perhaps the operation has been recovered a while ago.
|
52
|
+
when :destroy
|
53
|
+
use_id_selector
|
54
|
+
end
|
55
|
+
|
56
|
+
# The driver is responsible to set instance to the appropriate value.
|
57
|
+
query.call_and_remember_result(:instrumented)
|
58
|
+
|
59
|
+
if query.failed?
|
60
|
+
# If we get an network failure, we should retry later.
|
61
|
+
return if recoverable_failure?(query.exception)
|
62
|
+
@instance = nil
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
def yell_about_missing_instance
|
67
|
+
err = "Cannot find document. Database had a dataloss?. Proceeding anyways. #{@recovery_data}"
|
68
|
+
e = Promiscuous::Error::Recovery.new(err)
|
69
|
+
Promiscuous.warn "[recovery] #{e}"
|
70
|
+
Promiscuous::Config.error_notifier.call(e)
|
71
|
+
end
|
40
72
|
|
41
|
-
|
73
|
+
def execute_instrumented(query)
|
74
|
+
if recovering?
|
75
|
+
# The DB died or something. We cannot find our instance any more :(
|
76
|
+
# this is a problem, but we need to publish.
|
77
|
+
yell_about_missing_instance if @instance.nil?
|
78
|
+
else
|
42
79
|
generate_read_dependencies
|
43
80
|
acquire_op_lock
|
44
81
|
|
@@ -75,32 +112,7 @@ class Promiscuous::Publisher::Operation::Atomic < Promiscuous::Publisher::Operat
|
|
75
112
|
# documents are missing on our side to be able to resend the destroy
|
76
113
|
# message.
|
77
114
|
|
78
|
-
|
79
|
-
when :create
|
80
|
-
# We don't stash the version in the document as we can't have races
|
81
|
-
# on the same document.
|
82
|
-
when :update
|
83
|
-
stash_version_in_document(@committed_write_deps.first.version)
|
84
|
-
# We are now in the possession of an instance that matches the original
|
85
|
-
# selector. We need to make sure the db query will operate on it,
|
86
|
-
# instead of the original selector.
|
87
|
-
use_id_selector(:use_atomic_version_selector => true)
|
88
|
-
# We need to use an atomic versioned selector to make sure that
|
89
|
-
# if we lose the lock for a long period of time, we don't mess up
|
90
|
-
# the record. Perhaps the operation has been recovered a while ago.
|
91
|
-
when :destroy
|
92
|
-
use_id_selector
|
93
|
-
end
|
94
|
-
|
95
|
-
# The driver is responsible to set instance to the appropriate value.
|
96
|
-
query.call_and_remember_result(:instrumented)
|
97
|
-
|
98
|
-
if query.failed?
|
99
|
-
# If we get an network failure, we should retry later.
|
100
|
-
return if recoverable_failure?(query.exception)
|
101
|
-
@instance = nil
|
102
|
-
end
|
103
|
-
|
115
|
+
do_database_query(query) unless @instance.nil?
|
104
116
|
# We take a timestamp right after the write is performed because latency
|
105
117
|
# measurements are performed on the subscriber.
|
106
118
|
record_timestamp
|
@@ -141,6 +153,7 @@ class Promiscuous::Publisher::Operation::Atomic < Promiscuous::Publisher::Operat
|
|
141
153
|
def fetch_instance
|
142
154
|
# This method is overridden to use the original query selector.
|
143
155
|
# Should return nil if the instance is not found.
|
156
|
+
@instance.reload if @instance.respond_to?(:reload)
|
144
157
|
@instance
|
145
158
|
end
|
146
159
|
|
@@ -148,9 +161,8 @@ class Promiscuous::Publisher::Operation::Atomic < Promiscuous::Publisher::Operat
|
|
148
161
|
@instance = fetch_instance
|
149
162
|
end
|
150
163
|
|
151
|
-
def
|
152
|
-
# Overridden to
|
153
|
-
# instance[Promiscuous::Config.version_field] = version
|
164
|
+
def increment_version_in_document
|
165
|
+
# Overridden to increment version field in the query
|
154
166
|
end
|
155
167
|
|
156
168
|
def use_id_selector(options={})
|