webhookdb 1.2.2 → 1.3.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/admin-dist/assets/index-6aebf805.js +264 -0
- data/admin-dist/favicon.ico +0 -0
- data/admin-dist/index.html +130 -0
- data/admin-dist/manifest.json +15 -0
- data/data/messages/replicators/url-recorder.liquid +20 -0
- data/data/messages/templates/errors/signalwire_send_sms.email.liquid +31 -0
- data/data/messages/web/install-customer-login.liquid +6 -5
- data/data/messages/web/install-error.liquid +1 -1
- data/data/messages/web/install-forbidden.liquid +25 -0
- data/data/messages/web/install-org-chooser.liquid +40 -0
- data/data/messages/web/install-success.liquid +2 -1
- data/data/messages/web/install.liquid +2 -1
- data/data/messages/web/partials/head.liquid +2 -0
- data/data/messages/web/styles.liquid +24 -0
- data/db/migrations/041_views.rb +20 -0
- data/db/migrations/042_sint_lock.rb +10 -0
- data/db/migrations/043_text_search.rb +28 -0
- data/db/migrations/044_oauth_session_token_cache.rb +21 -0
- data/integration/auth_spec.rb +2 -2
- data/lib/sequel/plugins/text_searchable.rb +165 -0
- data/lib/sequel/text_searchable.rb +42 -0
- data/lib/webhookdb/admin_api/auth.rb +24 -3
- data/lib/webhookdb/admin_api/data_provider.rb +196 -0
- data/lib/webhookdb/admin_api/entities.rb +143 -28
- data/lib/webhookdb/admin_api.rb +0 -2
- data/lib/webhookdb/api/auth.rb +5 -6
- data/lib/webhookdb/api/db.rb +31 -6
- data/lib/webhookdb/api/entities.rb +7 -1
- data/lib/webhookdb/api/helpers.rb +6 -25
- data/lib/webhookdb/api/install.rb +204 -79
- data/lib/webhookdb/api/organizations.rb +14 -12
- data/lib/webhookdb/api/saved_queries.rb +9 -3
- data/lib/webhookdb/api/saved_views.rb +99 -0
- data/lib/webhookdb/api/service_integrations.rb +15 -9
- data/lib/webhookdb/api/subscriptions.rb +3 -1
- data/lib/webhookdb/api/sync_targets.rb +9 -7
- data/lib/webhookdb/api/system.rb +1 -0
- data/lib/webhookdb/api/webhook_subscriptions.rb +3 -1
- data/lib/webhookdb/apps.rb +30 -7
- data/lib/webhookdb/async/audit_logger.rb +2 -0
- data/lib/webhookdb/async.rb +5 -0
- data/lib/webhookdb/backfill_job/service_integration_lock.rb +22 -0
- data/lib/webhookdb/backfill_job.rb +9 -0
- data/lib/webhookdb/customer.rb +5 -0
- data/lib/webhookdb/database_document.rb +1 -1
- data/lib/webhookdb/db_adapter/default_sql.rb +1 -1
- data/lib/webhookdb/db_adapter.rb +20 -4
- data/lib/webhookdb/fixtures/message_bodies.rb +34 -0
- data/lib/webhookdb/fixtures/organizations.rb +5 -0
- data/lib/webhookdb/fixtures/roles.rb +14 -0
- data/lib/webhookdb/fixtures/saved_views.rb +25 -0
- data/lib/webhookdb/fixtures/webhook_subscription_deliveries.rb +18 -0
- data/lib/webhookdb/http.rb +8 -2
- data/lib/webhookdb/icalendar.rb +3 -0
- data/lib/webhookdb/idempotency.rb +69 -22
- data/lib/webhookdb/increase.rb +69 -21
- data/lib/webhookdb/intercom.rb +10 -3
- data/lib/webhookdb/jobs/backfill.rb +3 -1
- data/lib/webhookdb/jobs/emailer.rb +0 -1
- data/lib/webhookdb/jobs/icalendar_delete_stale_cancelled_events.rb +19 -0
- data/lib/webhookdb/jobs/icalendar_enqueue_syncs.rb +1 -1
- data/lib/webhookdb/jobs/icalendar_sync.rb +1 -1
- data/lib/webhookdb/jobs/increase_event_handler.rb +20 -0
- data/lib/webhookdb/jobs/scheduled_backfills.rb +2 -1
- data/lib/webhookdb/jobs/sync_target_run_sync.rb +3 -1
- data/lib/webhookdb/message/body.rb +6 -4
- data/lib/webhookdb/message/delivery.rb +2 -0
- data/lib/webhookdb/messages/error_icalendar_fetch.rb +1 -2
- data/lib/webhookdb/messages/error_signalwire_send_sms.rb +48 -0
- data/lib/webhookdb/oauth/fake_provider.rb +44 -0
- data/lib/webhookdb/oauth/front_provider.rb +1 -2
- data/lib/webhookdb/oauth/increase_provider.rb +80 -0
- data/lib/webhookdb/oauth/intercom_provider.rb +3 -11
- data/lib/webhookdb/oauth/session.rb +20 -0
- data/lib/webhookdb/oauth.rb +7 -21
- data/lib/webhookdb/organization/alerting.rb +2 -0
- data/lib/webhookdb/organization/database_migration.rb +3 -0
- data/lib/webhookdb/organization.rb +37 -6
- data/lib/webhookdb/organization_membership.rb +14 -7
- data/lib/webhookdb/postgres.rb +2 -0
- data/lib/webhookdb/replicator/base.rb +1 -0
- data/lib/webhookdb/replicator/docgen.rb +9 -1
- data/lib/webhookdb/replicator/fake.rb +2 -3
- data/lib/webhookdb/replicator/front_signalwire_message_channel_app_v1.rb +49 -14
- data/lib/webhookdb/replicator/icalendar_calendar_v1.rb +97 -17
- data/lib/webhookdb/replicator/icalendar_event_v1.rb +104 -2
- data/lib/webhookdb/replicator/increase_account_number_v1.rb +6 -43
- data/lib/webhookdb/replicator/increase_account_transfer_v1.rb +7 -24
- data/lib/webhookdb/replicator/increase_account_v1.rb +7 -31
- data/lib/webhookdb/replicator/increase_ach_transfer_v1.rb +5 -43
- data/lib/webhookdb/replicator/increase_app_v1.rb +78 -0
- data/lib/webhookdb/replicator/increase_check_transfer_v1.rb +23 -29
- data/lib/webhookdb/replicator/increase_event_v1.rb +41 -0
- data/lib/webhookdb/replicator/increase_limit_v1.rb +9 -34
- data/lib/webhookdb/replicator/increase_transaction_v1.rb +5 -30
- data/lib/webhookdb/replicator/increase_v1_mixin.rb +58 -78
- data/lib/webhookdb/replicator/increase_wire_transfer_v1.rb +5 -24
- data/lib/webhookdb/replicator/intercom_contact_v1.rb +51 -4
- data/lib/webhookdb/replicator/intercom_conversation_v1.rb +42 -6
- data/lib/webhookdb/replicator/intercom_marketplace_root_v1.rb +2 -13
- data/lib/webhookdb/replicator/intercom_v1_mixin.rb +20 -16
- data/lib/webhookdb/replicator/oauth_refresh_access_token_mixin.rb +1 -1
- data/lib/webhookdb/replicator/sponsy_v1_mixin.rb +1 -1
- data/lib/webhookdb/replicator/transistor_episode_v1.rb +17 -0
- data/lib/webhookdb/replicator/url_recorder_v1.rb +137 -0
- data/lib/webhookdb/replicator/webhook_request.rb +4 -0
- data/lib/webhookdb/replicator.rb +8 -0
- data/lib/webhookdb/role.rb +5 -2
- data/lib/webhookdb/saved_query.rb +23 -0
- data/lib/webhookdb/saved_view.rb +73 -0
- data/lib/webhookdb/sentry.rb +2 -0
- data/lib/webhookdb/service/entities.rb +0 -4
- data/lib/webhookdb/service/helpers.rb +5 -0
- data/lib/webhookdb/service/middleware.rb +9 -0
- data/lib/webhookdb/service/types.rb +10 -8
- data/lib/webhookdb/service/validators.rb +1 -2
- data/lib/webhookdb/service/view_api.rb +1 -1
- data/lib/webhookdb/service_integration.rb +17 -15
- data/lib/webhookdb/spec_helpers/shared_examples_for_replicators.rb +8 -8
- data/lib/webhookdb/spec_helpers/whdb.rb +3 -2
- data/lib/webhookdb/subscription.rb +2 -0
- data/lib/webhookdb/sync_target.rb +10 -2
- data/lib/webhookdb/tasks/message.rb +3 -1
- data/lib/webhookdb/version.rb +1 -1
- data/lib/webhookdb/webhook_subscription/delivery.rb +2 -0
- data/lib/webhookdb/webhook_subscription.rb +2 -0
- metadata +57 -9
- data/lib/webhookdb/admin_api/customers.rb +0 -63
- data/lib/webhookdb/admin_api/message_deliveries.rb +0 -61
- data/lib/webhookdb/admin_api/roles.rb +0 -15
|
@@ -65,7 +65,7 @@ class Webhookdb::Replicator::IcalendarEventV1 < Webhookdb::Replicator::Base
|
|
|
65
65
|
ruby: lambda do |entry, **|
|
|
66
66
|
self.entry_to_date(entry) if entry.is_a?(Hash) && self.entry_is_date_str?(entry)
|
|
67
67
|
end,
|
|
68
|
-
sql:
|
|
68
|
+
sql: Webhookdb::Replicator::Column::NOT_IMPLEMENTED,
|
|
69
69
|
)
|
|
70
70
|
CONV_DATETIME = Webhookdb::Replicator::Column::IsomorphicProc.new(
|
|
71
71
|
ruby: lambda do |entry, **|
|
|
@@ -108,6 +108,8 @@ class Webhookdb::Replicator::IcalendarEventV1 < Webhookdb::Replicator::Base
|
|
|
108
108
|
sql: ->(_) { raise NotImplementedError },
|
|
109
109
|
)
|
|
110
110
|
|
|
111
|
+
def _webhook_response(_request) = Webhookdb::WebhookResponse.ok
|
|
112
|
+
|
|
111
113
|
def _remote_key_column
|
|
112
114
|
return Webhookdb::Replicator::Column.new(
|
|
113
115
|
:compound_identity,
|
|
@@ -126,7 +128,7 @@ class Webhookdb::Replicator::IcalendarEventV1 < Webhookdb::Replicator::Base
|
|
|
126
128
|
return [
|
|
127
129
|
col.new(:calendar_external_id, TEXT, index: true),
|
|
128
130
|
col.new(:uid, TEXT, data_key: ["UID", "v"], index: true),
|
|
129
|
-
col.new(:row_updated_at, TIMESTAMP, index: true
|
|
131
|
+
col.new(:row_updated_at, TIMESTAMP, index: true),
|
|
130
132
|
col.new(:last_modified_at,
|
|
131
133
|
TIMESTAMP,
|
|
132
134
|
index: true,
|
|
@@ -153,6 +155,8 @@ class Webhookdb::Replicator::IcalendarEventV1 < Webhookdb::Replicator::Base
|
|
|
153
155
|
]
|
|
154
156
|
end
|
|
155
157
|
|
|
158
|
+
def _timestamp_column_name = :last_modified_at
|
|
159
|
+
|
|
156
160
|
def _resource_and_event(request)
|
|
157
161
|
return request.body, nil
|
|
158
162
|
end
|
|
@@ -165,6 +169,41 @@ class Webhookdb::Replicator::IcalendarEventV1 < Webhookdb::Replicator::Base
|
|
|
165
169
|
return data
|
|
166
170
|
end
|
|
167
171
|
|
|
172
|
+
def _prepare_for_insert(resource, event, request, enrichment)
|
|
173
|
+
h = super
|
|
174
|
+
# Events can have a DTSTART, but no DTEND.
|
|
175
|
+
# https://icalendar.org/iCalendar-RFC-5545/3-6-1-event-component.html
|
|
176
|
+
# In these cases, we need to:
|
|
177
|
+
# - Use the duration, given.
|
|
178
|
+
# - Dates default to the next day.
|
|
179
|
+
# - Times default to start time.
|
|
180
|
+
if (_implicit_end_time = h[:start_at] && !h[:end_at])
|
|
181
|
+
self._set_implicit_end_at(resource, h)
|
|
182
|
+
elsif (_implicit_end_date = h[:start_date] && !h[:end_date])
|
|
183
|
+
self._set_implicit_end_date(resource, h)
|
|
184
|
+
end
|
|
185
|
+
return h
|
|
186
|
+
end
|
|
187
|
+
|
|
188
|
+
def _set_implicit_end_date(resource, h)
|
|
189
|
+
if (d = resource["DURATION"])
|
|
190
|
+
# See https://icalendar.org/iCalendar-RFC-5545/3-3-6-duration.html
|
|
191
|
+
dur = ActiveSupport::Duration.parse(d.fetch("v"))
|
|
192
|
+
h[:end_date] = h[:start_date] + dur
|
|
193
|
+
return
|
|
194
|
+
end
|
|
195
|
+
h[:end_date] = h[:start_date] + 1.day
|
|
196
|
+
end
|
|
197
|
+
|
|
198
|
+
def _set_implicit_end_at(resource, h)
|
|
199
|
+
if (d = resource["DURATION"])
|
|
200
|
+
dur = ActiveSupport::Duration.parse(d.fetch("v"))
|
|
201
|
+
h[:end_at] = h[:start_at] + dur
|
|
202
|
+
return
|
|
203
|
+
end
|
|
204
|
+
h[:end_at] = h[:start_at]
|
|
205
|
+
end
|
|
206
|
+
|
|
168
207
|
# @return [Array<Webhookdb::Replicator::IndexSpec>]
|
|
169
208
|
def _extra_index_specs
|
|
170
209
|
return [
|
|
@@ -220,6 +259,21 @@ class Webhookdb::Replicator::IcalendarEventV1 < Webhookdb::Replicator::Base
|
|
|
220
259
|
value.gsub!("\\r\\n", "\r\n")
|
|
221
260
|
value.gsub!("\\n", "\n")
|
|
222
261
|
value.gsub!("\\t", "\t")
|
|
262
|
+
# This line is not tested, since replicating issues with HTTP body encoding
|
|
263
|
+
# is really tricky (while I love Ruby's unicode handling, trying to replicate
|
|
264
|
+
# invalid data from other sources is a pain).
|
|
265
|
+
# However we do get invalid unicode sequences, like:
|
|
266
|
+
# DESCRIPTION:\r\nNFL regional registration opens 9/25 and ends 11/20\XAOwww.nflflag.com
|
|
267
|
+
# which cannot be encoded in JSON:
|
|
268
|
+
# Invalid Unicode [a0 77 77 77 2e] at 52 (JSON::GeneratorError)
|
|
269
|
+
# The only way I can think to handle this is with replacing invalid utf-8 chars
|
|
270
|
+
# (with the unicode questionmark icon), so they can be represented as JSON.
|
|
271
|
+
# This fix is here, and not in `Base#_to_json` (like the null char fixes),
|
|
272
|
+
# since I think this is an issue with feeds like icalendar,
|
|
273
|
+
# and not something to handle generally
|
|
274
|
+
# (we may also see this in something like Atom, but perhaps because
|
|
275
|
+
# atom is XML, not a 'plain' text format, it'll be more rare).
|
|
276
|
+
value.encode!("UTF-8", invalid: :replace, undef: :replace)
|
|
223
277
|
end
|
|
224
278
|
entry = {"v" => value}
|
|
225
279
|
entry.merge!(params)
|
|
@@ -311,6 +365,54 @@ class Webhookdb::Replicator::IcalendarEventV1 < Webhookdb::Replicator::Base
|
|
|
311
365
|
return
|
|
312
366
|
end
|
|
313
367
|
|
|
368
|
+
# Delete CANCELLED events last updated (+row_updated_at+)' in the window between
|
|
369
|
+
# +stale_at+ to +age_cutoff+. This avoids endlessly adding to the icalendar events table
|
|
370
|
+
# due to feeds that change UIDs each fetch- events with changed UIDs will become CANCELLED,
|
|
371
|
+
# and then deleted over time.
|
|
372
|
+
# @param stale_at [Time] When an event is considered 'stale'.
|
|
373
|
+
# If stale events are a big problem, this can be shortened to just a few days.
|
|
374
|
+
# @param age_cutoff [Time] Where to stop searching for old events.
|
|
375
|
+
# This is important to avoid a full table scale when deleting events,
|
|
376
|
+
# since otherwise it is like 'row_updated_at < 35.days.ago'.
|
|
377
|
+
# Since this routine should run regularly, we should rarely have events more than 35 or 36 days old,
|
|
378
|
+
# for example.
|
|
379
|
+
# Use +nil+ to use no limit (a full table scan) which may be necessary when running this feature
|
|
380
|
+
# for the first time.
|
|
381
|
+
# @param chunk_size [Integer] The row delete is done in chunks to avoid long locks.
|
|
382
|
+
# The default seems safe, but it's exposed as a parameter if you need to play around with it,
|
|
383
|
+
# and can be done via configuration if needed at some point.
|
|
384
|
+
def delete_stale_cancelled_events(
|
|
385
|
+
stale_at: Webhookdb::Icalendar.stale_cancelled_event_threshold_days.days.ago,
|
|
386
|
+
age_cutoff: (Webhookdb::Icalendar.stale_cancelled_event_threshold_days + 10).days.ago,
|
|
387
|
+
chunk_size: 10_000
|
|
388
|
+
)
|
|
389
|
+
# Delete in chunks, like:
|
|
390
|
+
# DELETE from "public"."icalendar_event_v1_aaaa"
|
|
391
|
+
# WHERE pk IN (
|
|
392
|
+
# SELECT pk FROM "public"."icalendar_event_v1_aaaa"
|
|
393
|
+
# WHERE row_updated_at < (now() - '35 days'::interval)
|
|
394
|
+
# LIMIT 10000
|
|
395
|
+
# )
|
|
396
|
+
age = age_cutoff..stale_at
|
|
397
|
+
self.admin_dataset do |ds|
|
|
398
|
+
chunk_ds = ds.where(row_updated_at: age, status: "CANCELLED").select(:pk).limit(chunk_size)
|
|
399
|
+
loop do
|
|
400
|
+
# Due to conflicts where a feed is being inserted while the delete is happening,
|
|
401
|
+
# this may raise an error like:
|
|
402
|
+
# deadlock detected
|
|
403
|
+
# DETAIL: Process 18352 waits for ShareLock on transaction 435085606; blocked by process 24191.
|
|
404
|
+
# Process 24191 waits for ShareLock on transaction 435085589; blocked by process 18352.
|
|
405
|
+
# HINT: See server log for query details.
|
|
406
|
+
# CONTEXT: while deleting tuple (2119119,3) in relation "icalendar_event_v1_aaaa"
|
|
407
|
+
# Unit testing this is very difficult though, and in practice it is rare,
|
|
408
|
+
# and normal Sidekiq job retries should be sufficient to handle this.
|
|
409
|
+
# So we don't explicitly handle deadlocks, but could if it becomes an issue.
|
|
410
|
+
deleted = ds.where(pk: chunk_ds).delete
|
|
411
|
+
break if deleted != chunk_size
|
|
412
|
+
end
|
|
413
|
+
end
|
|
414
|
+
end
|
|
415
|
+
|
|
314
416
|
def calculate_webhook_state_machine
|
|
315
417
|
if (step = self.calculate_dependency_state_machine_step(dependency_help: ""))
|
|
316
418
|
return step
|
|
@@ -11,12 +11,12 @@ class Webhookdb::Replicator::IncreaseAccountNumberV1 < Webhookdb::Replicator::Ba
|
|
|
11
11
|
def self.descriptor
|
|
12
12
|
return Webhookdb::Replicator::Descriptor.new(
|
|
13
13
|
name: "increase_account_number_v1",
|
|
14
|
-
ctor:
|
|
14
|
+
ctor: self,
|
|
15
15
|
feature_roles: [],
|
|
16
16
|
resource_name_singular: "Increase Account Number",
|
|
17
|
-
|
|
17
|
+
dependency_descriptor: Webhookdb::Replicator::IncreaseAppV1.descriptor,
|
|
18
18
|
supports_backfill: true,
|
|
19
|
-
api_docs_url: "https://
|
|
19
|
+
api_docs_url: "https://increase.com/documentation/api",
|
|
20
20
|
)
|
|
21
21
|
end
|
|
22
22
|
|
|
@@ -26,52 +26,15 @@ class Webhookdb::Replicator::IncreaseAccountNumberV1 < Webhookdb::Replicator::Ba
|
|
|
26
26
|
|
|
27
27
|
def _denormalized_columns
|
|
28
28
|
return [
|
|
29
|
+
Webhookdb::Replicator::Column.new(:created_at, TIMESTAMP, index: true),
|
|
30
|
+
Webhookdb::Replicator::Column.new(:updated_at, TIMESTAMP, index: true),
|
|
29
31
|
Webhookdb::Replicator::Column.new(:account_id, TEXT, index: true),
|
|
30
32
|
Webhookdb::Replicator::Column.new(:account_number, TEXT, index: true),
|
|
31
33
|
Webhookdb::Replicator::Column.new(:name, TEXT),
|
|
32
34
|
Webhookdb::Replicator::Column.new(:routing_number, TEXT, index: true),
|
|
33
|
-
Webhookdb::Replicator::Column.new(
|
|
34
|
-
:row_created_at,
|
|
35
|
-
TIMESTAMP,
|
|
36
|
-
data_key: "created_at",
|
|
37
|
-
event_key: "created_at",
|
|
38
|
-
optional: true,
|
|
39
|
-
defaulter: :now,
|
|
40
|
-
index: true,
|
|
41
|
-
),
|
|
42
|
-
Webhookdb::Replicator::Column.new(
|
|
43
|
-
:row_updated_at,
|
|
44
|
-
TIMESTAMP,
|
|
45
|
-
data_key: "created_at",
|
|
46
|
-
event_key: "created_at",
|
|
47
|
-
defaulter: :now,
|
|
48
|
-
optional: true,
|
|
49
|
-
index: true,
|
|
50
|
-
),
|
|
51
35
|
Webhookdb::Replicator::Column.new(:status, TEXT),
|
|
52
36
|
]
|
|
53
37
|
end
|
|
54
38
|
|
|
55
|
-
def
|
|
56
|
-
return :row_updated_at
|
|
57
|
-
end
|
|
58
|
-
|
|
59
|
-
def _update_where_expr
|
|
60
|
-
return self.qualified_table_sequel_identifier[:row_updated_at] < Sequel[:excluded][:row_updated_at]
|
|
61
|
-
end
|
|
62
|
-
|
|
63
|
-
def _resource_and_event(request)
|
|
64
|
-
return self._find_resource_and_event(request.body, "account_number")
|
|
65
|
-
end
|
|
66
|
-
|
|
67
|
-
def _upsert_update_expr(inserting, **_kwargs)
|
|
68
|
-
update = super
|
|
69
|
-
# Only set created_at if it's not set so the initial insert isn't modified.
|
|
70
|
-
self._coalesce_excluded_on_update(update, [:row_created_at])
|
|
71
|
-
return update
|
|
72
|
-
end
|
|
73
|
-
|
|
74
|
-
def _mixin_backfill_url
|
|
75
|
-
return "#{self.service_integration.api_url}/account_numbers"
|
|
76
|
-
end
|
|
39
|
+
def _mixin_object_type = "account_number"
|
|
77
40
|
end
|
|
@@ -11,10 +11,10 @@ class Webhookdb::Replicator::IncreaseAccountTransferV1 < Webhookdb::Replicator::
|
|
|
11
11
|
def self.descriptor
|
|
12
12
|
return Webhookdb::Replicator::Descriptor.new(
|
|
13
13
|
name: "increase_account_transfer_v1",
|
|
14
|
-
ctor:
|
|
14
|
+
ctor: self,
|
|
15
15
|
feature_roles: [],
|
|
16
16
|
resource_name_singular: "Increase Account Transfer",
|
|
17
|
-
|
|
17
|
+
dependency_descriptor: Webhookdb::Replicator::IncreaseAppV1.descriptor,
|
|
18
18
|
supports_backfill: true,
|
|
19
19
|
api_docs_url: "https://increase.com/documentation/api",
|
|
20
20
|
)
|
|
@@ -28,34 +28,17 @@ class Webhookdb::Replicator::IncreaseAccountTransferV1 < Webhookdb::Replicator::
|
|
|
28
28
|
return [
|
|
29
29
|
Webhookdb::Replicator::Column.new(:amount, INTEGER, index: true),
|
|
30
30
|
Webhookdb::Replicator::Column.new(:account_id, TEXT, index: true),
|
|
31
|
-
Webhookdb::Replicator::Column.new(:canceled_at, TIMESTAMP, data_key: ["cancellation", "canceled_at"],
|
|
32
|
-
optional: true,),
|
|
33
31
|
Webhookdb::Replicator::Column.new(:created_at, TIMESTAMP, index: true),
|
|
32
|
+
Webhookdb::Replicator::Column.new(:updated_at, TIMESTAMP, index: true),
|
|
33
|
+
Webhookdb::Replicator::Column.new(
|
|
34
|
+
:canceled_at, TIMESTAMP, data_key: ["cancellation", "canceled_at"], optional: true,
|
|
35
|
+
),
|
|
34
36
|
Webhookdb::Replicator::Column.new(:destination_account_id, TEXT, index: true),
|
|
35
37
|
Webhookdb::Replicator::Column.new(:destination_transaction_id, TEXT, index: true),
|
|
36
38
|
Webhookdb::Replicator::Column.new(:status, TEXT),
|
|
37
|
-
Webhookdb::Replicator::Column.new(:template_id, TEXT),
|
|
38
39
|
Webhookdb::Replicator::Column.new(:transaction_id, TEXT, index: true),
|
|
39
|
-
Webhookdb::Replicator::Column.new(
|
|
40
|
-
:updated_at,
|
|
41
|
-
TIMESTAMP,
|
|
42
|
-
data_key: "created_at",
|
|
43
|
-
event_key: "created_at",
|
|
44
|
-
defaulter: :now,
|
|
45
|
-
index: true,
|
|
46
|
-
),
|
|
47
40
|
]
|
|
48
41
|
end
|
|
49
42
|
|
|
50
|
-
def
|
|
51
|
-
return self.qualified_table_sequel_identifier[:updated_at] < Sequel[:excluded][:updated_at]
|
|
52
|
-
end
|
|
53
|
-
|
|
54
|
-
def _resource_and_event(request)
|
|
55
|
-
return self._find_resource_and_event(request.body, "account_transfer")
|
|
56
|
-
end
|
|
57
|
-
|
|
58
|
-
def _mixin_backfill_url
|
|
59
|
-
return "#{self.service_integration.api_url}/account_transfers"
|
|
60
|
-
end
|
|
43
|
+
def _mixin_object_type = "account_transfer"
|
|
61
44
|
end
|
|
@@ -11,10 +11,10 @@ class Webhookdb::Replicator::IncreaseAccountV1 < Webhookdb::Replicator::Base
|
|
|
11
11
|
def self.descriptor
|
|
12
12
|
return Webhookdb::Replicator::Descriptor.new(
|
|
13
13
|
name: "increase_account_v1",
|
|
14
|
-
ctor:
|
|
14
|
+
ctor: self,
|
|
15
15
|
feature_roles: [],
|
|
16
16
|
resource_name_singular: "Increase Account",
|
|
17
|
-
|
|
17
|
+
dependency_descriptor: Webhookdb::Replicator::IncreaseAppV1.descriptor,
|
|
18
18
|
supports_backfill: true,
|
|
19
19
|
api_docs_url: "https://increase.com/documentation/api",
|
|
20
20
|
)
|
|
@@ -26,38 +26,14 @@ class Webhookdb::Replicator::IncreaseAccountV1 < Webhookdb::Replicator::Base
|
|
|
26
26
|
|
|
27
27
|
def _denormalized_columns
|
|
28
28
|
return [
|
|
29
|
-
Webhookdb::Replicator::Column.new(:
|
|
30
|
-
Webhookdb::Replicator::Column.new(
|
|
31
|
-
:created_at,
|
|
32
|
-
TIMESTAMP,
|
|
33
|
-
data_key: "created_at",
|
|
34
|
-
defaulter: :now,
|
|
35
|
-
index: true,
|
|
36
|
-
),
|
|
37
|
-
Webhookdb::Replicator::Column.new(:entity_id, TEXT, index: true),
|
|
38
|
-
Webhookdb::Replicator::Column.new(:interest_accrued, DECIMAL),
|
|
29
|
+
Webhookdb::Replicator::Column.new(:created_at, TIMESTAMP, index: true),
|
|
30
|
+
Webhookdb::Replicator::Column.new(:updated_at, TIMESTAMP, index: true),
|
|
39
31
|
Webhookdb::Replicator::Column.new(:name, TEXT),
|
|
32
|
+
Webhookdb::Replicator::Column.new(:entity_id, TEXT, index: true),
|
|
40
33
|
Webhookdb::Replicator::Column.new(:status, TEXT),
|
|
41
|
-
Webhookdb::Replicator::Column.new(
|
|
42
|
-
:updated_at,
|
|
43
|
-
TIMESTAMP,
|
|
44
|
-
data_key: "created_at",
|
|
45
|
-
event_key: "created_at",
|
|
46
|
-
defaulter: :now,
|
|
47
|
-
index: true,
|
|
48
|
-
),
|
|
34
|
+
Webhookdb::Replicator::Column.new(:interest_accrued, DECIMAL),
|
|
49
35
|
]
|
|
50
36
|
end
|
|
51
37
|
|
|
52
|
-
def
|
|
53
|
-
return self.qualified_table_sequel_identifier[:updated_at] < Sequel[:excluded][:updated_at]
|
|
54
|
-
end
|
|
55
|
-
|
|
56
|
-
def _resource_and_event(request)
|
|
57
|
-
return self._find_resource_and_event(request.body, "account")
|
|
58
|
-
end
|
|
59
|
-
|
|
60
|
-
def _mixin_backfill_url
|
|
61
|
-
return "#{self.service_integration.api_url}/accounts"
|
|
62
|
-
end
|
|
38
|
+
def _mixin_object_type = "account"
|
|
63
39
|
end
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
require "webhookdb/increase"
|
|
4
3
|
require "webhookdb/replicator/increase_v1_mixin"
|
|
5
4
|
|
|
6
5
|
class Webhookdb::Replicator::IncreaseACHTransferV1 < Webhookdb::Replicator::Base
|
|
@@ -11,10 +10,10 @@ class Webhookdb::Replicator::IncreaseACHTransferV1 < Webhookdb::Replicator::Base
|
|
|
11
10
|
def self.descriptor
|
|
12
11
|
return Webhookdb::Replicator::Descriptor.new(
|
|
13
12
|
name: "increase_ach_transfer_v1",
|
|
14
|
-
ctor:
|
|
13
|
+
ctor: self,
|
|
15
14
|
feature_roles: [],
|
|
16
15
|
resource_name_singular: "Increase ACH Transfer",
|
|
17
|
-
|
|
16
|
+
dependency_descriptor: Webhookdb::Replicator::IncreaseAppV1.descriptor,
|
|
18
17
|
supports_backfill: true,
|
|
19
18
|
api_docs_url: "https://increase.com/documentation/api",
|
|
20
19
|
)
|
|
@@ -29,50 +28,13 @@ class Webhookdb::Replicator::IncreaseACHTransferV1 < Webhookdb::Replicator::Base
|
|
|
29
28
|
Webhookdb::Replicator::Column.new(:account_number, TEXT, index: true),
|
|
30
29
|
Webhookdb::Replicator::Column.new(:account_id, TEXT, index: true),
|
|
31
30
|
Webhookdb::Replicator::Column.new(:amount, INTEGER, index: true),
|
|
32
|
-
Webhookdb::Replicator::Column.new(
|
|
33
|
-
|
|
34
|
-
TIMESTAMP,
|
|
35
|
-
data_key: "created_at",
|
|
36
|
-
index: true,
|
|
37
|
-
),
|
|
31
|
+
Webhookdb::Replicator::Column.new(:created_at, TIMESTAMP, index: true),
|
|
32
|
+
Webhookdb::Replicator::Column.new(:updated_at, TIMESTAMP, index: true),
|
|
38
33
|
Webhookdb::Replicator::Column.new(:routing_number, TEXT, index: true),
|
|
39
34
|
Webhookdb::Replicator::Column.new(:status, TEXT),
|
|
40
35
|
Webhookdb::Replicator::Column.new(:transaction_id, TEXT, index: true),
|
|
41
|
-
Webhookdb::Replicator::Column.new(
|
|
42
|
-
:updated_at,
|
|
43
|
-
TIMESTAMP,
|
|
44
|
-
data_key: "created_at",
|
|
45
|
-
event_key: "created_at",
|
|
46
|
-
defaulter: :now,
|
|
47
|
-
index: true,
|
|
48
|
-
),
|
|
49
36
|
]
|
|
50
37
|
end
|
|
51
38
|
|
|
52
|
-
def
|
|
53
|
-
# created_at is marked required, but to skip on nil.
|
|
54
|
-
# This will preserve its existing value when we update the webhook.
|
|
55
|
-
resource["created_at"] = nil if event&.fetch("event") == "updated"
|
|
56
|
-
return super
|
|
57
|
-
end
|
|
58
|
-
|
|
59
|
-
def _upsert_update_expr(inserting, enrichment: nil)
|
|
60
|
-
update = super
|
|
61
|
-
update[:data] = Sequel.lit("#{self.service_integration.table_name}.data || excluded.data")
|
|
62
|
-
return update
|
|
63
|
-
end
|
|
64
|
-
|
|
65
|
-
def _update_where_expr
|
|
66
|
-
return self.qualified_table_sequel_identifier[:updated_at] < Sequel[:excluded][:updated_at]
|
|
67
|
-
end
|
|
68
|
-
|
|
69
|
-
def _resource_and_event(request)
|
|
70
|
-
resource, event = self._find_resource_and_event(request.body, "ach_transfer")
|
|
71
|
-
return nil, nil if (resource && resource["type"]) == "inbound_ach_transfer"
|
|
72
|
-
return resource, event
|
|
73
|
-
end
|
|
74
|
-
|
|
75
|
-
def _mixin_backfill_url
|
|
76
|
-
return "#{self.service_integration.api_url}/transfers/achs"
|
|
77
|
-
end
|
|
39
|
+
def _mixin_object_type = "ach_transfer"
|
|
78
40
|
end
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
class Webhookdb::Replicator::IncreaseAppV1 < Webhookdb::Replicator::Base
|
|
4
|
+
include Appydays::Loggable
|
|
5
|
+
|
|
6
|
+
# @return [Webhookdb::Replicator::Descriptor]
|
|
7
|
+
def self.descriptor
|
|
8
|
+
return Webhookdb::Replicator::Descriptor.new(
|
|
9
|
+
name: "increase_app_v1",
|
|
10
|
+
ctor: self,
|
|
11
|
+
feature_roles: [],
|
|
12
|
+
resource_name_singular: "Increase App",
|
|
13
|
+
resource_name_plural: "Increase App",
|
|
14
|
+
supports_webhooks: true,
|
|
15
|
+
supports_backfill: true,
|
|
16
|
+
install_url: "#{Webhookdb.api_url}/increase",
|
|
17
|
+
documentation_url: "https://docs.webhookdb.com/guides/increase/",
|
|
18
|
+
description: "Replicate your Increase data to WebhookDB Cloud in one click using " \
|
|
19
|
+
"our [WebhookDB-Increase integration](https://docs.webhookdb.com/guides/increase).",
|
|
20
|
+
)
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def _remote_key_column
|
|
24
|
+
return Webhookdb::Replicator::Column.new(:ignore_id, INTEGER)
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def _denormalized_columns
|
|
28
|
+
return []
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def _upsert_webhook(request, **kw)
|
|
32
|
+
raise Webhookdb::InvalidPrecondition, "can only handle event payloads" unless request.body.fetch("type") == "event"
|
|
33
|
+
dispatchable = self.service_integration.dependents.select do |d|
|
|
34
|
+
d.service_name == "increase_event_v1" || d.replicator.handle_event?(request.body)
|
|
35
|
+
end
|
|
36
|
+
dispatchable.each do |sint|
|
|
37
|
+
sint.replicator.upsert_webhook(request, **kw)
|
|
38
|
+
end
|
|
39
|
+
return nil
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
def _fetch_backfill_page(*)
|
|
43
|
+
return [], nil
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
def webhook_response(request)
|
|
47
|
+
return Webhookdb::Increase.webhook_response(request, Webhookdb::Increase.webhook_secret)
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
def calculate_webhook_state_machine
|
|
51
|
+
return self.calculate_backfill_state_machine
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
def calculate_backfill_state_machine
|
|
55
|
+
step = Webhookdb::Replicator::StateMachineStep.new
|
|
56
|
+
step.output = %(This replicator is managed automatically using OAuth through Increase.
|
|
57
|
+
Head over to #{self.descriptor.install_url} to learn more.)
|
|
58
|
+
step.completed
|
|
59
|
+
return step
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
def build_dependents
|
|
63
|
+
org = self.service_integration.organization
|
|
64
|
+
parent_descr = self.descriptor
|
|
65
|
+
sints = self.service_integration.organization.available_replicators.
|
|
66
|
+
select { |dd| dd.dependency_descriptor == parent_descr }.
|
|
67
|
+
map do |dd|
|
|
68
|
+
Webhookdb::ServiceIntegration.create_disambiguated(
|
|
69
|
+
dd.name,
|
|
70
|
+
organization: org,
|
|
71
|
+
depends_on: self.service_integration,
|
|
72
|
+
)
|
|
73
|
+
end
|
|
74
|
+
sints.
|
|
75
|
+
select { |sint| sint.replicator.descriptor.supports_backfill? }.
|
|
76
|
+
each { |sint| sint.replicator._enqueue_backfill_jobs(incremental: false) }
|
|
77
|
+
end
|
|
78
|
+
end
|
|
@@ -11,10 +11,10 @@ class Webhookdb::Replicator::IncreaseCheckTransferV1 < Webhookdb::Replicator::Ba
|
|
|
11
11
|
def self.descriptor
|
|
12
12
|
return Webhookdb::Replicator::Descriptor.new(
|
|
13
13
|
name: "increase_check_transfer_v1",
|
|
14
|
-
ctor:
|
|
14
|
+
ctor: self,
|
|
15
15
|
feature_roles: [],
|
|
16
16
|
resource_name_singular: "Increase Check Transfer",
|
|
17
|
-
|
|
17
|
+
dependency_descriptor: Webhookdb::Replicator::IncreaseAppV1.descriptor,
|
|
18
18
|
supports_backfill: true,
|
|
19
19
|
api_docs_url: "https://increase.com/documentation/api",
|
|
20
20
|
)
|
|
@@ -26,39 +26,33 @@ class Webhookdb::Replicator::IncreaseCheckTransferV1 < Webhookdb::Replicator::Ba
|
|
|
26
26
|
|
|
27
27
|
def _denormalized_columns
|
|
28
28
|
return [
|
|
29
|
+
Webhookdb::Replicator::Column.new(:created_at, TIMESTAMP, index: true),
|
|
30
|
+
Webhookdb::Replicator::Column.new(:updated_at, TIMESTAMP, index: true),
|
|
29
31
|
Webhookdb::Replicator::Column.new(:account_id, TEXT, index: true),
|
|
30
|
-
Webhookdb::Replicator::Column.new(:address_line1, TEXT),
|
|
31
|
-
Webhookdb::Replicator::Column.new(:address_city, TEXT),
|
|
32
|
-
Webhookdb::Replicator::Column.new(:address_state, TEXT),
|
|
33
|
-
Webhookdb::Replicator::Column.new(:address_zip, TEXT, index: true),
|
|
34
32
|
Webhookdb::Replicator::Column.new(:amount, INTEGER, index: true),
|
|
35
|
-
Webhookdb::Replicator::Column.new(:
|
|
36
|
-
Webhookdb::Replicator::Column.new(:
|
|
37
|
-
Webhookdb::Replicator::Column.new(:
|
|
33
|
+
Webhookdb::Replicator::Column.new(:account_number, TEXT, index: true),
|
|
34
|
+
Webhookdb::Replicator::Column.new(:routing_number, TEXT, index: true),
|
|
35
|
+
Webhookdb::Replicator::Column.new(:check_number, TEXT, index: true),
|
|
36
|
+
Webhookdb::Replicator::Column.new(
|
|
37
|
+
:recipient_name,
|
|
38
|
+
TEXT,
|
|
39
|
+
data_key: ["physical_check", "recipient_name"], optional: true,
|
|
40
|
+
),
|
|
38
41
|
Webhookdb::Replicator::Column.new(:status, TEXT),
|
|
39
|
-
Webhookdb::Replicator::Column.new(:submitted_at, TIMESTAMP, index: true),
|
|
40
|
-
Webhookdb::Replicator::Column.new(:template_id, TEXT),
|
|
41
|
-
Webhookdb::Replicator::Column.new(:transaction_id, TEXT, index: true),
|
|
42
42
|
Webhookdb::Replicator::Column.new(
|
|
43
|
-
:
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
43
|
+
:canceled_at, TIMESTAMP, data_key: ["cancellation", "canceled_at"], optional: true, index: true,
|
|
44
|
+
),
|
|
45
|
+
Webhookdb::Replicator::Column.new(
|
|
46
|
+
:deposited_at, TIMESTAMP, data_key: ["deposit", "deposited_at"], optional: true, index: true,
|
|
47
|
+
),
|
|
48
|
+
Webhookdb::Replicator::Column.new(
|
|
49
|
+
:mailed_at, TIMESTAMP, data_key: ["mailing", "mailed_at"], optional: true, index: true,
|
|
50
|
+
),
|
|
51
|
+
Webhookdb::Replicator::Column.new(
|
|
52
|
+
:submitted_at, TIMESTAMP, data_key: ["submission", "submitted_at"], optional: true, index: true,
|
|
49
53
|
),
|
|
50
54
|
]
|
|
51
55
|
end
|
|
52
56
|
|
|
53
|
-
def
|
|
54
|
-
return self.qualified_table_sequel_identifier[:updated_at] < Sequel[:excluded][:updated_at]
|
|
55
|
-
end
|
|
56
|
-
|
|
57
|
-
def _resource_and_event(request)
|
|
58
|
-
return self._find_resource_and_event(request.body, "check_transfer")
|
|
59
|
-
end
|
|
60
|
-
|
|
61
|
-
def _mixin_backfill_url
|
|
62
|
-
return "#{self.service_integration.api_url}/check_transfers"
|
|
63
|
-
end
|
|
57
|
+
def _mixin_object_type = "check_transfer"
|
|
64
58
|
end
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
class Webhookdb::Replicator::IncreaseEventV1 < Webhookdb::Replicator::Base
|
|
4
|
+
include Appydays::Loggable
|
|
5
|
+
include Webhookdb::Replicator::IncreaseV1Mixin
|
|
6
|
+
|
|
7
|
+
# @return [Webhookdb::Replicator::Descriptor]
|
|
8
|
+
def self.descriptor
|
|
9
|
+
return Webhookdb::Replicator::Descriptor.new(
|
|
10
|
+
name: "increase_event_v1",
|
|
11
|
+
ctor: self,
|
|
12
|
+
feature_roles: [],
|
|
13
|
+
resource_name_singular: "Increase Event",
|
|
14
|
+
dependency_descriptor: Webhookdb::Replicator::IncreaseAppV1.descriptor,
|
|
15
|
+
# Since events are only done through the increase_app_v1,
|
|
16
|
+
# we don't support normal WebhookDB webhooks. Instead,
|
|
17
|
+
# they come in via the app. If we wanted to handle webhooks to the normal
|
|
18
|
+
# /v1/service_integrations/:opaque_id endpoint, rather than /v1/install/increase/webhook,
|
|
19
|
+
# we'd make this 'true' and have to do work like webhook validation.
|
|
20
|
+
# supports_webhooks: false,
|
|
21
|
+
supports_backfill: true,
|
|
22
|
+
api_docs_url: "https://increase.com/documentation/api",
|
|
23
|
+
)
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def _remote_key_column
|
|
27
|
+
return Webhookdb::Replicator::Column.new(:increase_id, TEXT, data_key: "id")
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def _denormalized_columns
|
|
31
|
+
return [
|
|
32
|
+
Webhookdb::Replicator::Column.new(:associated_object_id, TEXT, index: true),
|
|
33
|
+
Webhookdb::Replicator::Column.new(:associated_object_type, TEXT),
|
|
34
|
+
Webhookdb::Replicator::Column.new(:category, TEXT, index: true),
|
|
35
|
+
Webhookdb::Replicator::Column.new(:created_at, TIMESTAMP, index: true),
|
|
36
|
+
]
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
def _timestamp_column_name = :created_at
|
|
40
|
+
def _mixin_object_type = "event"
|
|
41
|
+
end
|
|
@@ -11,10 +11,13 @@ class Webhookdb::Replicator::IncreaseLimitV1 < Webhookdb::Replicator::Base
|
|
|
11
11
|
def self.descriptor
|
|
12
12
|
return Webhookdb::Replicator::Descriptor.new(
|
|
13
13
|
name: "increase_limit_v1",
|
|
14
|
-
ctor:
|
|
15
|
-
|
|
14
|
+
ctor: self,
|
|
15
|
+
# This is a legacy resource. Instead, users should set the 'allow/deny ACH debits' flag on account numbers,
|
|
16
|
+
# or use the Inbound ACH Transfer object, which can send a webhook to accept or reject it.
|
|
17
|
+
# This flag is here for WebhookDB users who still need access to Limit resources.
|
|
18
|
+
feature_roles: ["increase_limits"],
|
|
16
19
|
resource_name_singular: "Increase Limit",
|
|
17
|
-
|
|
20
|
+
dependency_descriptor: Webhookdb::Replicator::IncreaseAppV1.descriptor,
|
|
18
21
|
supports_backfill: true,
|
|
19
22
|
api_docs_url: "https://increase.com/documentation/api",
|
|
20
23
|
)
|
|
@@ -34,45 +37,17 @@ class Webhookdb::Replicator::IncreaseLimitV1 < Webhookdb::Replicator::Base
|
|
|
34
37
|
:row_created_at,
|
|
35
38
|
TIMESTAMP,
|
|
36
39
|
data_key: "created_at",
|
|
37
|
-
event_key: "created_at",
|
|
38
|
-
defaulter: :now,
|
|
39
|
-
optional: true,
|
|
40
|
-
index: true,
|
|
41
|
-
),
|
|
42
|
-
Webhookdb::Replicator::Column.new(
|
|
43
|
-
:row_updated_at,
|
|
44
|
-
TIMESTAMP,
|
|
45
|
-
data_key: "created_at",
|
|
46
|
-
event_key: "created_at",
|
|
47
40
|
defaulter: :now,
|
|
48
41
|
optional: true,
|
|
49
42
|
index: true,
|
|
50
43
|
),
|
|
44
|
+
Webhookdb::Replicator::Column.new(:row_updated_at, TIMESTAMP, data_key: "updated_at", index: true),
|
|
51
45
|
Webhookdb::Replicator::Column.new(:status, TEXT),
|
|
52
46
|
Webhookdb::Replicator::Column.new(:value, INTEGER),
|
|
53
47
|
]
|
|
54
48
|
end
|
|
55
49
|
|
|
56
|
-
def _timestamp_column_name
|
|
57
|
-
return :row_updated_at
|
|
58
|
-
end
|
|
50
|
+
def _timestamp_column_name = :row_updated_at
|
|
59
51
|
|
|
60
|
-
def
|
|
61
|
-
return self.qualified_table_sequel_identifier[:row_updated_at] < Sequel[:excluded][:row_updated_at]
|
|
62
|
-
end
|
|
63
|
-
|
|
64
|
-
def _resource_and_event(request)
|
|
65
|
-
return self._find_resource_and_event(request.body, "limit")
|
|
66
|
-
end
|
|
67
|
-
|
|
68
|
-
def _upsert_update_expr(inserting, **_kwargs)
|
|
69
|
-
update = super
|
|
70
|
-
# Only set created_at if it's not set so the initial insert isn't modified.
|
|
71
|
-
self._coalesce_excluded_on_update(update, [:row_created_at])
|
|
72
|
-
return update
|
|
73
|
-
end
|
|
74
|
-
|
|
75
|
-
def _mixin_backfill_url
|
|
76
|
-
return "#{self.service_integration.api_url}/limits"
|
|
77
|
-
end
|
|
52
|
+
def _mixin_object_type = "limit"
|
|
78
53
|
end
|