cosmonats 0.6.0 → 0.7.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.
Files changed (82) hide show
  1. checksums.yaml +4 -4
  2. data/LICENSE.txt +21 -169
  3. data/README.md +101 -17
  4. data/lib/cosmo/api/counter.rb +14 -11
  5. data/lib/cosmo/api/cron/entry.rb +23 -3
  6. data/lib/cosmo/api/cron.rb +22 -26
  7. data/lib/cosmo/api/job.rb +30 -0
  8. data/lib/cosmo/api/kv.rb +31 -11
  9. data/lib/cosmo/api/registry.rb +68 -0
  10. data/lib/cosmo/api/stats/busy.rb +63 -0
  11. data/lib/cosmo/api/stats/processes.rb +37 -0
  12. data/lib/cosmo/api/stats/totals.rb +35 -0
  13. data/lib/cosmo/api/stats.rb +5 -4
  14. data/lib/cosmo/api/stream.rb +1 -1
  15. data/lib/cosmo/api.rb +3 -2
  16. data/lib/cosmo/batch.rb +9 -2
  17. data/lib/cosmo/cli.rb +27 -7
  18. data/lib/cosmo/client.rb +33 -5
  19. data/lib/cosmo/config.rb +6 -2
  20. data/lib/cosmo/engine.rb +103 -4
  21. data/lib/cosmo/heartbeat.rb +129 -0
  22. data/lib/cosmo/http_server/handler.rb +44 -0
  23. data/lib/cosmo/http_server/health.rb +39 -0
  24. data/lib/cosmo/http_server/ping.rb +23 -0
  25. data/lib/cosmo/http_server.rb +62 -0
  26. data/lib/cosmo/job/failure.rb +52 -0
  27. data/lib/cosmo/job/processor.rb +87 -25
  28. data/lib/cosmo/job/stream_filter.rb +54 -0
  29. data/lib/cosmo/job.rb +2 -0
  30. data/lib/cosmo/processor.rb +39 -4
  31. data/lib/cosmo/sentry/job_processor_middleware.rb +1 -2
  32. data/lib/cosmo/stream/message.rb +2 -1
  33. data/lib/cosmo/stream/processor.rb +5 -0
  34. data/lib/cosmo/utils/json.rb +1 -1
  35. data/lib/cosmo/utils/overrides.rb +16 -10
  36. data/lib/cosmo/utils/thread_pool.rb +5 -0
  37. data/lib/cosmo/version.rb +1 -1
  38. data/lib/cosmo/web/assets/app.css +21 -0
  39. data/lib/cosmo/web/controllers/jobs.rb +28 -4
  40. data/lib/cosmo/web/helpers/application.rb +10 -1
  41. data/lib/cosmo/web/views/batches/index.erb +1 -1
  42. data/lib/cosmo/web/views/jobs/_busy.erb +70 -4
  43. data/lib/cosmo/web/views/jobs/_dead.erb +29 -16
  44. data/lib/cosmo/web/views/jobs/_enqueued.erb +10 -0
  45. data/lib/cosmo/web/views/jobs/_processes.erb +131 -0
  46. data/lib/cosmo/web/views/jobs/_scheduled.erb +1 -1
  47. data/lib/cosmo/web/views/jobs/busy.erb +1 -1
  48. data/lib/cosmo/web/views/jobs/dead.erb +2 -2
  49. data/lib/cosmo/web/views/jobs/enqueued.erb +1 -1
  50. data/lib/cosmo/web/views/jobs/index.erb +7 -1
  51. data/lib/cosmo/web/views/jobs/scheduled.erb +1 -1
  52. data/lib/cosmo/web/views/streams/index.erb +1 -1
  53. data/lib/cosmo/web.rb +2 -0
  54. data/lib/cosmo.rb +13 -0
  55. data/sig/cosmo/api/counter.rbs +2 -4
  56. data/sig/cosmo/api/cron/entry.rbs +2 -0
  57. data/sig/cosmo/api/cron.rbs +4 -2
  58. data/sig/cosmo/api/job.rbs +12 -0
  59. data/sig/cosmo/api/kv.rbs +7 -1
  60. data/sig/cosmo/api/registry.rbs +30 -0
  61. data/sig/cosmo/api/stats/busy.rbs +31 -0
  62. data/sig/cosmo/api/stats/processes.rbs +16 -0
  63. data/sig/cosmo/api/stats/totals.rbs +17 -0
  64. data/sig/cosmo/cli.rbs +4 -0
  65. data/sig/cosmo/client.rbs +12 -1
  66. data/sig/cosmo/engine.rbs +29 -0
  67. data/sig/cosmo/heartbeat.rbs +36 -0
  68. data/sig/cosmo/http_server/handler.rbs +17 -0
  69. data/sig/cosmo/http_server/health.rbs +21 -0
  70. data/sig/cosmo/http_server/ping.rbs +14 -0
  71. data/sig/cosmo/http_server.rbs +22 -0
  72. data/sig/cosmo/job/failure.rbs +28 -0
  73. data/sig/cosmo/job/processor.rbs +17 -1
  74. data/sig/cosmo/job/stream_filter.rbs +25 -0
  75. data/sig/cosmo/processor.rbs +12 -1
  76. data/sig/cosmo/stream/message.rbs +3 -1
  77. data/sig/cosmo/stream/processor.rbs +2 -0
  78. data/sig/cosmo/utils/thread_pool.rbs +3 -0
  79. data/sig/cosmo.rbs +4 -0
  80. metadata +33 -20
  81. data/lib/cosmo/api/busy.rb +0 -66
  82. data/sig/cosmo/api/busy.rbs +0 -35
