with_process_lock 0.1.1 → 1.0.0
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/README.md +47 -1
- data/lib/process_lock.rb +3 -0
- data/lib/process_lock/execute_once.rb +15 -0
- data/lib/process_lock/execute_with_retry.rb +37 -0
- data/lib/process_lock/process_lock_error.rb +7 -0
- data/lib/process_lock/version.rb +1 -1
- data/lib/process_lock/with_process_lock.rb +16 -17
- metadata +5 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: aa3c649e6d7f28c49dc515e0f1fc851921500bc0
|
4
|
+
data.tar.gz: b24366c20a4ee898d385af92aeda3cc26b5b8075
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: e4e1a90d66242b191695f42f26ffd548c8a3d3ef46d7c753cfbddc622d4fda065758b83ff5dfbcc095095b9e1f2a902aa0291739de4aeb1a5c91cadf223754e5
|
7
|
+
data.tar.gz: b4bdd542ced26842e933f99ee754f0fc1b74ad95cabadf7200044d25367d0c39a5807047381566c04fd18039a0461afe4abab2d2c19aef264dcaaa1f971dcdd0
|
data/README.md
CHANGED
@@ -29,13 +29,59 @@ Or install it yourself as:
|
|
29
29
|
|
30
30
|
## Usage
|
31
31
|
|
32
|
+
You can attempt to run a process once with `execute_once`. It will execute the
|
33
|
+
block if the process is not locked, otherwise it will raise an exception.
|
34
|
+
|
35
|
+
```
|
36
|
+
ProcessLock::WithProcessLock.execute_once('unique_key_for_your_process') do
|
37
|
+
# The code to run in the process
|
38
|
+
do_stuff
|
39
|
+
end
|
40
|
+
```
|
41
|
+
|
42
|
+
You can run a process with a retry:
|
43
|
+
|
44
|
+
```
|
45
|
+
ProcessLock::WithProcessLock.execute_with_retry(
|
46
|
+
'unique_key_for_your_process'
|
47
|
+
) do
|
48
|
+
# The code to run in the process
|
49
|
+
do_stuff
|
50
|
+
end
|
32
51
|
```
|
33
|
-
|
52
|
+
|
53
|
+
This will retry running the block every 1 second until the process is unblocked.
|
54
|
+
The current thread will be blocked until the block successfully executes.
|
55
|
+
You can override the default retry wait by providing the `retry_wait` parameter
|
56
|
+
in seconds.
|
57
|
+
|
58
|
+
```
|
59
|
+
ProcessLock::WithProcessLock.execute_with_retry(
|
60
|
+
'unique_key_for_your_process',
|
61
|
+
retry_wait: 2
|
62
|
+
) do
|
63
|
+
# The code to run in the process
|
64
|
+
do_stuff
|
65
|
+
end
|
66
|
+
```
|
67
|
+
|
68
|
+
If you don't want the retry to run forever, you can specify a timeout by
|
69
|
+
providing the `timeout` parameter in seconds:
|
70
|
+
|
71
|
+
|
72
|
+
```
|
73
|
+
ProcessLock::WithProcessLock.execute_with_retry(
|
74
|
+
'unique_key_for_your_process',
|
75
|
+
retry_wait: 2,
|
76
|
+
timeout: 10
|
77
|
+
) do
|
34
78
|
# The code to run in the process
|
35
79
|
do_stuff
|
36
80
|
end
|
37
81
|
```
|
38
82
|
|
83
|
+
This will retry until the timeout time is expired, then raise an error.
|
84
|
+
|
39
85
|
## Development
|
40
86
|
|
41
87
|
After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake test` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
|
data/lib/process_lock.rb
CHANGED
@@ -0,0 +1,15 @@
|
|
1
|
+
module ProcessLock
|
2
|
+
module ExecuteOnce
|
3
|
+
# Tries to run the given block and raises an exception if the process is
|
4
|
+
# locked
|
5
|
+
# @param key [String] The unique key to determine if the process is locked
|
6
|
+
def execute_once(key, &blk)
|
7
|
+
if can_execute?(key)
|
8
|
+
execute(key, &blk)
|
9
|
+
else
|
10
|
+
redis.quit
|
11
|
+
raise ProcessLockError, key: key
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
module ProcessLock
|
2
|
+
module ExecuteWithRetry
|
3
|
+
# Tries to run the given block and retries every retry_wait seconds until
|
4
|
+
# the process in unblocked
|
5
|
+
# @param key [String] The unique key to determine if the process is locked
|
6
|
+
# @param retry_wait [Number] The number of seconds to wait in between
|
7
|
+
# retry attempts, defaulting to 1
|
8
|
+
# @param timeout [Number] The number of seconds until an exception should
|
9
|
+
# be raised instead of retrying, defaulting to nil (no timeout)
|
10
|
+
def execute_with_retry(
|
11
|
+
key,
|
12
|
+
retry_wait: 1,
|
13
|
+
timeout: nil,
|
14
|
+
&blk
|
15
|
+
)
|
16
|
+
if can_execute?(key)
|
17
|
+
execute(key, &blk)
|
18
|
+
else
|
19
|
+
# If there is time left before timeout or there is no timeout,
|
20
|
+
# wait retry_wait seconds and then recurse
|
21
|
+
if timeout.nil? || timeout >= retry_wait
|
22
|
+
sleep(retry_wait)
|
23
|
+
execute_with_retry(
|
24
|
+
key,
|
25
|
+
retry_wait: retry_wait,
|
26
|
+
timeout: timeout.nil? ? nil : timeout - retry_wait,
|
27
|
+
&blk
|
28
|
+
)
|
29
|
+
else
|
30
|
+
# If the timeout was reached, give up
|
31
|
+
redis.quit
|
32
|
+
raise ProcessLockError, key: key
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
data/lib/process_lock/version.rb
CHANGED
@@ -1,28 +1,27 @@
|
|
1
1
|
module ProcessLock
|
2
2
|
class WithProcessLock
|
3
|
+
class << self
|
4
|
+
include ExecuteOnce
|
5
|
+
include ExecuteWithRetry
|
3
6
|
|
4
|
-
|
5
|
-
|
7
|
+
private
|
8
|
+
|
9
|
+
def execute(key, &blk)
|
6
10
|
redis.set(key, true)
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
redis.del(key)
|
12
|
-
redis.quit
|
13
|
-
end
|
14
|
-
else
|
11
|
+
yield blk
|
12
|
+
ensure
|
13
|
+
# Delete the key and quit redis even if the block raises an exception
|
14
|
+
redis.del(key)
|
15
15
|
redis.quit
|
16
|
-
raise StandardError, "Can not run process because #{key} taken."
|
17
16
|
end
|
18
|
-
end
|
19
17
|
|
20
|
-
|
21
|
-
|
22
|
-
|
18
|
+
def can_execute?(key)
|
19
|
+
!redis.exists(key)
|
20
|
+
end
|
23
21
|
|
24
|
-
|
25
|
-
|
22
|
+
def redis
|
23
|
+
@_redis ||= Redis.new
|
24
|
+
end
|
26
25
|
end
|
27
26
|
end
|
28
27
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: with_process_lock
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 1.0.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- James Friedman
|
@@ -10,7 +10,7 @@ authors:
|
|
10
10
|
autorequire:
|
11
11
|
bindir: exe
|
12
12
|
cert_chain: []
|
13
|
-
date: 2017-05-
|
13
|
+
date: 2017-05-02 00:00:00.000000000 Z
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
16
16
|
name: redis
|
@@ -141,6 +141,9 @@ files:
|
|
141
141
|
- bin/console
|
142
142
|
- bin/setup
|
143
143
|
- lib/process_lock.rb
|
144
|
+
- lib/process_lock/execute_once.rb
|
145
|
+
- lib/process_lock/execute_with_retry.rb
|
146
|
+
- lib/process_lock/process_lock_error.rb
|
144
147
|
- lib/process_lock/version.rb
|
145
148
|
- lib/process_lock/with_process_lock.rb
|
146
149
|
- process_lock.gemspec
|