cosmonats 0.1.3 → 0.1.4

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: 9c5a169718d8f3ddb85e2fcc95a5e1b6c0fd3061c1ad4410bd7bad85add934c6
4
- data.tar.gz: aa9715564bdbead26f876ff9de8c9119084015fb3e0d52e2ec6b126c3d3ad0a0
3
+ metadata.gz: c001e33a420b73f46eebfe6ecffca697ef7d67f0436a2b70a88ed6207b3846a5
4
+ data.tar.gz: 2fd541b16a24b5a461ea60078be20d92a0c815d0a09996fc9e419f958fce31ea
5
5
  SHA512:
6
- metadata.gz: 41bf7cc2664b566e0f70f9b4045a921abe7afc0e0cd33897f46dd975d4148aead93eaf7faeaffd7364268acee1713b08daeb151c7b124412de2983970787f97b
7
- data.tar.gz: 761a89e2379601c71b75e6c13f63e0c7c0dda9fa7f5631aa6b0f8bab7493f3fe29bee1e562677be8f22ac45b1597f4a0f34660b91e999a7eceb7367d0db50d33
6
+ metadata.gz: b401aaac7b86f8d08167d256814bed8cd8332aa1f9d82e97548f89d5f3770f95d90a8c36dc711eb0798fbc21ec654d21f629879e3fb56e8d3ecc4c943411be24
7
+ data.tar.gz: 8ff68d161c0f1f15dabddab8e36ad37363456126c5332bdfe636620e68c91510d690048585fa2064538e77ef3be6c1f892be4f57878de844d9f32d4a46815da3
data/lib/cosmo/client.rb CHANGED
@@ -11,7 +11,9 @@ module Cosmo
11
11
  attr_reader :nc, :js
12
12
 
13
13
  def initialize(nats_url: ENV.fetch("NATS_URL", "nats://localhost:4222"))
14
+ Logger.debug "Connecting to NATS server at #{nats_url}..."
14
15
  @nc = NATS.connect(nats_url)
16
+ Logger.debug "Connection established"
15
17
  @js = @nc.jetstream
16
18
  end
17
19
 
@@ -28,7 +28,11 @@ module Cosmo
28
28
  end
29
29
 
30
30
  def work_loop # rubocop:disable Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity, Metrics/MethodLength, Metrics/AbcSize
31
+ shutdown = false
32
+
31
33
  while running?
34
+ break if shutdown
35
+
32
36
  @weights.shuffle.each do |stream_name|
33
37
  break unless running?
34
38
 
@@ -36,10 +40,11 @@ module Cosmo
36
40
  timeout = ENV.fetch("COSMO_JOBS_FETCH_TIMEOUT", 0.1).to_f
37
41
  @pool.post do
38
42
  subscription = @consumers.find { |(_, sn)| sn == stream_name }&.first
39
- messages = fetch_messages(subscription, batch_size: 1, timeout:)
43
+ messages = fetch(subscription, batch_size: 1, timeout:)
40
44
  process(messages) if messages&.any?
41
45
  end
42
46
  rescue Concurrent::RejectedExecutionError
47
+ shutdown = true
43
48
  break # pool doesn't accept new jobs, we are shutting down
44
49
  end
45
50
 
@@ -55,7 +60,7 @@ module Cosmo
55
60
  now = Time.now.to_i
56
61
  timeout = ENV.fetch("COSMO_JOBS_SCHEDULER_FETCH_TIMEOUT", 5).to_f
57
62
  subscription = @consumers.find { |(_, sn)| sn == :scheduled }&.first
58
- messages = fetch_messages(subscription, batch_size: 100, timeout:)
63
+ messages = fetch(subscription, batch_size: 100, timeout:)
59
64
  messages&.each do |message|
60
65
  headers = message.header.except("X-Stream", "X-Subject", "X-Execute-At", "Nats-Expected-Stream")
61
66
  stream, subject, execute_at = message.header.values_at("X-Stream", "X-Subject", "X-Execute-At")
@@ -39,10 +39,16 @@ module Cosmo
39
39
  @running.true?
40
40
  end
41
41
 
42
- def fetch_messages(subscription, batch_size:, timeout:)
42
+ def fetch(subscription, batch_size:, timeout:)
43
43
  subscription.fetch(batch_size, timeout:)
44
44
  rescue NATS::Timeout
45
45
  # No messages, continue
46
+ rescue StandardError => e
47
+ Logger.error "Snap! Error just happened"
48
+ Logger.error "#{e.class}: #{e.message}"
49
+
50
+ backoff = ENV.fetch("COSMO_STREAMS_FETCH_BACKOFF", 5).to_f
51
+ sleep([timeout, backoff].max) # backoff before retry
46
52
  end
47
53
 
48
54
  def client
@@ -7,6 +7,7 @@ module Cosmo
7
7
  class Data