@@ -0,0 +1,28 @@
1
+ module Cosmo
2
+ module Job
3
+ class Failure
4
+ HEADER_LIMIT: Integer
5
+ BACKTRACE_LINES: Integer
6
+ BACKTRACE_SEPARATOR: String
7
+
8
+ @exception: Exception
9
+ @backtrace: ::String?
10
+
11
+ def self.headers: (Exception exception) -> Hash[::String, ::String]
12
+
13
+ def initialize: (Exception exception) -> void
14
+
15
+ def headers: () -> Hash[::String, ::String]
16
+
17
+ private
18
+
19
+ def name: () -> ::String
20
+
21
+ def message: () -> ::String
22
+
23
+ def backtrace: () -> ::String
24
+
25
+ def single_line: (untyped value) -> ::String
26
+ end
27
+ end
28
+ end
@@ -1,13 +1,27 @@
1
1
  module Cosmo
2
2
  module Job
3
3
  class Processor < ::Cosmo::Processor
4
+ DISPATCH_HEADERS: ::Array[::String]
5
+
4
6
  @weights: Array[Symbol]?
5
7
 
8
+ def self.validate_options!: (Hash[Symbol, untyped] options) -> void
9
+
10
+ def subscriptions: () -> Array[::String]
11
+
6
12
  private
7
13
 
8
14
  def setup: () -> void
9
15
 
16
+ def log_subscriptions: () -> void
17
+
18
+ def scheduled_config: () -> Hash[Symbol, untyped]?
19
+
20
+ def consumer_name: (::String | Symbol stream_name) -> ::String
21
+
10
22
  def schedule_loop: () -> void
23
+ def scheduled_by: (untyped message) -> ::String?
24
+ def enqueued_at: (untyped message) -> ::Time
11
25
 
12
26
  def scheduler?: () -> bool
13
27
 
@@ -37,7 +51,9 @@ module Cosmo
37
51
 
38
52
  def drop_message: (untyped message, Hash[Symbol, untyped] data) -> void
39
53
 
40
- def move_message: (untyped message, ?Hash[Symbol, untyped]? data) -> void
54
+ def reject_message: (untyped message, Exception error, ?Hash[Symbol, untyped]? data) -> void
55
+
56
+ def move_message: (untyped message, ?Hash[Symbol, untyped]? data, ?Exception? exception) -> void
41
57
 
42
58
  def with_stats: (untyped message) { () -> untyped } -> void
43
59
 
@@ -0,0 +1,25 @@
1
+ module Cosmo
2
+ module Job
3
+ class StreamFilter
4
+ SCHEDULED: Symbol
5
+ ENV_NAME: ::String
6
+
7
+ @names: Array[::String]
8
+ @configured: Array[::String]?
9
+
10
+ def self.from: (Array[::String]? names) -> StreamFilter
11
+
12
+ def initialize: (Array[::String]? names) -> void
13
+
14
+ def all?: () -> bool
15
+
16
+ def include?: (::String | Symbol stream_name) -> bool
17
+
18
+ def validate!: () -> StreamFilter
19
+
20
+ private
21
+
22
+ def configured: () -> Array[::String]
23
+ end
24
+ end
25
+ end
@@ -3,23 +3,30 @@ module Cosmo
3
3
  STREAM_PAUSED_RECHECK_TTL: ::String
