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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 0af2c6f49c7b058970c7fc98be0949625b6f005d
4
- data.tar.gz: '005991b9d6d6355c7c98e9ed0aa9241c3e2b147d'
3
+ metadata.gz: aa3c649e6d7f28c49dc515e0f1fc851921500bc0
4
+ data.tar.gz: b24366c20a4ee898d385af92aeda3cc26b5b8075
5
5
  SHA512:
6
- metadata.gz: 7c34ceac06e7d7e8ffdb256a968a9e8464161fc742065cc3679ab5acdc19c810099c30f084f59940a746d913285509db1bc679426101d0296bc4e3ad6bd05eda
7
- data.tar.gz: 6a700c32cff253497e62aa6e668b95b692ce359dbff3d5e5786154dd00687585ab2e89ea290a2df4164cf7bb23388c0adf73cda47693c3087117502ef25fa9c2
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
- ProcessLock::WithProcessLock.execute('unique_key_for_your_process') do
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
@@ -1,6 +1,9 @@
1
1
  require 'redis'
2
2
  require "process_lock/version"
3
+ require "process_lock/execute_once"
4
+ require "process_lock/execute_with_retry"
3
5
  require "process_lock/with_process_lock"
6
+ require "process_lock/process_lock_error"
4
7
  module ProcessLock
5
8
 
6
9
  end
@@ -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
@@ -0,0 +1,7 @@
1
+ module ProcessLock
2
+ class ProcessLockError < StandardError
3
+ def initialize(key:)
4
+ super("Can not run process because #{key} taken.")
5
+ end
6
+ end
7
+ end
@@ -1,3 +1,3 @@
1
1
  module ProcessLock
2
- VERSION = "0.1.1"
2
+ VERSION = "1.0.0"
3
3
  end
@@ -1,28 +1,27 @@
1
1
  module ProcessLock
2
2
  class WithProcessLock
3
+ class << self
4
+ include ExecuteOnce
5
+ include ExecuteWithRetry
3
6
 
4
- def self.execute(key, &blk)
5
- if can_execute?(key)
7
+ private
8
+
9
+ def execute(key, &blk)
6
10
  redis.set(key, true)
7
- begin
8
- yield blk
9
- ensure
10
- # Delete the key and quit redis even if the block raises an exception
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
- def self.can_execute?(key)
21
- !redis.exists(key)
22
- end
18
+ def can_execute?(key)
19
+ !redis.exists(key)
20
+ end
23
21
 
24
- def self.redis
25
- @_redis ||= Redis.new
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.1.1
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-01 00:00:00.000000000 Z
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