mongoid-locker 1.0.0 → 1.0.1
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.
- checksums.yaml +4 -4
- data/.gitignore +1 -2
- data/.rubocop.yml +1 -6
- data/.rubocop_todo.yml +46 -27
- data/.travis.yml +36 -10
- data/CHANGELOG.md +11 -0
- data/Gemfile +4 -8
- data/README.md +9 -8
- data/RELEASING.md +2 -2
- data/Rakefile +1 -1
- data/lib/mongoid/locker.rb +19 -18
- data/lib/mongoid/locker/version.rb +1 -1
- data/lib/mongoid/locker/wrapper.rb +2 -16
- data/mongoid-locker.gemspec +2 -3
- metadata +10 -27
- data/demo/README.md +0 -10
- data/demo/config/mongoid.yml +0 -6
- data/demo/instagram.graffle +0 -1012
- data/demo/instagram.png +0 -0
- data/demo/showoff.css +0 -16
- data/demo/showoff.md +0 -159
- data/lib/mongoid/locker/wrapper2.rb +0 -26
- data/lib/mongoid/locker/wrapper3.rb +0 -26
data/demo/instagram.png
DELETED
Binary file
|
data/demo/showoff.css
DELETED
data/demo/showoff.md
DELETED
@@ -1,159 +0,0 @@
|
|
1
|
-
!SLIDE
|
2
|
-
|
3
|
-
# Mongoid-Locker
|
4
|
-
|
5
|
-
[github.com/mongoid/mongoid-locker](https://github.com/mongoid/mongoid-locker)
|
6
|
-
|
7
|
-
## Aidan Feldman, [Jux.com](https://jux.com)
|
8
|
-
|
9
|
-
!SLIDE
|
10
|
-
|
11
|
-

|
12
|
-
|
13
|
-
!SLIDE
|
14
|
-
|
15
|
-
# Jux needed a queue.
|
16
|
-
|
17
|
-
* Distributed, but synchronized
|
18
|
-
* No add'l DB
|
19
|
-
* No add'l hassle (managing workers, etc.)
|
20
|
-
|
21
|
-
!SLIDE
|
22
|
-
|
23
|
-
* Thread
|
24
|
-
- \+ Distributed
|
25
|
-
- – Not synchronized
|
26
|
-
* Many workers
|
27
|
-
- \+ Distributed
|
28
|
-
- – Not synchronized
|
29
|
-
* One worker
|
30
|
-
- \+ Synchronized
|
31
|
-
- – Not distributed
|
32
|
-
- – Single POF
|
33
|
-
|
34
|
-
!SLIDE
|
35
|
-
|
36
|
-
@@@ ruby
|
37
|
-
require 'rubygems'
|
38
|
-
require 'mongoid-locker'
|
39
|
-
Mongoid.load!('config/mongoid.yml', :development)
|
40
|
-
|
41
|
-
|
42
|
-
class User
|
43
|
-
include Mongoid::Document
|
44
|
-
# include Mongoid::Locker
|
45
|
-
|
46
|
-
field :balance, type: Float
|
47
|
-
end
|
48
|
-
|
49
|
-
# cleanup
|
50
|
-
User.destroy_all
|
51
|
-
|
52
|
-
bob = User.create!(balance: 100.00)
|
53
|
-
|
54
|
-
!SLIDE
|
55
|
-
|
56
|
-
# Atomic Operations
|
57
|
-
|
58
|
-
@@@ ruby
|
59
|
-
class User
|
60
|
-
def purchase(amount)
|
61
|
-
if amount > self.balance
|
62
|
-
raise "Can't have negative balance!"
|
63
|
-
else
|
64
|
-
# deduct *atomically*
|
65
|
-
self.inc(:balance, -1 * amount)
|
66
|
-
# a.k.a.
|
67
|
-
# db.users.update({_id: ...}, {$inc: {balance: ...}})
|
68
|
-
|
69
|
-
puts "cha-ching!"
|
70
|
-
end
|
71
|
-
end
|
72
|
-
end
|
73
|
-
|
74
|
-
bob.purchase(5.10) #=> "cha-ching!"
|
75
|
-
bob.purchase(110.53) #=> "Can't have negative balance!"
|
76
|
-
|
77
|
-
!SLIDE
|
78
|
-
|
79
|
-
# All fine, right?
|
80
|
-
|
81
|
-
!SLIDE
|
82
|
-
|
83
|
-
@@@ ruby
|
84
|
-
class User
|
85
|
-
def purchase(amount)
|
86
|
-
if amount > self.balance
|
87
|
-
raise "Can't have negative balance!"
|
88
|
-
else
|
89
|
-
# artificial delay
|
90
|
-
print 'has enough money...waiting for ENTER > '
|
91
|
-
gets
|
92
|
-
|
93
|
-
self.inc(:balance, -1 * amount)
|
94
|
-
puts "cha-ching!"
|
95
|
-
end
|
96
|
-
end
|
97
|
-
end
|
98
|
-
|
99
|
-
!SLIDE
|
100
|
-
|
101
|
-
@@@ ruby
|
102
|
-
# shell 1
|
103
|
-
bob.purchase(10.00)
|
104
|
-
|
105
|
-
# shell 2
|
106
|
-
also_bob = User.first
|
107
|
-
also_bob.purchase(95.00)
|
108
|
-
|
109
|
-
!SLIDE
|
110
|
-
|
111
|
-
# oops.
|
112
|
-
|
113
|
-
!SLIDE
|
114
|
-
|
115
|
-
@@@ ruby
|
116
|
-
class User
|
117
|
-
# add doc-level locking
|
118
|
-
include Mongoid::Locker
|
119
|
-
timeout_lock_after 20
|
120
|
-
|
121
|
-
def purchase(amount)
|
122
|
-
# only one at a time
|
123
|
-
self.with_lock(wait: true) do
|
124
|
-
# after the `wait`, will have updated `balance`
|
125
|
-
|
126
|
-
if amount > self.balance
|
127
|
-
raise "Can't have negative balance!"
|
128
|
-
else
|
129
|
-
print 'has enough money...waiting for ENTER > '
|
130
|
-
gets
|
131
|
-
|
132
|
-
self.inc(:balance, -1 * amount)
|
133
|
-
puts "cha-ching!"
|
134
|
-
end
|
135
|
-
end
|
136
|
-
end
|
137
|
-
end
|
138
|
-
|
139
|
-
!SLIDE
|
140
|
-
|
141
|
-
# Summary
|
142
|
-
|
143
|
-
* Easy document-level locking
|
144
|
-
* Useful for queueing or pseudo-transactions
|
145
|
-
* No additional dependencies
|
146
|
-
|
147
|
-
!SLIDE
|
148
|
-
|
149
|
-
# Fin.
|
150
|
-
|
151
|
-
[mongoid/mongoid-locker](https://github.com/mongoid/mongoid-locker)
|
152
|
-
|
153
|
-
----------------
|
154
|
-
|
155
|
-
## Aidan Feldman
|
156
|
-
|
157
|
-
[@aidanfeldman](https://twitter.com/aidanfeldman)
|
158
|
-
|
159
|
-
[afeld.me](http://afeld.me)
|
@@ -1,26 +0,0 @@
|
|
1
|
-
module Mongoid
|
2
|
-
module Locker
|
3
|
-
# Normalizes queries between various Mongoid versions.
|
4
|
-
module Wrapper
|
5
|
-
# Update the document for the provided Class matching the provided query with the provided setter.
|
6
|
-
#
|
7
|
-
# @param [Class] The model class
|
8
|
-
# @param [Hash] The Mongoid query
|
9
|
-
# @param [Hash] The Mongoid setter
|
10
|
-
# @return [Boolean] true if the document was successfully updated, false otherwise
|
11
|
-
def self.update(klass, query, setter)
|
12
|
-
klass.collection.update(query, setter, safe: true)['n'] == 1
|
13
|
-
end
|
14
|
-
|
15
|
-
# Determine whether the provided document is locked in the database or not.
|
16
|
-
#
|
17
|
-
# @param [Class] The model instance
|
18
|
-
# @return [Time] The timestamp of when the document is locked until, nil if not locked.
|
19
|
-
def self.locked_until(doc)
|
20
|
-
existing_query = { _id: doc.id, doc.locked_until_field => { '$exists' => true } }
|
21
|
-
existing = doc.class.collection.find_one(existing_query, fields: { doc.locked_until_field => 1 })
|
22
|
-
existing ? existing[doc.locked_until_field] : nil
|
23
|
-
end
|
24
|
-
end
|
25
|
-
end
|
26
|
-
end
|
@@ -1,26 +0,0 @@
|
|
1
|
-
module Mongoid
|
2
|
-
module Locker
|
3
|
-
# Normalizes queries between various Mongoid versions.
|
4
|
-
module Wrapper
|
5
|
-
# Update the document for the provided Class matching the provided query with the provided setter.
|
6
|
-
#
|
7
|
-
# @param [Class] The model class
|
8
|
-
# @param [Hash] The Mongoid query
|
9
|
-
# @param [Hash] The Mongoid setter
|
10
|
-
# @return [Boolean] true if the document was successfully updated, false otherwise
|
11
|
-
def self.update(klass, query, setter)
|
12
|
-
klass.with(safe: true).collection.find(query).update(setter)['n'] == 1
|
13
|
-
end
|
14
|
-
|
15
|
-
# Determine whether the provided document is locked in the database or not.
|
16
|
-
#
|
17
|
-
# @param [Class] The model instance
|
18
|
-
# @return [Time] The timestamp of when the document is locked until, nil if not locked.
|
19
|
-
def self.locked_until(doc)
|
20
|
-
existing_query = { _id: doc.id, doc.locked_until_field => { '$exists' => true } }
|
21
|
-
existing = doc.class.where(existing_query).limit(1).only(doc.locked_until_field).first
|
22
|
-
existing ? existing[doc.locked_until_field] : nil
|
23
|
-
end
|
24
|
-
end
|
25
|
-
end
|
26
|
-
end
|