4
4
  STREAMS_PAUSED_IDLE_SLEEP: ::String
5
5
  STREAM_EMPTY_BACKOFF_MAX: ::String
6
+ QUIET_SLEEP: ::String
6
7
 
7
8
  @pool: Utils::ThreadPool
8
9
  @running: untyped
10
+ @quiet: untyped
9
11
  @consumers: Array[untyped]
10
12
  @threads: Array[Thread]
11
13
  @cache: Utils::TTLCache
14
+ @busy: untyped
12
15
  @options: Hash[Symbol, untyped]
13
16
  @consumer_state: untyped
14
17
 
15
18
  def self.run: (*untyped) -> Processor
16
19
 
20
+ def self.validate_options!: (Hash[Symbol, untyped] options) -> void
21
+
17
22
  attr_reader consumers: Array[untyped]
18
23
 
19
- def initialize: (Utils::ThreadPool pool, untyped running, Hash[Symbol, untyped] options) -> void
24
+ def initialize: (Utils::ThreadPool pool, untyped running, Hash[Symbol, untyped] options, quiet: untyped) -> void
20
25
 
21
26
  def run: () -> void
22
27
 
28
+ def busy: () -> Integer
29
+
23
30
  def stop: (?::Integer | ::Float timeout) -> void
24
31
 
25
32
  private
@@ -40,8 +47,12 @@ module Cosmo
40
47
 
41
48
  def fetch_subjects: (Hash[Symbol, untyped] config) -> untyped
42
49
 
50
+ def track_busy: [T] () { () -> T } -> T
51
+
43
52
  def running?: () -> bool
44
53
 
54
+ def quiet?: () -> bool
55
+
45
56
  def fetch: (untyped subscription, batch_size: Integer, timeout: Float) ?{ (Array[untyped]) -> void } -> void
46
57
 
47
58
  def client: () -> Client
@@ -14,7 +14,9 @@ module Cosmo
14
14
 
15
15
  def ack: () -> void
16
16
 
17
- def nack: (?delay: Integer?) -> void
17
+ def nak: (?delay: Integer?) -> void
18
+
19
+ alias nack nak
18
20
 
19
21
  def term: () -> void
20
22
 
@@ -3,6 +3,8 @@ module Cosmo
3
3
  class Processor < ::Cosmo::Processor
4
4
  @configs: Array[Hash[Symbol, untyped]]
5
5
 
6
+ def subscriptions: () -> Array[::String]
7
+
6
8
  private
7
9
 
8
10
  def setup: () -> void
@@ -2,12 +2,15 @@ module Cosmo
2
2
  module Utils
3
3
  class ThreadPool
4
4
  @mutex: Thread::Mutex
5
+ @concurrency: Integer
5
6
  @available: Integer
6
7
  @cond: Thread::ConditionVariable
7
8
  @pool: untyped
8
9
 
9
10
  def initialize: (Integer concurrency) -> void
10
11
 
12
+ def wait_idle: () -> void
13
+
11
14
  def post: () { () -> void } -> void
12
15
 
13
16
  def shutdown: () -> void
data/sig/cosmo.rbs CHANGED
@@ -17,4 +17,8 @@ module Cosmo
17
17
  class StreamNotFoundError < Error
18
18
  def initialize: (::String stream_name) -> void
19
19
  end
20
+
21
+ class UnknownJobStreamError < Error
22
+ def initialize: (Array[::String] names, Array[::String] configured) -> void
23
+ end
20
24
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: cosmonats
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.6.0
4
+ version: 0.7.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Dmitry Vorotilin
@@ -41,30 +41,22 @@ dependencies:
41
41
  name: nats-pure
42
42
  requirement: !ruby/object:Gem::Requirement
43
43
  requirements:
44
- - - "~>"
44
+ - - ">="
45
45
  - !ruby/object:Gem::Version
46
46
  version: '2.5'
47
+ - - "<"
48
+ - !ruby/object:Gem::Version
49
+ version: '2.7'
47
50
  type: :runtime
48
51
  prerelease: false
49
52
  version_requirements: !ruby/object:Gem::Requirement
50
53
  requirements:
51
- - - "~>"
54
+ - - ">="
52
55
  - !ruby/object:Gem::Version
53
56
  version: '2.5'
