chronos-ruby 0.2.0.pre.1 → 0.3.0.pre.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/CHANGELOG.md +25 -0
- data/README.md +35 -18
- data/docs/adr/ADR-005-sanitize-before-backlog.md +2 -2
- data/docs/adr/ADR-011-bounded-resilience-and-remote-control.md +27 -0
- data/docs/architecture.md +5 -4
- data/docs/compatibility.md +6 -6
- data/docs/configuration.md +17 -0
- data/docs/data-collected.md +2 -2
- data/docs/examples/plain-ruby.md +6 -0
- data/docs/modules/async-queue.md +6 -2
- data/docs/modules/notice-pipeline.md +2 -1
- data/docs/modules/remote-configuration.md +54 -0
- data/docs/modules/retry-backlog.md +60 -0
- data/docs/modules/transport.md +5 -3
- data/docs/performance.md +27 -2
- data/docs/privacy-lgpd.md +4 -2
- data/docs/troubleshooting.md +1 -1
- data/lib/chronos/adapters/net_http_transport.rb +21 -3
- data/lib/chronos/agent.rb +16 -8
- data/lib/chronos/application/capture_exception.rb +20 -14
- data/lib/chronos/application/circuit_breaker.rb +70 -0
- data/lib/chronos/application/delivery_pipeline.rb +248 -0
- data/lib/chronos/application/remote_configuration.rb +173 -0
- data/lib/chronos/application/retry_policy.rb +57 -0
- data/lib/chronos/configuration.rb +101 -19
- data/lib/chronos/core/payload_serializer.rb +4 -2
- data/lib/chronos/internal/bounded_queue.rb +1 -1
- data/lib/chronos/internal/memory_backlog.rb +65 -0
- data/lib/chronos/internal/worker_pool.rb +5 -6
- data/lib/chronos/ports/transport.rb +4 -3
- data/lib/chronos/version.rb +1 -1
- data/lib/chronos.rb +6 -1
- metadata +9 -1
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
require "time"
|
|
2
|
+
|
|
3
|
+
module Chronos
|
|
4
|
+
module Application
|
|
5
|
+
# Bounded retry timing policy with exponential backoff and jitter.
|
|
6
|
+
#
|
|
7
|
+
# @responsibility Decide whether and when a retry may occur.
|
|
8
|
+
# @motivation Centralize retry limits independently from HTTP and worker code.
|
|
9
|
+
# @limits It does not sleep, send events, or retain payloads.
|
|
10
|
+
# @collaborators TransportResult and DeliveryPipeline.
|
|
11
|
+
# @thread_safety Immutable after construction when the random callable is thread-safe.
|
|
12
|
+
# @compatibility Ruby 2.2.10 through Ruby 2.6.
|
|
13
|
+
# @example
|
|
14
|
+
# policy.delay(2, result)
|
|
15
|
+
# @errors Invalid configuration is rejected by Configuration.
|
|
16
|
+
# @performance Constant time per decision.
|
|
17
|
+
class RetryPolicy
|
|
18
|
+
def initialize(options)
|
|
19
|
+
@max_retries = options[:max_retries]
|
|
20
|
+
@base_interval = options[:base_interval]
|
|
21
|
+
@max_interval = options[:max_interval]
|
|
22
|
+
@jitter = options[:jitter]
|
|
23
|
+
@random = options[:random] || proc { rand }
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def retry?(result, retries)
|
|
27
|
+
result.retryable? && retries < @max_retries
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def delay(retry_number, result = nil)
|
|
31
|
+
retry_after = retry_after_seconds(result)
|
|
32
|
+
return [retry_after, @max_interval].min if retry_after
|
|
33
|
+
|
|
34
|
+
base = @base_interval * (2**(retry_number - 1))
|
|
35
|
+
jittered = base * (1.0 + (@random.call.to_f * @jitter))
|
|
36
|
+
[jittered, @max_interval].min
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
private
|
|
40
|
+
|
|
41
|
+
def retry_after_seconds(result)
|
|
42
|
+
return nil unless result && result.retry_after
|
|
43
|
+
|
|
44
|
+
value = result.retry_after.to_s
|
|
45
|
+
seconds = Float(value)
|
|
46
|
+
seconds >= 0 ? seconds : nil
|
|
47
|
+
rescue ArgumentError, TypeError
|
|
48
|
+
begin
|
|
49
|
+
seconds = Time.httpdate(value) - Time.now
|
|
50
|
+
seconds > 0 ? seconds : nil
|
|
51
|
+
rescue ArgumentError
|
|
52
|
+
nil
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
end
|
|
@@ -31,12 +31,52 @@ module Chronos
|
|
|
31
31
|
:queue_size, :workers, :enabled, :error_notifications,
|
|
32
32
|
:ignored_environments, :proxy, :ssl_verify, :user_agent,
|
|
33
33
|
:max_payload_size, :gzip, :blocklist_keys, :allowlist_keys,
|
|
34
|
-
:filters, :hash_keys, :anonymize_ip
|
|
34
|
+
:filters, :hash_keys, :anonymize_ip, :max_retries,
|
|
35
|
+
:retry_base_interval, :retry_max_interval, :retry_jitter,
|
|
36
|
+
:backlog_size, :circuit_failure_threshold, :circuit_reset_timeout,
|
|
37
|
+
:remote_configuration, :remote_config_max_bytes, :sampling_rate,
|
|
38
|
+
:enabled_event_types, :max_remote_send_interval
|
|
35
39
|
].freeze
|
|
36
40
|
|
|
37
41
|
attr_accessor(*ATTRIBUTES)
|
|
38
42
|
|
|
39
43
|
def initialize
|
|
44
|
+
initialize_core_defaults
|
|
45
|
+
initialize_privacy_defaults
|
|
46
|
+
initialize_resilience_defaults
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
def snapshot
|
|
50
|
+
errors = validation_errors
|
|
51
|
+
raise ConfigurationError, errors.join(", ") unless errors.empty?
|
|
52
|
+
|
|
53
|
+
Snapshot.new(to_hash)
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
def valid?
|
|
57
|
+
validation_errors.empty?
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
def validation_errors
|
|
61
|
+
errors = []
|
|
62
|
+
if enabled
|
|
63
|
+
errors << "project_id is required" if blank?(project_id)
|
|
64
|
+
errors << "project_key is required" if blank?(project_key)
|
|
65
|
+
errors.concat(host_errors)
|
|
66
|
+
end
|
|
67
|
+
errors << "timeout must be greater than zero" unless positive_number?(timeout)
|
|
68
|
+
errors << "open_timeout must be greater than zero" unless positive_number?(open_timeout)
|
|
69
|
+
errors << "queue_size must be a positive integer" unless positive_integer?(queue_size)
|
|
70
|
+
errors << "workers must be a positive integer" unless positive_integer?(workers)
|
|
71
|
+
errors << "max_payload_size must be a positive integer" unless positive_integer?(max_payload_size)
|
|
72
|
+
errors.concat(resilience_errors)
|
|
73
|
+
errors.concat(privacy_errors)
|
|
74
|
+
errors
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
private
|
|
78
|
+
|
|
79
|
+
def initialize_core_defaults
|
|
40
80
|
@project_id = nil
|
|
41
81
|
@project_key = nil
|
|
42
82
|
@host = nil
|
|
@@ -57,6 +97,9 @@ module Chronos
|
|
|
57
97
|
@user_agent = "chronos-ruby/#{Chronos::VERSION}"
|
|
58
98
|
@max_payload_size = 1_048_576
|
|
59
99
|
@gzip = false
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
def initialize_privacy_defaults
|
|
60
103
|
@blocklist_keys = DEFAULT_BLOCKLIST_KEYS.dup
|
|
61
104
|
@allowlist_keys = []
|
|
62
105
|
@filters = []
|
|
@@ -64,34 +107,65 @@ module Chronos
|
|
|
64
107
|
@anonymize_ip = true
|
|
65
108
|
end
|
|
66
109
|
|
|
67
|
-
def
|
|
68
|
-
|
|
69
|
-
|
|
110
|
+
def initialize_resilience_defaults
|
|
111
|
+
@max_retries = 3
|
|
112
|
+
@retry_base_interval = 0.5
|
|
113
|
+
@retry_max_interval = 30.0
|
|
114
|
+
@retry_jitter = 0.25
|
|
115
|
+
@backlog_size = 100
|
|
116
|
+
@circuit_failure_threshold = 5
|
|
117
|
+
@circuit_reset_timeout = 30.0
|
|
118
|
+
@remote_configuration = true
|
|
119
|
+
@remote_config_max_bytes = 4096
|
|
120
|
+
@sampling_rate = 1.0
|
|
121
|
+
@enabled_event_types = ["exception"]
|
|
122
|
+
@max_remote_send_interval = 60.0
|
|
123
|
+
end
|
|
70
124
|
|
|
71
|
-
|
|
125
|
+
def resilience_errors
|
|
126
|
+
errors = []
|
|
127
|
+
errors.concat(retry_errors)
|
|
128
|
+
errors.concat(backlog_and_circuit_errors)
|
|
129
|
+
errors.concat(remote_policy_errors)
|
|
130
|
+
errors
|
|
72
131
|
end
|
|
73
132
|
|
|
74
|
-
def
|
|
75
|
-
|
|
133
|
+
def retry_errors
|
|
134
|
+
errors = []
|
|
135
|
+
errors << "max_retries must be a non-negative integer" unless non_negative_integer?(max_retries)
|
|
136
|
+
errors << "retry_base_interval must be greater than zero" unless positive_number?(retry_base_interval)
|
|
137
|
+
errors << "retry_max_interval must be greater than zero" unless positive_number?(retry_max_interval)
|
|
138
|
+
if positive_number?(retry_base_interval) && positive_number?(retry_max_interval) &&
|
|
139
|
+
retry_max_interval < retry_base_interval
|
|
140
|
+
errors << "retry_max_interval must be greater than or equal to retry_base_interval"
|
|
141
|
+
end
|
|
142
|
+
errors << "retry_jitter must be between zero and one" unless rate?(retry_jitter)
|
|
143
|
+
errors
|
|
76
144
|
end
|
|
77
145
|
|
|
78
|
-
def
|
|
146
|
+
def backlog_and_circuit_errors
|
|
79
147
|
errors = []
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
errors << "
|
|
83
|
-
errors.concat(host_errors)
|
|
148
|
+
errors << "backlog_size must be a non-negative integer" unless non_negative_integer?(backlog_size)
|
|
149
|
+
unless positive_integer?(circuit_failure_threshold)
|
|
150
|
+
errors << "circuit_failure_threshold must be a positive integer"
|
|
84
151
|
end
|
|
85
|
-
errors << "
|
|
86
|
-
errors << "open_timeout must be greater than zero" unless positive_number?(open_timeout)
|
|
87
|
-
errors << "queue_size must be a positive integer" unless positive_integer?(queue_size)
|
|
88
|
-
errors << "workers must be a positive integer" unless positive_integer?(workers)
|
|
89
|
-
errors << "max_payload_size must be a positive integer" unless positive_integer?(max_payload_size)
|
|
90
|
-
errors.concat(privacy_errors)
|
|
152
|
+
errors << "circuit_reset_timeout must be greater than zero" unless positive_number?(circuit_reset_timeout)
|
|
91
153
|
errors
|
|
92
154
|
end
|
|
93
155
|
|
|
94
|
-
|
|
156
|
+
def remote_policy_errors
|
|
157
|
+
errors = []
|
|
158
|
+
unless [true, false].include?(remote_configuration)
|
|
159
|
+
errors << "remote_configuration must be true or false"
|
|
160
|
+
end
|
|
161
|
+
errors << "remote_config_max_bytes must be a positive integer" unless positive_integer?(remote_config_max_bytes)
|
|
162
|
+
errors << "sampling_rate must be between zero and one" unless rate?(sampling_rate)
|
|
163
|
+
unless enabled_event_types.is_a?(Array) && enabled_event_types.all? { |value| value.is_a?(String) }
|
|
164
|
+
errors << "enabled_event_types must contain only String values"
|
|
165
|
+
end
|
|
166
|
+
errors << "max_remote_send_interval must be greater than zero" unless positive_number?(max_remote_send_interval)
|
|
167
|
+
errors
|
|
168
|
+
end
|
|
95
169
|
|
|
96
170
|
def to_hash
|
|
97
171
|
ATTRIBUTES.each_with_object({}) do |attribute, values|
|
|
@@ -170,6 +244,14 @@ module Chronos
|
|
|
170
244
|
value.is_a?(Integer) && value > 0
|
|
171
245
|
end
|
|
172
246
|
|
|
247
|
+
def non_negative_integer?(value)
|
|
248
|
+
value.is_a?(Integer) && value >= 0
|
|
249
|
+
end
|
|
250
|
+
|
|
251
|
+
def rate?(value)
|
|
252
|
+
value.is_a?(Numeric) && value >= 0.0 && value <= 1.0
|
|
253
|
+
end
|
|
254
|
+
|
|
173
255
|
# Immutable configuration shared by all runtime components.
|
|
174
256
|
#
|
|
175
257
|
# @responsibility Expose validated settings without mutable containers.
|
|
@@ -43,13 +43,15 @@ module Chronos
|
|
|
43
43
|
@clock = clock || proc { Time.now }
|
|
44
44
|
@sanitizer = options[:sanitizer] || Sanitizer.new(config)
|
|
45
45
|
@safe_serializer = options[:safe_serializer] || SafeSerializer.new
|
|
46
|
+
@max_payload_size = options[:max_payload_size] || proc { @config.max_payload_size }
|
|
46
47
|
end
|
|
47
48
|
|
|
48
49
|
def call(notice)
|
|
49
50
|
envelope = @safe_serializer.call(@sanitizer.call(build_envelope(notice)))
|
|
50
51
|
body = JSON.generate(envelope)
|
|
51
|
-
|
|
52
|
-
|
|
52
|
+
limit = @max_payload_size.call
|
|
53
|
+
body = JSON.generate(compact_envelope(envelope)) if body.bytesize > limit
|
|
54
|
+
raise Error, "event exceeds max_payload_size" if body.bytesize > limit
|
|
53
55
|
|
|
54
56
|
SerializedEvent.new(notice.event_id, body)
|
|
55
57
|
end
|
|
@@ -4,7 +4,7 @@ module Chronos
|
|
|
4
4
|
#
|
|
5
5
|
# @responsibility Accept events up to a limit and count accepted and dropped items.
|
|
6
6
|
# @motivation Prevent telemetry bursts from growing application memory indefinitely.
|
|
7
|
-
# @limits Version 0.
|
|
7
|
+
# @limits Version 0.3 drops the newest item when full and does not persist to disk.
|
|
8
8
|
# @collaborators WorkerPool.
|
|
9
9
|
# @thread_safety Mutex and condition variable protect all mutable state.
|
|
10
10
|
# @compatibility Ruby 2.2.10 through Ruby 2.6 and fork-aware callers.
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
module Chronos
|
|
2
|
+
module Internal
|
|
3
|
+
# Fixed-capacity retry storage for sanitized serialized events.
|
|
4
|
+
#
|
|
5
|
+
# @responsibility Retain failed deliveries in memory without unbounded growth.
|
|
6
|
+
# @motivation Allow later recovery while preserving the host application's memory limit.
|
|
7
|
+
# @limits It never writes to disk and accepts only SerializedEvent instances.
|
|
8
|
+
# @collaborators DeliveryPipeline and SerializedEvent.
|
|
9
|
+
# @thread_safety A mutex protects storage and counters.
|
|
10
|
+
# @compatibility Ruby 2.2.10 through Ruby 2.6.
|
|
11
|
+
# @example
|
|
12
|
+
# backlog.push(serialized_event)
|
|
13
|
+
# @errors Invalid event types raise before entering storage.
|
|
14
|
+
# @performance Push and shift are bounded by the configured capacity.
|
|
15
|
+
class MemoryBacklog
|
|
16
|
+
attr_reader :capacity
|
|
17
|
+
|
|
18
|
+
def initialize(capacity)
|
|
19
|
+
unless capacity.is_a?(Integer) && capacity >= 0
|
|
20
|
+
raise ArgumentError, "capacity must be a non-negative integer"
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
@capacity = capacity
|
|
24
|
+
@items = []
|
|
25
|
+
@accepted = 0
|
|
26
|
+
@dropped = 0
|
|
27
|
+
@mutex = Mutex.new
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def push(event)
|
|
31
|
+
unless event.is_a?(Core::SerializedEvent)
|
|
32
|
+
raise ArgumentError, "backlog accepts only sanitized serialized events"
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
@mutex.synchronize do
|
|
36
|
+
if @items.length >= capacity
|
|
37
|
+
@dropped += 1
|
|
38
|
+
return false
|
|
39
|
+
end
|
|
40
|
+
@items << event
|
|
41
|
+
@accepted += 1
|
|
42
|
+
true
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
def shift
|
|
47
|
+
@mutex.synchronize { @items.shift }
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
def size
|
|
51
|
+
@mutex.synchronize { @items.size }
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
def empty?
|
|
55
|
+
size.zero?
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
def stats
|
|
59
|
+
@mutex.synchronize do
|
|
60
|
+
{:size => @items.size, :capacity => capacity, :accepted => @accepted, :dropped => @dropped}
|
|
61
|
+
end
|
|
62
|
+
end
|
|
63
|
+
end
|
|
64
|
+
end
|
|
65
|
+
end
|
|
@@ -4,8 +4,8 @@ module Chronos
|
|
|
4
4
|
#
|
|
5
5
|
# @responsibility Start workers on first use, deliver events, flush, and shut down predictably.
|
|
6
6
|
# @motivation Keep serialization and network delivery outside the caller's critical path.
|
|
7
|
-
# @limits
|
|
8
|
-
# @collaborators BoundedQueue,
|
|
7
|
+
# @limits Retry policy belongs to the delivery collaborator.
|
|
8
|
+
# @collaborators BoundedQueue, DeliveryPipeline, and SafeLogger.
|
|
9
9
|
# @thread_safety Internal state is synchronized and active delivery is counted.
|
|
10
10
|
# @compatibility Ruby 2.2.10 through Ruby 2.6; workers are recreated after fork.
|
|
11
11
|
# @example
|
|
@@ -16,9 +16,9 @@ module Chronos
|
|
|
16
16
|
class WorkerPool
|
|
17
17
|
POLL_INTERVAL = 0.05
|
|
18
18
|
|
|
19
|
-
def initialize(queue,
|
|
19
|
+
def initialize(queue, delivery, worker_count, logger = nil)
|
|
20
20
|
@queue = queue
|
|
21
|
-
@
|
|
21
|
+
@delivery = delivery
|
|
22
22
|
@worker_count = worker_count
|
|
23
23
|
@logger = logger || SafeLogger.new(nil)
|
|
24
24
|
@mutex = Mutex.new
|
|
@@ -59,7 +59,6 @@ module Chronos
|
|
|
59
59
|
flushed = flush_without_reopening(timeout)
|
|
60
60
|
@queue.close
|
|
61
61
|
join_workers(timeout)
|
|
62
|
-
@transport.close
|
|
63
62
|
flushed
|
|
64
63
|
rescue StandardError => error
|
|
65
64
|
@logger.warn("Chronos worker shutdown failed: #{error.class}")
|
|
@@ -87,7 +86,7 @@ module Chronos
|
|
|
87
86
|
|
|
88
87
|
increment_active
|
|
89
88
|
begin
|
|
90
|
-
@
|
|
89
|
+
@delivery.send_event(event)
|
|
91
90
|
rescue StandardError => error
|
|
92
91
|
@logger.warn("Chronos worker contained #{error.class}")
|
|
93
92
|
ensure
|
|
@@ -4,17 +4,18 @@ module Chronos
|
|
|
4
4
|
#
|
|
5
5
|
# @responsibility Describe delivery outcome and retry classification.
|
|
6
6
|
# @motivation Keep HTTP implementation details outside the application layer.
|
|
7
|
-
# @limits It does not schedule retries
|
|
7
|
+
# @limits It classifies outcomes but does not schedule retries.
|
|
8
8
|
# @thread_safety Immutable after construction.
|
|
9
9
|
# @compatibility Ruby 2.2.10 through Ruby 2.6.
|
|
10
10
|
class TransportResult
|
|
11
|
-
attr_reader :status, :status_code, :retry_after, :error
|
|
11
|
+
attr_reader :status, :status_code, :retry_after, :error, :remote_configuration
|
|
12
12
|
|
|
13
13
|
def initialize(status, options = {})
|
|
14
14
|
@status = status
|
|
15
15
|
@status_code = options[:status_code]
|
|
16
16
|
@retry_after = options[:retry_after]
|
|
17
17
|
@error = options[:error]
|
|
18
|
+
@remote_configuration = options[:remote_configuration]
|
|
18
19
|
freeze
|
|
19
20
|
end
|
|
20
21
|
|
|
@@ -23,7 +24,7 @@ module Chronos
|
|
|
23
24
|
end
|
|
24
25
|
|
|
25
26
|
def retryable?
|
|
26
|
-
[:rate_limited, :server_error, :network_error].include?(status)
|
|
27
|
+
[:request_timeout, :rate_limited, :server_error, :network_error].include?(status)
|
|
27
28
|
end
|
|
28
29
|
end
|
|
29
30
|
|
data/lib/chronos/version.rb
CHANGED
data/lib/chronos.rb
CHANGED
|
@@ -18,8 +18,13 @@ require "chronos/core/payload_serializer"
|
|
|
18
18
|
require "chronos/ports/transport"
|
|
19
19
|
require "chronos/internal/safe_logger"
|
|
20
20
|
require "chronos/internal/bounded_queue"
|
|
21
|
+
require "chronos/internal/memory_backlog"
|
|
21
22
|
require "chronos/internal/worker_pool"
|
|
22
23
|
require "chronos/adapters/net_http_transport"
|
|
24
|
+
require "chronos/application/retry_policy"
|
|
25
|
+
require "chronos/application/circuit_breaker"
|
|
26
|
+
require "chronos/application/remote_configuration"
|
|
27
|
+
require "chronos/application/delivery_pipeline"
|
|
23
28
|
require "chronos/application/capture_exception"
|
|
24
29
|
require "chronos/agent"
|
|
25
30
|
|
|
@@ -27,7 +32,7 @@ require "chronos/agent"
|
|
|
27
32
|
#
|
|
28
33
|
# @responsibility Configure the agent and expose its small lifecycle API.
|
|
29
34
|
# @motivation Give applications a stable entry point while internals evolve.
|
|
30
|
-
# @limits Version 0.
|
|
35
|
+
# @limits Version 0.3 captures Ruby exceptions manually; integrations arrive later.
|
|
31
36
|
# @collaborators Configuration and Agent.
|
|
32
37
|
# @thread_safety Agent replacement and lookup are protected by a mutex.
|
|
33
38
|
# @compatibility Ruby 2.2.10 through Ruby 2.6.
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: chronos-ruby
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.3.0.pre.1
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Antonio Jefferson
|
|
@@ -93,6 +93,7 @@ files:
|
|
|
93
93
|
- docs/adr/ADR-004-bounded-queue.md
|
|
94
94
|
- docs/adr/ADR-005-sanitize-before-backlog.md
|
|
95
95
|
- docs/adr/ADR-006-versioned-event-contract.md
|
|
96
|
+
- docs/adr/ADR-011-bounded-resilience-and-remote-control.md
|
|
96
97
|
- docs/architecture.md
|
|
97
98
|
- docs/compatibility.md
|
|
98
99
|
- docs/configuration.md
|
|
@@ -101,6 +102,8 @@ files:
|
|
|
101
102
|
- docs/modules/async-queue.md
|
|
102
103
|
- docs/modules/configuration.md
|
|
103
104
|
- docs/modules/notice-pipeline.md
|
|
105
|
+
- docs/modules/remote-configuration.md
|
|
106
|
+
- docs/modules/retry-backlog.md
|
|
104
107
|
- docs/modules/sanitization.md
|
|
105
108
|
- docs/modules/serialization.md
|
|
106
109
|
- docs/modules/transport.md
|
|
@@ -113,6 +116,10 @@ files:
|
|
|
113
116
|
- lib/chronos/agent.rb
|
|
114
117
|
- lib/chronos/application.rb
|
|
115
118
|
- lib/chronos/application/capture_exception.rb
|
|
119
|
+
- lib/chronos/application/circuit_breaker.rb
|
|
120
|
+
- lib/chronos/application/delivery_pipeline.rb
|
|
121
|
+
- lib/chronos/application/remote_configuration.rb
|
|
122
|
+
- lib/chronos/application/retry_policy.rb
|
|
116
123
|
- lib/chronos/configuration.rb
|
|
117
124
|
- lib/chronos/core.rb
|
|
118
125
|
- lib/chronos/core/backtrace_parser.rb
|
|
@@ -127,6 +134,7 @@ files:
|
|
|
127
134
|
- lib/chronos/errors.rb
|
|
128
135
|
- lib/chronos/internal.rb
|
|
129
136
|
- lib/chronos/internal/bounded_queue.rb
|
|
137
|
+
- lib/chronos/internal/memory_backlog.rb
|
|
130
138
|
- lib/chronos/internal/safe_logger.rb
|
|
131
139
|
- lib/chronos/internal/worker_pool.rb
|
|
132
140
|
- lib/chronos/ports.rb
|