status_workflow 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 -0
- data/.travis.yml +1 -0
- data/CHANGELOG +6 -0
- data/README.md +2 -0
- data/lib/status_workflow.rb +39 -10
- data/lib/status_workflow/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 31fac79b181eaf226d6f199406c58b23f2860674
|
4
|
+
data.tar.gz: abb35fc730390397b21692c0a0f398a9628253e1
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: e7f31170e7845fcd47a2f0f9ab5e68c08b6a7eae0226f784b8060d563a4ffa812ca21d7ff79230e248fb899d2a325d57299ce830ade5ffb4776d412247889a85
|
7
|
+
data.tar.gz: 271e5943314d59d02ca2a8e48e2cd5750077fbea2986605c2ca3d0074de16efca5bbb407cbd5fc76b6d1316bb4a80629c8ddff2d877b574a9d9e7da5c1b9f50c
|
data/.gitignore
CHANGED
data/.travis.yml
CHANGED
data/CHANGELOG
CHANGED
data/README.md
CHANGED
data/lib/status_workflow.rb
CHANGED
@@ -1,5 +1,6 @@
|
|
1
1
|
require 'status_workflow/version'
|
2
2
|
require 'timeout'
|
3
|
+
require 'set'
|
3
4
|
|
4
5
|
module StatusWorkflow
|
5
6
|
class InvalidTransition < StandardError; end
|
@@ -16,29 +17,57 @@ module StatusWorkflow
|
|
16
17
|
@redis or raise("please set StatusWorkflow.redis=")
|
17
18
|
end
|
18
19
|
|
20
|
+
LOCK_ACQUISITION_TIMEOUT = 8
|
21
|
+
LOCK_EXPIRY = 4
|
22
|
+
LOCK_CHECK_RATE = 0.2
|
23
|
+
|
19
24
|
module ClassMethods
|
20
25
|
def status_workflow(transitions)
|
21
26
|
transitions.inject({}) do |memo, (from_status, to_statuses)|
|
22
27
|
to_statuses.each do |to_status|
|
23
|
-
memo[to_status] ||=
|
28
|
+
memo[to_status] ||= Set.new
|
24
29
|
memo[to_status] << from_status
|
25
30
|
end
|
26
31
|
memo
|
27
32
|
end.each do |to_status, from_statuses|
|
28
|
-
define_method "enter_#{to_status}!" do
|
33
|
+
define_method "enter_#{to_status}!" do |&blk|
|
29
34
|
lock_key = "status_workflow/#{self.class.name}/#{id}"
|
30
|
-
|
31
|
-
|
32
|
-
|
35
|
+
# Give ourselves 8 seconds to get the lock, checking every 0.2 seconds
|
36
|
+
Timeout.timeout(LOCK_ACQUISITION_TIMEOUT, nil, "timeout waiting for #{self.class.name}/#{id} lock") do
|
37
|
+
until StatusWorkflow.redis.set(lock_key, true, nx: true, ex: LOCK_EXPIRY)
|
38
|
+
sleep LOCK_CHECK_RATE
|
33
39
|
end
|
34
40
|
end
|
35
|
-
|
36
|
-
|
37
|
-
#
|
38
|
-
|
41
|
+
heartbeat = nil
|
42
|
+
begin
|
43
|
+
# Give ourselves 2 seconds to check the status of the lock
|
44
|
+
Timeout.timeout(2, nil, "timeout waiting for #{self.class.name}/#{id} status check") do
|
45
|
+
# depend on #can_enter_X to reload
|
46
|
+
raise InvalidTransition, "can't enter #{to_status} from #{status}, expected #{from_statuses.to_a.join('/')}" unless send("can_enter_#{to_status}?")
|
47
|
+
end
|
48
|
+
# If a block was given, start a heartbeat thread
|
49
|
+
if blk
|
50
|
+
begin
|
51
|
+
heartbeat = Thread.new do
|
52
|
+
loop do
|
53
|
+
StatusWorkflow.redis.expire lock_key, LOCK_EXPIRY
|
54
|
+
sleep LOCK_EXPIRY/2
|
55
|
+
end
|
56
|
+
end
|
57
|
+
blk.call
|
58
|
+
rescue
|
59
|
+
# If the block errors, set status to error and record the backtrace
|
60
|
+
error = (["#{$!.class} #{$!.message}"] + $!.backtrace).join("\n")
|
61
|
+
update_columns status: 'error', status_changed_at: Time.now, error: error
|
62
|
+
raise
|
63
|
+
end
|
64
|
+
end
|
65
|
+
# Success!
|
39
66
|
update_columns status: to_status, status_changed_at: Time.now
|
67
|
+
ensure
|
68
|
+
StatusWorkflow.redis.del lock_key
|
69
|
+
heartbeat.kill if heartbeat
|
40
70
|
end
|
41
|
-
StatusWorkflow.redis.del lock_key
|
42
71
|
true
|
43
72
|
end
|
44
73
|
define_method "can_enter_#{to_status}?" do
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: status_workflow
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.0.
|
4
|
+
version: 1.0.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Seamus Abshere
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2018-09-
|
11
|
+
date: 2018-09-28 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: redis
|