54
- - !ruby/object:Gem::Dependency
55
- name: rack
56
- requirement: !ruby/object:Gem::Requirement
57
- requirements:
58
- - - "~>"
59
- - !ruby/object:Gem::Version
60
- version: '3.0'
61
- type: :runtime
62
- prerelease: false
63
- version_requirements: !ruby/object:Gem::Requirement
64
- requirements:
65
- - - "~>"
57
+ - - "<"
66
58
  - !ruby/object:Gem::Version
67
- version: '3.0'
59
+ version: '2.7'
68
60
  description: Lightweight background and stream processing for Ruby
69
61
  email:
70
62
  - d.vorotilin@gmail.com
@@ -83,13 +75,16 @@ files:
83
75
  - lib/cosmo/active_job/options.rb
84
76
  - lib/cosmo/api.rb
85
77
  - lib/cosmo/api/batch.rb
86
- - lib/cosmo/api/busy.rb
87
78
  - lib/cosmo/api/counter.rb
88
79
  - lib/cosmo/api/cron.rb
89
80
  - lib/cosmo/api/cron/entry.rb
90
81
  - lib/cosmo/api/job.rb
91
82
  - lib/cosmo/api/kv.rb
83
+ - lib/cosmo/api/registry.rb
92
84
  - lib/cosmo/api/stats.rb
85
+ - lib/cosmo/api/stats/busy.rb
86
+ - lib/cosmo/api/stats/processes.rb
87
+ - lib/cosmo/api/stats/totals.rb
93
88
  - lib/cosmo/api/stream.rb
94
89
  - lib/cosmo/batch.rb
95
90
  - lib/cosmo/batch/callback.rb
@@ -98,10 +93,17 @@ files:
98
93
  - lib/cosmo/client.rb
99
94
  - lib/cosmo/config.rb
100
95
  - lib/cosmo/engine.rb
96
+ - lib/cosmo/heartbeat.rb
97
+ - lib/cosmo/http_server.rb
98
+ - lib/cosmo/http_server/handler.rb
99
+ - lib/cosmo/http_server/health.rb
100
+ - lib/cosmo/http_server/ping.rb
101
101
  - lib/cosmo/job.rb
102
102
  - lib/cosmo/job/data.rb
103
+ - lib/cosmo/job/failure.rb
103
104
  - lib/cosmo/job/limit.rb
104
105
  - lib/cosmo/job/processor.rb
106
+ - lib/cosmo/job/stream_filter.rb
105
107
  - lib/cosmo/logger.rb
106
108
  - lib/cosmo/processor.rb
107
109
  - lib/cosmo/publisher.rb
@@ -145,6 +147,7 @@ files:
145
147
  - lib/cosmo/web/views/jobs/_busy.erb
146
148
  - lib/cosmo/web/views/jobs/_dead.erb
147
149
  - lib/cosmo/web/views/jobs/_enqueued.erb
150
+ - lib/cosmo/web/views/jobs/_processes.erb
148
151
  - lib/cosmo/web/views/jobs/_scheduled.erb
149
152
  - lib/cosmo/web/views/jobs/_stats.erb
150
153
  - lib/cosmo/web/views/jobs/_tabs.erb
@@ -166,13 +169,16 @@ files:
166
169
  - sig/cosmo/active_job/executor.rbs
167
170
  - sig/cosmo/active_job/options.rbs
168
171
  - sig/cosmo/api/batch.rbs
169
- - sig/cosmo/api/busy.rbs
170
172
  - sig/cosmo/api/counter.rbs
171
173
  - sig/cosmo/api/cron.rbs
172
174
  - sig/cosmo/api/cron/entry.rbs
173
175
  - sig/cosmo/api/job.rbs
174
176
  - sig/cosmo/api/kv.rbs
177
+ - sig/cosmo/api/registry.rbs
175
178
  - sig/cosmo/api/stats.rbs
179
+ - sig/cosmo/api/stats/busy.rbs
180
+ - sig/cosmo/api/stats/processes.rbs
181
+ - sig/cosmo/api/stats/totals.rbs
176
182
  - sig/cosmo/api/stream.rbs
177
183
  - sig/cosmo/batch.rbs
178
184
  - sig/cosmo/batch/callback.rbs
@@ -181,10 +187,17 @@ files:
181
187
  - sig/cosmo/client.rbs
182
188
  - sig/cosmo/config.rbs
183
189
  - sig/cosmo/engine.rbs