8
8
  DEFAULTS = {
9
9
  batch_size: 100,
10
+ fetch_timeout: 10.0,
10
11
  consumer: {
11
12
  ack_policy: "explicit",
12
13
  max_deliver: 1,
@@ -19,21 +19,26 @@ module Cosmo
19
19
  setup_consumers
20
20
  end
21
21
 
22
- def work_loop # rubocop:disable Metrics/AbcSize, Metrics/MethodLength, Metrics/CyclomaticComplexity
22
+ def work_loop # rubocop:disable Metrics/AbcSize, Metrics/MethodLength, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
23
+ shutdown = false
24
+
23
25
  while running?
26
+ break if shutdown
27
+
24
28
  @consumers.each do |(subscription, config, processor)|
25
29
  break unless running?
26
30
 
27
31
  begin
28
- timeout = ENV.fetch("COSMO_STREAMS_FETCH_TIMEOUT", 0.1).to_f
29
32
  @pool.post do
33
+ timeout = convert_timeout(config[:fetch_timeout])
30
34
  Logger.debug "fetching #{config.dig(:consumer, :subjects).inspect}, timeout=#{timeout}"
31
- messages = fetch_messages(subscription, batch_size: config[:batch_size], timeout:)
35
+ messages = fetch(subscription, batch_size: config[:batch_size], timeout:)
32
36
  Logger.debug "fetched (#{messages&.size.to_i}) messages"
33
37
  process(messages, processor) if messages&.any?
34
38
  Logger.debug "processed (#{messages&.size.to_i}) messages"
35
39
  end
36
40
  rescue Concurrent::RejectedExecutionError
41
+ shutdown = true
37
42
  break # pool doesn't accept new jobs, we are shutting down
38
43
  end
39
44
 
@@ -95,6 +100,16 @@ module Cosmo
95
100
  def dynamic_config
96
101
  Config.system[:streams].map { _1.default_options.merge(class: _1) }
97
102
  end
103
+
104
+ def convert_timeout(value)
105
+ timeout = value.to_f
106
+ if timeout <= 0
107
+ Logger.warn "Ignoring `fetch_timeout: #{timeout}` (causes high CPU usage) with #{Data::DEFAULTS[:fetch_timeout]}s instead"
108
+ timeout = Data::DEFAULTS[:fetch_timeout].to_f
109
+ end
110
+
111
+ timeout
112
+ end
98
113
  end
99
114
  end
100
115
  end
data/lib/cosmo/stream.rb CHANGED
@@ -12,9 +12,9 @@ module Cosmo
12
12
  end
13
13
 
14
14
  module ClassMethods
15
- def options(stream: nil, consumer_name: nil, batch_size: nil, start_position: nil, consumer: nil, publisher: nil) # rubocop:disable Metrics/ParameterLists
15
+ def options(stream: nil, consumer_name: nil, batch_size: nil, fetch_timeout: nil, start_position: nil, consumer: nil, publisher: nil) # rubocop:disable Metrics/ParameterLists
16
16
  register
17
- default_options.merge!({ stream:, consumer_name:, batch_size:, start_position:, consumer:, publisher: }.compact)
17
+ default_options.merge!({ stream:, consumer_name:, batch_size:, fetch_timeout:, start_position:, consumer:, publisher: }.compact)
18
18
  end
19
19
 
20
20
  def publish(data, subject: nil, **options)
data/lib/cosmo/version.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Cosmo
4
- VERSION = "0.1.3"
4
+ VERSION = "0.1.4"
5
5
  end
@@ -21,7 +21,7 @@ module Cosmo
21
21
 
22
22
  def running?: () -> bool
23
23
 
24
- def fetch_messages: (untyped subscription, batch_size: Integer, timeout: Float) ?{ (Array[untyped]) -> void } -> void
24
+ def fetch: (untyped subscription, batch_size: Integer, timeout: Float) ?{ (Array[untyped]) -> void } -> void
25
25
 
26
26
  def client: () -> Client
27
27
 
@@ -1,7 +1,7 @@
1
1
  module Cosmo
2
2
  module Stream
3
3
  class Data
4
- DEFAULTS: Hash[Symbol, Integer | Hash[Symbol, untyped]]
4
+ DEFAULTS: Hash[Symbol, Numeric | Hash[Symbol, untyped]]
5
5
  end
6
6
  end
7
7
  end
@@ -11,6 +11,8 @@ module Cosmo
11
11
 
12
12
  def setup: () -> void
13
13
 
14
+ def convert_timeout: (Numeric) -> Float
15
+
14
16
  def work_loop: () -> void
15
17
 
16
18
  def process: (Array[untyped] messages, untyped processor) -> void
data/sig/cosmo/stream.rbs CHANGED
@@ -9,6 +9,7 @@ module Cosmo
9
9
  ?stream: Symbol?,
10
10
  ?consumer_name: ::String?,
11
11
  ?batch_size: Integer?,
12
+ ?fetch_timeout: (Integer | Float)?,
12
13
  ?start_position: (Symbol | ::String | Time)?,
13
14
  ?consumer: Hash[Symbol, untyped]?,
14
15
  ?publisher: Hash[Symbol, untyped]?
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.1.3
4
+ version: 0.1.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - Dmitry Vorotilin
@@ -82,11 +82,11 @@ files:
82
82
  - sig/cosmo/job/data.rbs
83
83
  - sig/cosmo/job/processor.rbs
84
84
  - sig/cosmo/logger.rbs
85
- - sig/cosmo/message.rbs
86
85
  - sig/cosmo/processor.rbs
87
86
  - sig/cosmo/publisher.rbs
88
87
  - sig/cosmo/stream.rbs
89
88
  - sig/cosmo/stream/data.rbs
89
+ - sig/cosmo/stream/message.rbs
90
90
  - sig/cosmo/stream/processor.rbs
91
91
  - sig/cosmo/stream/serializer.rbs
92
92
  - sig/cosmo/utils/hash.rbs
File without changes