journaled 6.2.4 → 6.2.5
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:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: ccf34c7b5e32419b7b42919fc2325a8132655ade454e437523f55588b92ea901
|
|
4
|
+
data.tar.gz: 788f394e0c7ecdab76e5cb862d21add0d4a96d3ac2d766eead458159f511d842
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: fc9c29ef11509f18647b4c90f3890f0da76318d5163ac378f561d08e38a61dec729dfdb768c2c1c2d7846d7d53b32ff4d06ae2389ceef41b19f5fc111d3d6bcf
|
|
7
|
+
data.tar.gz: f91ef462e9d89d492f083a546b6106c328baf3ade91e7ac88a9f9b13d3b203a7a0c4c03968ac372b007f3cb2ec7881f1497f78d5485c3b67a777ce7258f7f5cc
|
|
@@ -19,6 +19,7 @@ module Journaled
|
|
|
19
19
|
attribute :event_data, :json
|
|
20
20
|
|
|
21
21
|
validates :event_type, :event_data, :partition_key, :stream_name, presence: true
|
|
22
|
+
validate :failed_at_and_failure_reason_must_be_consistent
|
|
22
23
|
|
|
23
24
|
scope :ready_to_process, -> {
|
|
24
25
|
where(failed_at: nil)
|
|
@@ -63,6 +64,14 @@ module Journaled
|
|
|
63
64
|
def self.oldest_non_failed_timestamp
|
|
64
65
|
ready_to_process.order(:id).limit(1).pick(:created_at)
|
|
65
66
|
end
|
|
67
|
+
|
|
68
|
+
private
|
|
69
|
+
|
|
70
|
+
def failed_at_and_failure_reason_must_be_consistent
|
|
71
|
+
if failed_at.present? != failure_reason.present?
|
|
72
|
+
errors.add(:base, 'failed_at and failure_reason must both be present or both be absent')
|
|
73
|
+
end
|
|
74
|
+
end
|
|
66
75
|
end
|
|
67
76
|
end
|
|
68
77
|
end
|
|
@@ -15,6 +15,8 @@ module Journaled
|
|
|
15
15
|
'ValidationException',
|
|
16
16
|
].freeze
|
|
17
17
|
|
|
18
|
+
BATCH_TOO_LARGE_PATTERN = /too large/i
|
|
19
|
+
|
|
18
20
|
# Send a batch of database events to Kinesis
|
|
19
21
|
#
|
|
20
22
|
# Uses put_records batch API. Groups events by stream and sends each group as a batch.
|
|
@@ -40,11 +42,10 @@ module Journaled
|
|
|
40
42
|
begin
|
|
41
43
|
response = kinesis_client.put_records(stream_name:, records:)
|
|
42
44
|
process_response(response, stream_events)
|
|
43
|
-
rescue Aws::Kinesis::Errors::ValidationException
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
raise
|
|
45
|
+
rescue Aws::Kinesis::Errors::ValidationException => e
|
|
46
|
+
raise unless e.message.match?(BATCH_TOO_LARGE_PATTERN)
|
|
47
|
+
|
|
48
|
+
handle_batch_too_large(stream_name, stream_events)
|
|
48
49
|
rescue StandardError => e
|
|
49
50
|
# Handle transient errors (throttling, network issues, service unavailable)
|
|
50
51
|
handle_transient_batch_error(e, stream_events)
|
|
@@ -93,6 +94,36 @@ module Journaled
|
|
|
93
94
|
)
|
|
94
95
|
end
|
|
95
96
|
|
|
97
|
+
def handle_batch_too_large(stream_name, stream_events)
|
|
98
|
+
if stream_events.size <= 1
|
|
99
|
+
# Single event exceeds payload limit — treat as permanent failure
|
|
100
|
+
return {
|
|
101
|
+
succeeded: [],
|
|
102
|
+
failed: stream_events.map do |event|
|
|
103
|
+
create_failed_event(
|
|
104
|
+
event,
|
|
105
|
+
error_code: 'ValidationException',
|
|
106
|
+
error_message: 'Record exceeds Kinesis payload limit',
|
|
107
|
+
transient: false,
|
|
108
|
+
)
|
|
109
|
+
end,
|
|
110
|
+
}
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
Rails.logger.warn(
|
|
114
|
+
"[journaled] Batch too large for Kinesis (#{stream_events.size} events), splitting in half and retrying",
|
|
115
|
+
)
|
|
116
|
+
|
|
117
|
+
mid = stream_events.size / 2
|
|
118
|
+
first_half = send_stream_batch(stream_name, stream_events[...mid])
|
|
119
|
+
second_half = send_stream_batch(stream_name, stream_events[mid...])
|
|
120
|
+
|
|
121
|
+
{
|
|
122
|
+
succeeded: first_half[:succeeded] + second_half[:succeeded],
|
|
123
|
+
failed: first_half[:failed] + second_half[:failed],
|
|
124
|
+
}
|
|
125
|
+
end
|
|
126
|
+
|
|
96
127
|
def handle_transient_batch_error(error, stream_events)
|
|
97
128
|
Rails.logger.error("Kinesis batch send failed (transient): #{error.class} - #{error.message}")
|
|
98
129
|
|
|
@@ -73,7 +73,7 @@ module Journaled
|
|
|
73
73
|
Event.select(
|
|
74
74
|
'COUNT(*) AS total_count',
|
|
75
75
|
'COUNT(*) FILTER (WHERE failed_at IS NULL) AS workable_count',
|
|
76
|
-
'COUNT(*) FILTER (WHERE
|
|
76
|
+
'COUNT(*) FILTER (WHERE failed_at IS NOT NULL) AS failed_count',
|
|
77
77
|
'MIN(created_at) FILTER (WHERE failed_at IS NULL) AS oldest_non_failed_timestamp',
|
|
78
78
|
).to_sql,
|
|
79
79
|
)
|
data/lib/journaled/version.rb
CHANGED
metadata
CHANGED
|
@@ -1,16 +1,17 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: journaled
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 6.2.
|
|
4
|
+
version: 6.2.5
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Jake Lipson
|
|
8
8
|
- Corey Alexander
|
|
9
9
|
- Cyrus Eslami
|
|
10
10
|
- John Mileham
|
|
11
|
+
autorequire:
|
|
11
12
|
bindir: bin
|
|
12
13
|
cert_chain: []
|
|
13
|
-
date:
|
|
14
|
+
date: 2026-03-03 00:00:00.000000000 Z
|
|
14
15
|
dependencies:
|
|
15
16
|
- !ruby/object:Gem::Dependency
|
|
16
17
|
name: activejob
|
|
@@ -324,7 +325,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
324
325
|
- !ruby/object:Gem::Version
|
|
325
326
|
version: '0'
|
|
326
327
|
requirements: []
|
|
327
|
-
rubygems_version: 3.
|
|
328
|
+
rubygems_version: 3.4.10
|
|
329
|
+
signing_key:
|
|
328
330
|
specification_version: 4
|
|
329
331
|
summary: Journaling for Betterment apps.
|
|
330
332
|
test_files: []
|