190
+ - sig/cosmo/heartbeat.rbs
191
+ - sig/cosmo/http_server.rbs
192
+ - sig/cosmo/http_server/handler.rbs
193
+ - sig/cosmo/http_server/health.rbs
194
+ - sig/cosmo/http_server/ping.rbs
184
195
  - sig/cosmo/job.rbs
185
196
  - sig/cosmo/job/data.rbs
197
+ - sig/cosmo/job/failure.rbs
186
198
  - sig/cosmo/job/limit.rbs
187
199
  - sig/cosmo/job/processor.rbs
200
+ - sig/cosmo/job/stream_filter.rbs
188
201
  - sig/cosmo/logger.rbs
189
202
  - sig/cosmo/processor.rbs
190
203
  - sig/cosmo/publisher.rbs
@@ -204,7 +217,7 @@ files:
204
217
  - sig/cosmo/utils/ttl_cache.rbs
205
218
  homepage: https://github.com/bitsbeam/cosmonats
206
219
  licenses:
207
- - LGPL-3.0
220
+ - MIT
208
221
  metadata:
209
222
  homepage_uri: https://github.com/bitsbeam/cosmonats
210
223
  bug_tracker_uri: https://github.com/bitsbeam/cosmonats/issues
@@ -226,7 +239,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
226
239
  - !ruby/object:Gem::Version
227
240
  version: '0'
228
241
  requirements: []
229
- rubygems_version: 4.0.16
242
+ rubygems_version: 4.0.12
230
243
  specification_version: 4
231
244
  summary: Lightweight background and stream processing
232
245
  test_files: []
@@ -1,66 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require "socket"
4
-
5
- module Cosmo
6
- module API
7
- class Busy
8
- TTL = 70
9
- HEARTBEAT = 30
10
- BUCKET = "cosmo_jobs_busy"
11
-
12
- def self.instance
13
- @instance ||= new
14
- end
15
-
16
- def initialize
17
- @messages = {}
18
- @kv = KV.new(BUCKET, { ttl: TTL })
19
- end
20
-
21
- def with(message)
22
- add(message)
23
- yield
24
- ensure
25
- delete(message)
26
- end
27
-
28
- def add(message)
29
- @thread ||= Thread.new { heartbeat_loop }
30
- seq = message.metadata.sequence.stream
31
- value = Utils::Json.dump({ data: message.data, stream: message.metadata.stream, worker: worker_id, started_at: Time.now.to_i })
32
- @messages[seq] = value
33
- @kv.set(seq, value)
34
- end
35
-
36
- def delete(message)
37
- seq = message.metadata.sequence.stream
38
- @messages.delete(seq)
39
- @kv.purge(seq)
40
- end
41
-
42
- def list(limit: 25)
43
- @kv.keys(limit:).filter_map { Utils::Json.parse(@kv.get(_1)&.value) }.map { _1.merge(data: Utils::Json.parse(_1[:data])) }
44
- end
45
-
46
- def size
47
- @kv.size
48
- end
49
-
50
- private
51
-
52
- def heartbeat_loop
53
- loop do
54
- sleep(HEARTBEAT)
55
- @messages.dup.each { |seq, value| @kv.set(seq, value) rescue StandardError }
56
- rescue StandardError => e
57
- Logger.debug "Busy heartbeat error: #{e.class} #{e.message}"
58
- end
59
- end
60
-
61
- def worker_id
62
- @worker_id ||= "#{Socket.gethostname}-#{Process.pid}"
63
- end
64
- end
65
- end
66
- end
@@ -1,35 +0,0 @@
1
- module Cosmo
2
- module API
3
- class Busy
4
- TTL: ::Integer
5
- HEARTBEAT: ::Integer
6
- BUCKET: ::String
7
-
8
- self.@instance: Busy
9
- @messages: Hash[::Integer, ::String]
10
- @kv: KV
11
- @thread: Thread?
12
- @worker_id: ::String
13
-
14
- def self.instance: () -> Busy
15
-
16
- def initialize: () -> void
17
-
18
- def with: (untyped message) { () -> void } -> void
19
-
20
- def add: (untyped message) -> void
21
-
22
- def delete: (untyped message) -> void
23
-
24
- def list: (?limit: ::Integer) -> Array[Hash[Symbol, untyped]]
25
-
26
- def size: () -> ::Integer
27
-
28
- private
29
-
30
- def heartbeat_loop: () -> void
31
-
32
- def worker_id: () -> ::String
33
- end
34
- end
35
- end