event_store_subscriptions 1.0.0 → 1.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/event_store_subscriptions/make_atomic.rb +23 -0
- data/lib/event_store_subscriptions/object_state.rb +2 -3
- data/lib/event_store_subscriptions/subscription.rb +33 -33
- data/lib/event_store_subscriptions/subscriptions.rb +11 -10
- data/lib/event_store_subscriptions/version.rb +1 -1
- data/lib/event_store_subscriptions/watch_dog.rb +1 -12
- data/lib/event_store_subscriptions.rb +1 -0
- metadata +3 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: a7e6e16c2a7382f97ae35a90701acbcd6d1ddbb76f3de3d8d91fb4f5a5970301
|
4
|
+
data.tar.gz: 297942167731aa297bd5d1d036cba81fc8a5b2f050abc5a46c2918ffe43260c3
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: f5425d9761f330cd9cbabf2b19947709cb75cfecb7a604015fc6c1a8f768ebc97d9d35d87191e14706db7f9bfe2b79fce2a39608cca004116333f80ea7356d95
|
7
|
+
data.tar.gz: b3e1c417218056c29a85ef135a270296e2683258cc57b49bc19c7e12a7949b8aac2076fc9aa45fbd6c1bc69c4809a77b89b56c68bc91467a6d39a89c0f7228b3
|
@@ -0,0 +1,23 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module EventStoreSubscriptions
|
4
|
+
module MakeAtomic
|
5
|
+
# Wraps method in Mutex#synchronize to make it atomic. You should have #semaphore method
|
6
|
+
# implemented in order this to work.
|
7
|
+
# @param method [Symbol] a name of the method
|
8
|
+
# @return [Symbol]
|
9
|
+
def make_atomic(method)
|
10
|
+
module_to_prepend = Module.new do
|
11
|
+
class_eval <<-RUBY, __FILE__, __LINE__ + 1
|
12
|
+
def #{method}(*args, **kwargs, &blk)
|
13
|
+
semaphore.synchronize do
|
14
|
+
super
|
15
|
+
end
|
16
|
+
end
|
17
|
+
RUBY
|
18
|
+
end
|
19
|
+
prepend module_to_prepend
|
20
|
+
method
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -10,7 +10,6 @@ module EventStoreSubscriptions
|
|
10
10
|
STATES = %i(initial running halting stopped dead).freeze
|
11
11
|
|
12
12
|
def initialize
|
13
|
-
@semaphore = Thread::Mutex.new
|
14
13
|
initial!
|
15
14
|
end
|
16
15
|
|
@@ -18,13 +17,13 @@ module EventStoreSubscriptions
|
|
18
17
|
# Checks whether the object is in appropriate state
|
19
18
|
# @return [Boolean]
|
20
19
|
define_method "#{state}?" do
|
21
|
-
|
20
|
+
self.state == state
|
22
21
|
end
|
23
22
|
|
24
23
|
# Sets the state.
|
25
24
|
# @return [Symbol]
|
26
25
|
define_method "#{state}!" do
|
27
|
-
|
26
|
+
self.state = state
|
28
27
|
end
|
29
28
|
end
|
30
29
|
|
@@ -3,11 +3,12 @@
|
|
3
3
|
module EventStoreSubscriptions
|
4
4
|
class Subscription
|
5
5
|
include WaitForFinish
|
6
|
+
extend MakeAtomic
|
6
7
|
|
7
8
|
FORCED_SHUTDOWN_DELAY = 60 # seconds
|
8
9
|
|
9
10
|
attr_accessor :runner
|
10
|
-
attr_reader :client, :setup, :state, :position, :statistic
|
11
|
+
attr_reader :client, :setup, :state, :position, :statistic, :semaphore
|
11
12
|
private :runner, :runner=
|
12
13
|
|
13
14
|
# @param position [EventStoreSubscriptions::SubscriptionPosition, EventStoreSubscriptions::SubscriptionRevision]
|
@@ -21,36 +22,19 @@ module EventStoreSubscriptions
|
|
21
22
|
@state = ObjectState.new
|
22
23
|
@statistic = statistic
|
23
24
|
@runner = nil
|
25
|
+
@semaphore = Mutex.new
|
24
26
|
end
|
25
27
|
|
26
28
|
# Start listening for the events
|
27
29
|
# @return [EventStoreSubscriptions::Subscription] returns self
|
28
|
-
def listen
|
29
|
-
|
30
|
-
begin
|
31
|
-
state.running!
|
32
|
-
Thread.new do
|
33
|
-
Thread.current.abort_on_exception = false
|
34
|
-
Thread.current.report_on_exception = false
|
35
|
-
client.subscribe_to_stream(
|
36
|
-
*setup.args,
|
37
|
-
**adjusted_kwargs,
|
38
|
-
&setup.blk
|
39
|
-
)
|
40
|
-
rescue StandardError => e
|
41
|
-
statistic.last_error = e
|
42
|
-
statistic.errors_count += 1
|
43
|
-
state.dead!
|
44
|
-
raise
|
45
|
-
end
|
46
|
-
end
|
47
|
-
self
|
30
|
+
make_atomic def listen
|
31
|
+
_listen
|
48
32
|
end
|
49
33
|
|
50
34
|
# Stops listening for events. This command is async - the result is not immediate. Use the #wait_for_finish
|
51
35
|
# method to wait until the runner has fully stopped.
|
52
36
|
# @return [EventStoreSubscriptions::Subscription] returns self
|
53
|
-
def stop_listening
|
37
|
+
make_atomic def stop_listening
|
54
38
|
return self unless runner&.alive?
|
55
39
|
|
56
40
|
state.halting!
|
@@ -71,22 +55,38 @@ module EventStoreSubscriptions
|
|
71
55
|
self
|
72
56
|
end
|
73
57
|
|
74
|
-
|
75
|
-
|
76
|
-
# @return [EventStoreSubscriptions::Subscription] frozen object
|
77
|
-
# @raise [EventStoreSubscriptions::ThreadNotDeadError] raises this error in case runner Thread
|
78
|
-
# is still alive for some reason. Normally this should never happen.
|
79
|
-
def delete
|
80
|
-
if runner&.alive?
|
81
|
-
raise ThreadNotDeadError, "Can not delete alive Subscription #{self.inspect}"
|
82
|
-
end
|
58
|
+
make_atomic def restart
|
59
|
+
return self if runner&.alive?
|
83
60
|
|
84
|
-
|
85
|
-
|
61
|
+
statistic.last_restart_at = Time.now.utc
|
62
|
+
_listen
|
86
63
|
end
|
87
64
|
|
88
65
|
private
|
89
66
|
|
67
|
+
# @return [EventStoreSubscriptions::Subscription] returns self
|
68
|
+
def _listen
|
69
|
+
self.runner ||=
|
70
|
+
begin
|
71
|
+
state.running!
|
72
|
+
Thread.new do
|
73
|
+
Thread.current.abort_on_exception = false
|
74
|
+
Thread.current.report_on_exception = false
|
75
|
+
client.subscribe_to_stream(
|
76
|
+
*setup.args,
|
77
|
+
**adjusted_kwargs,
|
78
|
+
&setup.blk
|
79
|
+
)
|
80
|
+
rescue StandardError => e
|
81
|
+
statistic.last_error = e
|
82
|
+
statistic.errors_count += 1
|
83
|
+
state.dead!
|
84
|
+
raise
|
85
|
+
end
|
86
|
+
end
|
87
|
+
self
|
88
|
+
end
|
89
|
+
|
90
90
|
# Wraps original handler into our own handler to provide extended functionality.
|
91
91
|
# @param original_handler [#call]
|
92
92
|
# @return [Proc]
|
@@ -3,6 +3,7 @@
|
|
3
3
|
module EventStoreSubscriptions
|
4
4
|
# Implements Subscription-s collection
|
5
5
|
class Subscriptions
|
6
|
+
extend MakeAtomic
|
6
7
|
ALL_STREAM = '$all'
|
7
8
|
|
8
9
|
attr_reader :client
|
@@ -37,34 +38,34 @@ module EventStoreSubscriptions
|
|
37
38
|
# Adds Subscription to the collection
|
38
39
|
# @param subscription [EventStoreSubscriptions::Subscription]
|
39
40
|
# @return [Array<EventStoreSubscriptions::Subscription>] current subscription's collection
|
40
|
-
def add(subscription)
|
41
|
-
|
41
|
+
make_atomic def add(subscription)
|
42
|
+
@subscriptions << subscription
|
42
43
|
end
|
43
44
|
|
44
45
|
# Removes subscription from the collection
|
45
46
|
# @param subscription [EventStoreSubscriptions::Subscription]
|
46
47
|
# @return [EventStoreSubscriptions::Subscription, nil] returns deleted subscription or nil if it
|
47
48
|
# wasn't present in the collection
|
48
|
-
def remove(subscription)
|
49
|
-
|
49
|
+
make_atomic def remove(subscription)
|
50
|
+
@subscriptions.delete(subscription)
|
50
51
|
end
|
51
52
|
|
52
53
|
# Starts listening to all subscriptions in the collection
|
53
54
|
# @return [Array<EventStoreSubscriptions::Subscription>]
|
54
|
-
def listen_all
|
55
|
-
|
55
|
+
make_atomic def listen_all
|
56
|
+
@subscriptions.each(&:listen)
|
56
57
|
end
|
57
58
|
|
58
59
|
# Stops listening to all subscriptions in the collection
|
59
60
|
# @return [Array<EventStoreSubscriptions::Subscription>]
|
60
|
-
def stop_all
|
61
|
-
|
61
|
+
make_atomic def stop_all
|
62
|
+
@subscriptions.each(&:stop_listening)
|
62
63
|
end
|
63
64
|
|
64
65
|
# @return [Array<EventStoreSubscriptions::Subscription>]
|
65
|
-
def subscriptions
|
66
|
+
make_atomic def subscriptions
|
66
67
|
# Duping original collection to prevent potential mutable operations over it from user's side
|
67
|
-
|
68
|
+
@subscriptions.dup
|
68
69
|
end
|
69
70
|
|
70
71
|
private
|
@@ -92,19 +92,8 @@ module EventStoreSubscriptions
|
|
92
92
|
# @return [EventStoreSubscriptions::Subscription] newly created Subscription
|
93
93
|
def restart_subscription(failed_sub)
|
94
94
|
return if restart_terminator&.call(failed_sub)
|
95
|
-
# Check if no one else did this job
|
96
|
-
return unless collection.remove(failed_sub)
|
97
95
|
|
98
|
-
|
99
|
-
position: failed_sub.position,
|
100
|
-
client: failed_sub.client,
|
101
|
-
setup: failed_sub.setup,
|
102
|
-
statistic: failed_sub.statistic
|
103
|
-
)
|
104
|
-
new_sub.statistic.last_restart_at = Time.now.utc
|
105
|
-
collection.add(new_sub)
|
106
|
-
failed_sub.delete
|
107
|
-
new_sub.listen
|
96
|
+
failed_sub.restart
|
108
97
|
end
|
109
98
|
end
|
110
99
|
end
|
@@ -4,6 +4,7 @@ require 'event_store_client'
|
|
4
4
|
require_relative 'event_store_subscriptions/version'
|
5
5
|
require_relative 'event_store_subscriptions/error'
|
6
6
|
require_relative 'event_store_subscriptions/wait_for_finish'
|
7
|
+
require_relative 'event_store_subscriptions/make_atomic'
|
7
8
|
require_relative 'event_store_subscriptions/object_state'
|
8
9
|
require_relative 'event_store_subscriptions/subscription_statistic'
|
9
10
|
require_relative 'event_store_subscriptions/subscription'
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: event_store_subscriptions
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.1.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Ivan Dzyzenko
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2022-10-
|
11
|
+
date: 2022-10-18 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: event_store_client
|
@@ -77,6 +77,7 @@ files:
|
|
77
77
|
- README.md
|
78
78
|
- lib/event_store_subscriptions.rb
|
79
79
|
- lib/event_store_subscriptions/error.rb
|
80
|
+
- lib/event_store_subscriptions/make_atomic.rb
|
80
81
|
- lib/event_store_subscriptions/object_state.rb
|
81
82
|
- lib/event_store_subscriptions/subscription.rb
|
82
83
|
- lib/event_store_subscriptions/subscription_position.rb
|