goru 0.3.0 → 0.4.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 65d57e96ef8a7bef1abaf43db02e461af067b60238728379b9a5e48cea91c2f9
4
- data.tar.gz: feba54796b8120fe753014a9f904c29c3e379ef50910e6cfde0507ca85d4d695
3
+ metadata.gz: ee1c8b3918ce9583f53e8d0e80c15b45ac402a33cd006b43cc022c90ddab02ae
4
+ data.tar.gz: 8f951013098962c00aca0e20ba82a3b81b6d30ccb7d36abfae333f042b9bbd53
5
5
  SHA512:
6
- metadata.gz: c65b2730c39ec515c1ab44ee83909c4ea93c53072cb33887aebafaedfeb0131a37c0b3d1bb323b79ce21acdc5248be3fefa3d19c007c9aa5c56217e9a7195541
7
- data.tar.gz: f4d7f05d63ad6ce781053946fa0d0e22ec9562b7e20fed83bca8f84441b4f6ec9c30b8b4b79fa7435cc93a76425ec793b6db7ac334aba0fddac84320777226b3
6
+ metadata.gz: 339305691d3b38927b32c5cc51040a2cd48f179956bcfc6d04648631a6508d2d4147c63a3eef4a75cdd7517a37b255e654875c66f6da60b39a37b20a64fb2028
7
+ data.tar.gz: 65fa5d90461938fac3c3857e431505ba855dabd555afb60993b6a52f4f1d3468db0d7747f433d53139fbc2b34ce600b3677aeb0c73ac79f08514732454a7c599
data/CHANGELOG.md CHANGED
@@ -1,3 +1,19 @@
1
+ ## [v0.4.1](https://github.com/bryanp/goru/releases/tag/v0.4.1)
2
+
3
+ *released on 2023-07-29*
4
+
5
+ * `fix` [#23](https://github.com/bryanp/goru/pull/23) Handle `IOError` in io routines ([bryanp](https://github.com/bryanp))
6
+
7
+ ## [v0.4.0](https://github.com/bryanp/goru/releases/tag/v0.4.0)
8
+
9
+ *released on 2023-07-16*
10
+
11
+ * `add` [#22](https://github.com/bryanp/goru/pull/22) Add reactor as a reader to `Goru::Routine` ([bryanp](https://github.com/bryanp))
12
+ * `add` [#21](https://github.com/bryanp/goru/pull/21) Improve statuses ([bryanp](https://github.com/bryanp))
13
+ * `add` [#20](https://github.com/bryanp/goru/pull/20) Add observer pattern to routines ([bryanp](https://github.com/bryanp))
14
+ * `add` [#19](https://github.com/bryanp/goru/pull/19) Add ability to pause and resume a routine ([bryanp](https://github.com/bryanp))
15
+ * `chg` [#18](https://github.com/bryanp/goru/pull/18) Remove the unused `observer` writer from `Goru::Channel` ([bryanp](https://github.com/bryanp))
16
+
1
17
  ## [v0.3.0](https://github.com/bryanp/goru/releases/tag/v0.3.0)
2
18
 
3
19
  *released on 2023-07-10*
data/lib/goru/bridge.rb CHANGED
@@ -11,6 +11,18 @@ module Goru
11
11
  update_status
12
12
  end
13
13
 
14
+ # [public]
15
+ #
16
+ STATUS_READY = :ready
17
+
18
+ # [public]
19
+ #
20
+ STATUS_FINISHED = :finished
21
+
22
+ # [public]
23
+ #
24
+ STATUS_IDLE = :idle
25
+
14
26
  # [public]
15
27
  #
16
28
  attr_reader :status
@@ -30,9 +42,9 @@ module Goru
30
42
 
31
43
  private def status_changed
32
44
  case @status
33
- when :ready
45
+ when :STATUS_READY
34
46
  @routine.bridged
35
- when :finished
47
+ when :STATUS_FINISHED
36
48
  @channel.remove_observer(self)
37
49
  @routine.unbridge
38
50
  end
@@ -6,14 +6,14 @@ module Goru
6
6
  module Bridges
7
7
  class Readable < Bridge
8
8
  private def update_status
9
- status = if @routine.status == :finished
10
- :finished
9
+ status = if @routine.status == Routine::STATUS_FINISHED
10
+ Bridge::STATUS_FINISHED
11
11
  elsif @channel.full?
12
- :idle
12
+ Bridge::STATUS_IDLE
13
13
  elsif @channel.closed?
14
- :finished
14
+ Bridge::STATUS_FINISHED
15
15
  else
16
- :ready
16
+ Bridge::STATUS_READY
17
17
  end
18
18
 
19
19
  set_status(status)
@@ -6,14 +6,14 @@ module Goru
6
6
  module Bridges
7
7
  class Writable < Bridge
8
8
  private def update_status
9
- status = if @routine.status == :finished
10
- :finished
9
+ status = if @routine.status == Routine::STATUS_FINISHED
10
+ Bridge::STATUS_FINISHED
11
11
  elsif @channel.any?
12
- :ready
12
+ Bridge::STATUS_READY
13
13
  elsif @channel.closed?
14
- :finished
14
+ Bridge::STATUS_FINISHED
15
15
  else
16
- :idle
16
+ Bridge::STATUS_IDLE
17
17
  end
18
18
 
19
19
  set_status(status)
data/lib/goru/channel.rb CHANGED
@@ -11,10 +11,6 @@ module Goru
11
11
  @observers = Set.new
12
12
  end
13
13
 
14
- # [public]
15
- #
16
- attr_writer :observer
17
-
18
14
  # [public]
19
15
  #
20
16
  def <<(message)
data/lib/goru/reactor.rb CHANGED
@@ -21,6 +21,22 @@ module Goru
21
21
  @commands = []
22
22
  end
23
23
 
24
+ # [public]
25
+ #
26
+ STATUS_RUNNING = :running
27
+
28
+ # [public]
29
+ #
30
+ STATUS_FINISHED = :finished
31
+
32
+ # [public]
33
+ #
34
+ STATUS_IDLE = :idle
35
+
36
+ # [public]
37
+ #
38
+ STATUS_STOPPED = :stopped
39
+
24
40
  # [public]
25
41
  #
26
42
  attr_reader :status
@@ -28,7 +44,7 @@ module Goru
28
44
  # [public]
29
45
  #
30
46
  def run
31
- set_status(:running)
47
+ set_status(STATUS_RUNNING)
32
48
 
33
49
  until @stopped
34
50
  tick
@@ -36,7 +52,7 @@ module Goru
36
52
  ensure
37
53
  @timers.cancel
38
54
  @selector.close
39
- set_status(:finished)
55
+ set_status(STATUS_FINISHED)
40
56
  end
41
57
 
42
58
  private def tick
@@ -81,10 +97,10 @@ module Goru
81
97
  interval = @timers.wait_interval
82
98
 
83
99
  if interval.nil? && @routines.empty?
84
- set_status(:idle)
100
+ set_status(STATUS_IDLE)
85
101
  @scheduler.signal
86
102
  wait
87
- set_status(:running)
103
+ set_status(STATUS_RUNNING)
88
104
  elsif interval.nil?
89
105
  wait unless @routines.any?(&:ready?)
90
106
  elsif interval > 0
@@ -103,7 +119,7 @@ module Goru
103
119
  # [public]
104
120
  #
105
121
  def finished?
106
- @status == :idle || @status == :stopped
122
+ @status == STATUS_IDLE || @status == STATUS_STOPPED
107
123
  end
108
124
 
109
125
  # [public]
data/lib/goru/routine.rb CHANGED
@@ -20,14 +20,35 @@ module Goru
20
20
  def initialize(state = nil, &block)
21
21
  @state = state
22
22
  @block = block
23
- set_status(:ready)
23
+ @observers = Set.new
24
+ set_status(STATUS_READY)
24
25
  @result, @error, @reactor = nil
25
26
  @debug = true
26
27
  end
27
28
 
28
29
  # [public]
29
30
  #
30
- attr_reader :state, :status, :error
31
+ STATUS_READY = :ready
32
+
33
+ # [public]
34
+ #
35
+ STATUS_FINISHED = :finished
36
+
37
+ # [public]
38
+ #
39
+ STATUS_ERRORED = :errored
40
+
41
+ # [public]
42
+ #
43
+ STATUS_IDLE = :idle
44
+
45
+ # [public]
46
+ #
47
+ STATUS_PAUSED = :paused
48
+
49
+ # [public]
50
+ #
51
+ attr_reader :state, :status, :error, :reactor
31
52
 
32
53
  # [public]
33
54
  #
@@ -46,7 +67,7 @@ module Goru
46
67
  @block.call(self)
47
68
  rescue => error
48
69
  @error = error
49
- set_status(:errored)
70
+ set_status(STATUS_ERRORED)
50
71
  trigger(error)
51
72
  end
52
73
 
@@ -54,7 +75,7 @@ module Goru
54
75
  #
55
76
  def finished(result = nil)
56
77
  @result = result
57
- set_status(:finished)
78
+ set_status(STATUS_FINISHED)
58
79
 
59
80
  throw :continue
60
81
  end
@@ -69,7 +90,7 @@ module Goru
69
90
  #
70
91
  def result
71
92
  case @status
72
- when :errored
93
+ when STATUS_ERRORED
73
94
  raise @error
74
95
  else
75
96
  @result
@@ -79,9 +100,9 @@ module Goru
79
100
  # [public]
80
101
  #
81
102
  def sleep(seconds)
82
- set_status(:idle)
103
+ set_status(STATUS_IDLE)
83
104
  @reactor.asleep_for(seconds) do
84
- set_status(:ready)
105
+ set_status(STATUS_READY)
85
106
  end
86
107
 
87
108
  throw :continue
@@ -90,7 +111,25 @@ module Goru
90
111
  # [public]
91
112
  #
92
113
  def ready?
93
- @status == :ready
114
+ @status == STATUS_READY
115
+ end
116
+
117
+ # [public]
118
+ #
119
+ def finished?
120
+ @status == STATUS_ERRORED || @status == STATUS_FINISHED
121
+ end
122
+
123
+ # [public]
124
+ #
125
+ def pause
126
+ set_status(STATUS_PAUSED)
127
+ end
128
+
129
+ # [public]
130
+ #
131
+ def resume
132
+ set_status(STATUS_READY)
94
133
  end
95
134
 
96
135
  # [public]
@@ -103,8 +142,10 @@ module Goru
103
142
  # [public]
104
143
  #
105
144
  private def status_changed
145
+ @observers.each(&:call)
146
+
106
147
  case @status
107
- when :errored, :finished
148
+ when STATUS_ERRORED, STATUS_FINISHED
108
149
  @reactor&.routine_finished(self)
109
150
  end
110
151
  end
@@ -114,5 +155,17 @@ module Goru
114
155
  def adopted
115
156
  # noop
116
157
  end
158
+
159
+ # [public]
160
+ #
161
+ def add_observer(observer = nil, &block)
162
+ @observers << (block || observer.method(:routine_status_changed))
163
+ end
164
+
165
+ # [public]
166
+ #
167
+ def remove_observer(observer)
168
+ @observers.delete(observer)
169
+ end
117
170
  end
118
171
  end
@@ -17,9 +17,9 @@ module Goru
17
17
 
18
18
  private def status_changed
19
19
  case @status
20
- when :ready
20
+ when Routine::STATUS_READY
21
21
  @reactor&.wakeup
22
- when :finished
22
+ when Routine::STATUS_FINISHED
23
23
  @channel.remove_observer(self)
24
24
  end
25
25
 
@@ -16,11 +16,11 @@ module Goru
16
16
 
17
17
  private def update_status
18
18
  status = if @channel.any?
19
- :ready
19
+ Routine::STATUS_READY
20
20
  elsif @channel.closed?
21
- :finished
21
+ Routine::STATUS_FINISHED
22
22
  else
23
- :idle
23
+ Routine::STATUS_IDLE
24
24
  end
25
25
 
26
26
  set_status(status)
@@ -16,11 +16,11 @@ module Goru
16
16
 
17
17
  private def update_status
18
18
  status = if @channel.full?
19
- :idle
19
+ Routine::STATUS_IDLE
20
20
  elsif @channel.closed?
21
- :finished
21
+ Routine::STATUS_FINISHED
22
22
  else
23
- :ready
23
+ Routine::STATUS_READY
24
24
  end
25
25
 
26
26
  set_status(status)
@@ -19,6 +19,10 @@ module Goru
19
19
  @monitor = nil
20
20
  end
21
21
 
22
+ # [public]
23
+ #
24
+ STATUS_IO_READY = :io_ready
25
+
22
26
  # [public]
23
27
  #
24
28
  attr_reader :io, :intent
@@ -28,7 +32,7 @@ module Goru
28
32
  # [public]
29
33
  #
30
34
  def adopted
31
- set_status(:ready)
35
+ set_status(Routine::STATUS_READY)
32
36
  end
33
37
 
34
38
  # [public]
@@ -39,11 +43,11 @@ module Goru
39
43
  #
40
44
  @monitor&.interests = nil
41
45
 
42
- set_status(:io_ready)
46
+ set_status(STATUS_IO_READY)
43
47
  end
44
48
 
45
- READY_STATUSES = [:io_ready, :ready].freeze
46
- READY_BRIDGE_STATUSES = [nil, :ready].freeze
49
+ READY_STATUSES = [STATUS_IO_READY, Routine::STATUS_READY].freeze
50
+ READY_BRIDGE_STATUSES = [nil, Bridge::STATUS_READY].freeze
47
51
 
48
52
  # [public]
49
53
  #
@@ -64,8 +68,9 @@ module Goru
64
68
  rescue Errno::EAGAIN
65
69
  wait
66
70
  rescue Errno::ECONNRESET, Errno::EPIPE, EOFError
67
- finished
68
- nil
71
+ handle_io_unavailable
72
+ rescue IOError
73
+ handle_io_unavailable
69
74
  end
70
75
 
71
76
  def wait
@@ -82,8 +87,9 @@ module Goru
82
87
  rescue Errno::EAGAIN
83
88
  wait
84
89
  rescue Errno::ECONNRESET, Errno::EPIPE, EOFError
85
- finished
86
- nil
90
+ handle_io_unavailable
91
+ rescue IOError
92
+ handle_io_unavailable
87
93
  end
88
94
 
89
95
  # [public]
@@ -93,6 +99,12 @@ module Goru
93
99
  rescue Errno::EAGAIN
94
100
  wait
95
101
  rescue Errno::ECONNRESET, Errno::EPIPE, EOFError
102
+ handle_io_unavailable
103
+ rescue IOError
104
+ handle_io_unavailable
105
+ end
106
+
107
+ private def handle_io_unavailable
96
108
  finished
97
109
  nil
98
110
  end
@@ -151,7 +163,7 @@ module Goru
151
163
 
152
164
  private def status_changed
153
165
  case @status
154
- when :finished
166
+ when Routine::STATUS_FINISHED
155
167
  @reactor&.deregister(self)
156
168
  end
157
169
 
data/lib/goru/version.rb CHANGED
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Goru
4
- VERSION = "0.3.0"
4
+ VERSION = "0.4.1"
5
5
 
6
6
  # [public]
7
7
  #
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: goru
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.0
4
+ version: 0.4.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Bryan Powell
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2023-07-10 00:00:00.000000000 Z
11
+ date: 2023-07-29 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: core-extension
@@ -121,7 +121,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
121
121
  - !ruby/object:Gem::Version
122
122
  version: '0'
123
123
  requirements: []
124
- rubygems_version: 3.4.12
124
+ rubygems_version: 3.4.17
125
125
  signing_key:
126
126
  specification_version: 4
127
127
  summary: Concurrent routines for Ruby.