jetstream_bridge 1.12.0 → 1.14.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.
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 649a6258b0dce4c43433916df6bb2f9c5d41ba233f05ce66b935853b16637b64
|
4
|
+
data.tar.gz: 942589e88710ac2da1651baa5cee79dbd2304db0fa15a12a8c9d911c8d05ef44
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 10540646b48b7d605f5f92915d4d8be5aed2f72578a151c3f2e4bc500a2908df4c216f1baa0dc128fddd502ca4f88ef73e6c27bb56ab9174573619a298893d4e
|
7
|
+
data.tar.gz: 0debe41380866ee0253570f87b7a3f13dbdbdd3456cbc655815da586612d36155df1f169ba5f321f037b0031f50552f6e8d5e82b04f52f49b41f4e05eb1c1a40
|
data/Gemfile.lock
CHANGED
@@ -15,6 +15,7 @@ module JetstreamBridge
|
|
15
15
|
# Safe column presence check that never boots a connection during class load.
|
16
16
|
def has_column?(name)
|
17
17
|
return false unless ar_connected?
|
18
|
+
|
18
19
|
connection.schema_cache.columns_hash(table_name).key?(name.to_s)
|
19
20
|
rescue ActiveRecord::ConnectionNotEstablished, ActiveRecord::NoDatabaseError
|
20
21
|
false
|
@@ -22,7 +23,7 @@ module JetstreamBridge
|
|
22
23
|
|
23
24
|
def ar_connected?
|
24
25
|
ActiveRecord::Base.connected? && connection_pool.active_connection?
|
25
|
-
rescue
|
26
|
+
rescue StandardError
|
26
27
|
false
|
27
28
|
end
|
28
29
|
end
|
@@ -42,7 +43,7 @@ module JetstreamBridge
|
|
42
43
|
|
43
44
|
validates :stream_seq,
|
44
45
|
uniqueness: { scope: :stream },
|
45
|
-
if:
|
46
|
+
if: lambda {
|
46
47
|
!self.class.has_column?(:event_id) &&
|
47
48
|
self.class.has_column?(:stream_seq) &&
|
48
49
|
self.class.has_column?(:stream)
|
@@ -50,7 +51,7 @@ module JetstreamBridge
|
|
50
51
|
|
51
52
|
validates :stream_seq,
|
52
53
|
uniqueness: true,
|
53
|
-
if:
|
54
|
+
if: lambda {
|
54
55
|
!self.class.has_column?(:event_id) &&
|
55
56
|
self.class.has_column?(:stream_seq) &&
|
56
57
|
!self.class.has_column?(:stream)
|
@@ -62,8 +63,10 @@ module JetstreamBridge
|
|
62
63
|
|
63
64
|
# ---- Defaults that do not require schema at load time ----
|
64
65
|
before_validation do
|
65
|
-
self.status
|
66
|
-
|
66
|
+
self.status ||= 'received' if self.class.has_column?(:status) && status.blank?
|
67
|
+
if self.class.has_column?(:received_at) && received_at.blank?
|
68
|
+
self.received_at ||= Time.now.utc
|
69
|
+
end
|
67
70
|
end
|
68
71
|
|
69
72
|
# ---- Helpers ----
|
@@ -80,8 +83,12 @@ module JetstreamBridge
|
|
80
83
|
def payload_hash
|
81
84
|
v = self[:payload]
|
82
85
|
case v
|
83
|
-
when String then
|
84
|
-
|
86
|
+
when String then begin
|
87
|
+
JSON.parse(v)
|
88
|
+
rescue StandardError
|
89
|
+
{}
|
90
|
+
end
|
91
|
+
when Hash then v
|
85
92
|
else v.respond_to?(:as_json) ? v.as_json : {}
|
86
93
|
end
|
87
94
|
end
|
@@ -93,14 +100,18 @@ module JetstreamBridge
|
|
93
100
|
def method_missing(method_name, *_args, &_block)
|
94
101
|
raise_missing_ar!('Inbox', method_name)
|
95
102
|
end
|
96
|
-
|
103
|
+
|
104
|
+
def respond_to_missing?(_m, _p = false)
|
105
|
+
false
|
106
|
+
end
|
97
107
|
|
98
108
|
private
|
109
|
+
|
99
110
|
def raise_missing_ar!(which, method_name)
|
100
111
|
raise(
|
101
112
|
"#{which} requires ActiveRecord (tried to call ##{method_name}). " \
|
102
|
-
|
103
|
-
|
113
|
+
'Enable `use_inbox` only in apps with ActiveRecord, or add ' \
|
114
|
+
'`gem \"activerecord\"` to your Gemfile.'
|
104
115
|
)
|
105
116
|
end
|
106
117
|
end
|
@@ -27,15 +27,15 @@ module JetstreamBridge
|
|
27
27
|
event_id = envelope['event_id'].to_s
|
28
28
|
|
29
29
|
attrs = {
|
30
|
-
event_id:
|
31
|
-
subject:
|
32
|
-
payload:
|
33
|
-
headers:
|
34
|
-
status:
|
30
|
+
event_id: event_id,
|
31
|
+
subject: subject,
|
32
|
+
payload: ModelUtils.json_dump(envelope),
|
33
|
+
headers: ModelUtils.json_dump({ 'Nats-Msg-Id' => event_id }),
|
34
|
+
status: 'publishing',
|
35
35
|
last_error: nil
|
36
36
|
}
|
37
|
-
attrs[:attempts]
|
38
|
-
attrs[:enqueued_at]= (record.enqueued_at || now) if record.respond_to?(:enqueued_at)
|
37
|
+
attrs[:attempts] = 1 + (record.attempts || 0) if record.respond_to?(:attempts)
|
38
|
+
attrs[:enqueued_at] = (record.enqueued_at || now) if record.respond_to?(:enqueued_at)
|
39
39
|
attrs[:updated_at] = now if record.respond_to?(:updated_at)
|
40
40
|
|
41
41
|
ModelUtils.assign_known_attrs(record, attrs)
|
@@ -45,8 +45,8 @@ module JetstreamBridge
|
|
45
45
|
def persist_success(record)
|
46
46
|
now = Time.now.utc
|
47
47
|
attrs = { status: 'sent' }
|
48
|
-
attrs[:sent_at]
|
49
|
-
attrs[:updated_at]= now if record.respond_to?(:updated_at)
|
48
|
+
attrs[:sent_at] = now if record.respond_to?(:sent_at)
|
49
|
+
attrs[:updated_at] = now if record.respond_to?(:updated_at)
|
50
50
|
ModelUtils.assign_known_attrs(record, attrs)
|
51
51
|
record.save!
|
52
52
|
end
|
@@ -61,9 +61,10 @@ module JetstreamBridge
|
|
61
61
|
|
62
62
|
def persist_exception(record, error)
|
63
63
|
return unless record
|
64
|
+
|
64
65
|
persist_failure(record, "#{error.class}: #{error.message}")
|
65
|
-
rescue =>
|
66
|
-
Logging.warn("Failed to persist outbox failure: #{
|
66
|
+
rescue StandardError => e
|
67
|
+
Logging.warn("Failed to persist outbox failure: #{e.class}: #{e.message}",
|
67
68
|
tag: 'JetstreamBridge::Publisher')
|
68
69
|
end
|
69
70
|
end
|
@@ -6,6 +6,7 @@ require_relative '../core/connection'
|
|
6
6
|
require_relative '../core/logging'
|
7
7
|
require_relative '../core/config'
|
8
8
|
require_relative '../core/model_utils'
|
9
|
+
require_relative 'outbox_repository'
|
9
10
|
|
10
11
|
module JetstreamBridge
|
11
12
|
# Publishes to "{env}.data.sync.{app}.{dest}".
|
@@ -14,10 +15,10 @@ module JetstreamBridge
|
|
14
15
|
RETRY_BACKOFFS = [0.25, 1.0].freeze
|
15
16
|
|
16
17
|
TRANSIENT_ERRORS = begin
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
18
|
+
errs = [NATS::IO::Timeout, NATS::IO::Error]
|
19
|
+
errs << NATS::IO::SocketTimeoutError if defined?(NATS::IO::SocketTimeoutError)
|
20
|
+
errs.freeze
|
21
|
+
end
|
21
22
|
|
22
23
|
def initialize
|
23
24
|
@jts = Connection.connect!
|
@@ -42,6 +43,7 @@ module JetstreamBridge
|
|
42
43
|
|
43
44
|
def ensure_destination!
|
44
45
|
return unless JetstreamBridge.config.destination_app.to_s.empty?
|
46
|
+
|
45
47
|
raise ArgumentError, 'destination_app must be configured'
|
46
48
|
end
|
47
49
|
|
@@ -78,7 +80,7 @@ module JetstreamBridge
|
|
78
80
|
ok = with_retries { do_publish(subject, envelope) }
|
79
81
|
ok ? repo.persist_success(record) : repo.persist_failure(record, 'Publish returned false')
|
80
82
|
ok
|
81
|
-
rescue => e
|
83
|
+
rescue StandardError => e
|
82
84
|
repo.persist_exception(record, e) if defined?(repo) && defined?(record)
|
83
85
|
log_error(false, e)
|
84
86
|
end
|
@@ -88,10 +90,11 @@ module JetstreamBridge
|
|
88
90
|
def with_retries(retries = DEFAULT_RETRIES)
|
89
91
|
attempts = 0
|
90
92
|
begin
|
91
|
-
|
93
|
+
yield
|
92
94
|
rescue *TRANSIENT_ERRORS => e
|
93
95
|
attempts += 1
|
94
96
|
return log_error(false, e) if attempts > retries
|
97
|
+
|
95
98
|
backoff(attempts, e)
|
96
99
|
retry
|
97
100
|
end
|
@@ -112,15 +115,15 @@ module JetstreamBridge
|
|
112
115
|
|
113
116
|
def build_envelope(resource_type, event_type, payload, options = {})
|
114
117
|
{
|
115
|
-
'event_id'
|
118
|
+
'event_id' => options[:event_id] || SecureRandom.uuid,
|
116
119
|
'schema_version' => 1,
|
117
|
-
'event_type'
|
118
|
-
'producer'
|
119
|
-
'resource_id'
|
120
|
-
'occurred_at'
|
121
|
-
'trace_id'
|
122
|
-
'resource_type'
|
123
|
-
'payload'
|
120
|
+
'event_type' => event_type,
|
121
|
+
'producer' => JetstreamBridge.config.app_name,
|
122
|
+
'resource_id' => (payload['id'] || payload[:id]).to_s,
|
123
|
+
'occurred_at' => (options[:occurred_at] || Time.now.utc).iso8601,
|
124
|
+
'trace_id' => options[:trace_id] || SecureRandom.hex(8),
|
125
|
+
'resource_type' => resource_type,
|
126
|
+
'payload' => payload
|
124
127
|
}
|
125
128
|
end
|
126
129
|
end
|