webhookdb 0.1.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.
Files changed (364) hide show
  1. checksums.yaml +7 -0
  2. data/data/messages/layouts/blank.email.liquid +10 -0
  3. data/data/messages/layouts/minimal.email.liquid +28 -0
  4. data/data/messages/layouts/standard.email.liquid +28 -0
  5. data/data/messages/partials/button.liquid +15 -0
  6. data/data/messages/partials/environment_banner.liquid +9 -0
  7. data/data/messages/partials/footer.liquid +22 -0
  8. data/data/messages/partials/greeting.liquid +3 -0
  9. data/data/messages/partials/logo_header.liquid +18 -0
  10. data/data/messages/partials/signoff.liquid +1 -0
  11. data/data/messages/styles/v1.liquid +346 -0
  12. data/data/messages/templates/errors/icalendar_fetch.email.liquid +29 -0
  13. data/data/messages/templates/invite.email.liquid +15 -0
  14. data/data/messages/templates/new_customer.email.liquid +24 -0
  15. data/data/messages/templates/org_database_migration_finished.email.liquid +7 -0
  16. data/data/messages/templates/org_database_migration_started.email.liquid +9 -0
  17. data/data/messages/templates/specs/_field_partial.liquid +1 -0
  18. data/data/messages/templates/specs/basic.email.liquid +2 -0
  19. data/data/messages/templates/specs/basic.fake.liquid +1 -0
  20. data/data/messages/templates/specs/with_field.email.liquid +2 -0
  21. data/data/messages/templates/specs/with_field.fake.liquid +1 -0
  22. data/data/messages/templates/specs/with_include.email.liquid +2 -0
  23. data/data/messages/templates/specs/with_partial.email.liquid +1 -0
  24. data/data/messages/templates/verification.email.liquid +14 -0
  25. data/data/messages/templates/verification.sms.liquid +1 -0
  26. data/data/messages/web/install-customer-login.liquid +48 -0
  27. data/data/messages/web/install-error.liquid +17 -0
  28. data/data/messages/web/install-success.liquid +35 -0
  29. data/data/messages/web/install.liquid +20 -0
  30. data/data/messages/web/partials/footer.liquid +4 -0
  31. data/data/messages/web/partials/form_error.liquid +1 -0
  32. data/data/messages/web/partials/header.liquid +3 -0
  33. data/data/messages/web/styles.liquid +134 -0
  34. data/data/windows_tz.txt +461 -0
  35. data/db/migrations/001_testing_pixies.rb +13 -0
  36. data/db/migrations/002_initial.rb +132 -0
  37. data/db/migrations/003_ux_overhaul.rb +20 -0
  38. data/db/migrations/004_incremental_backfill.rb +9 -0
  39. data/db/migrations/005_log_webhooks.rb +24 -0
  40. data/db/migrations/006_generalize_roles.rb +29 -0
  41. data/db/migrations/007_org_dns.rb +12 -0
  42. data/db/migrations/008_webhook_subscriptions.rb +19 -0
  43. data/db/migrations/009_nonunique_stripe_subscription_customer.rb +16 -0
  44. data/db/migrations/010_drop_integration_soft_delete.rb +14 -0
  45. data/db/migrations/011_webhook_subscriptions_created_at.rb +10 -0
  46. data/db/migrations/012_webhook_subscriptions_created_by.rb +9 -0
  47. data/db/migrations/013_default_org_membership.rb +30 -0
  48. data/db/migrations/014_webhook_subscription_deliveries.rb +26 -0
  49. data/db/migrations/015_dependent_integrations.rb +9 -0
  50. data/db/migrations/016_encrypted_columns.rb +9 -0
  51. data/db/migrations/017_skip_verification.rb +9 -0
  52. data/db/migrations/018_sync_targets.rb +25 -0
  53. data/db/migrations/019_org_schema.rb +9 -0
  54. data/db/migrations/020_org_database_migrations.rb +25 -0
  55. data/db/migrations/021_no_default_org_schema.rb +14 -0
  56. data/db/migrations/022_database_document.rb +15 -0
  57. data/db/migrations/023_sync_target_schema.rb +9 -0
  58. data/db/migrations/024_org_semaphore_jobs.rb +9 -0
  59. data/db/migrations/025_integration_backfill_cursor.rb +9 -0
  60. data/db/migrations/026_undo_integration_backfill_cursor.rb +9 -0
  61. data/db/migrations/027_sync_target_http_sync.rb +12 -0
  62. data/db/migrations/028_logged_webhook_path.rb +24 -0
  63. data/db/migrations/029_encrypt_columns.rb +97 -0
  64. data/db/migrations/030_org_sync_target_timeout.rb +9 -0
  65. data/db/migrations/031_org_max_query_rows.rb +9 -0
  66. data/db/migrations/032_remove_db_defaults.rb +12 -0
  67. data/db/migrations/033_backfill_jobs.rb +26 -0
  68. data/db/migrations/034_backfill_job_criteria.rb +9 -0
  69. data/db/migrations/035_synchronous_backfill.rb +9 -0
  70. data/db/migrations/036_oauth.rb +26 -0
  71. data/db/migrations/037_oauth_used.rb +9 -0
  72. data/lib/amigo/durable_job.rb +416 -0
  73. data/lib/pry/clipboard.rb +111 -0
  74. data/lib/sequel/advisory_lock.rb +65 -0
  75. data/lib/webhookdb/admin.rb +4 -0
  76. data/lib/webhookdb/admin_api/auth.rb +36 -0
  77. data/lib/webhookdb/admin_api/customers.rb +63 -0
  78. data/lib/webhookdb/admin_api/database_documents.rb +20 -0
  79. data/lib/webhookdb/admin_api/entities.rb +66 -0
  80. data/lib/webhookdb/admin_api/message_deliveries.rb +61 -0
  81. data/lib/webhookdb/admin_api/roles.rb +15 -0
  82. data/lib/webhookdb/admin_api.rb +34 -0
  83. data/lib/webhookdb/aggregate_result.rb +63 -0
  84. data/lib/webhookdb/api/auth.rb +122 -0
  85. data/lib/webhookdb/api/connstr_auth.rb +36 -0
  86. data/lib/webhookdb/api/db.rb +188 -0
  87. data/lib/webhookdb/api/demo.rb +14 -0
  88. data/lib/webhookdb/api/entities.rb +198 -0
  89. data/lib/webhookdb/api/helpers.rb +253 -0
  90. data/lib/webhookdb/api/install.rb +296 -0
  91. data/lib/webhookdb/api/me.rb +53 -0
  92. data/lib/webhookdb/api/organizations.rb +254 -0
  93. data/lib/webhookdb/api/replay.rb +64 -0
  94. data/lib/webhookdb/api/service_integrations.rb +402 -0
  95. data/lib/webhookdb/api/services.rb +27 -0
  96. data/lib/webhookdb/api/stripe.rb +22 -0
  97. data/lib/webhookdb/api/subscriptions.rb +67 -0
  98. data/lib/webhookdb/api/sync_targets.rb +232 -0
  99. data/lib/webhookdb/api/system.rb +37 -0
  100. data/lib/webhookdb/api/webhook_subscriptions.rb +96 -0
  101. data/lib/webhookdb/api.rb +92 -0
  102. data/lib/webhookdb/apps.rb +93 -0
  103. data/lib/webhookdb/async/audit_logger.rb +38 -0
  104. data/lib/webhookdb/async/autoscaler.rb +84 -0
  105. data/lib/webhookdb/async/job.rb +18 -0
  106. data/lib/webhookdb/async/job_logger.rb +45 -0
  107. data/lib/webhookdb/async/scheduled_job.rb +18 -0
  108. data/lib/webhookdb/async.rb +142 -0
  109. data/lib/webhookdb/aws.rb +98 -0
  110. data/lib/webhookdb/backfill_job.rb +107 -0
  111. data/lib/webhookdb/backfiller.rb +107 -0
  112. data/lib/webhookdb/cloudflare.rb +39 -0
  113. data/lib/webhookdb/connection_cache.rb +177 -0
  114. data/lib/webhookdb/console.rb +71 -0
  115. data/lib/webhookdb/convertkit.rb +14 -0
  116. data/lib/webhookdb/crypto.rb +66 -0
  117. data/lib/webhookdb/customer/reset_code.rb +94 -0
  118. data/lib/webhookdb/customer.rb +347 -0
  119. data/lib/webhookdb/database_document.rb +72 -0
  120. data/lib/webhookdb/db_adapter/column_types.rb +37 -0
  121. data/lib/webhookdb/db_adapter/default_sql.rb +187 -0
  122. data/lib/webhookdb/db_adapter/pg.rb +96 -0
  123. data/lib/webhookdb/db_adapter/snowflake.rb +137 -0
  124. data/lib/webhookdb/db_adapter.rb +208 -0
  125. data/lib/webhookdb/dbutil.rb +92 -0
  126. data/lib/webhookdb/demo_mode.rb +100 -0
  127. data/lib/webhookdb/developer_alert.rb +51 -0
  128. data/lib/webhookdb/email_octopus.rb +21 -0
  129. data/lib/webhookdb/enumerable.rb +18 -0
  130. data/lib/webhookdb/fixtures/backfill_jobs.rb +72 -0
  131. data/lib/webhookdb/fixtures/customers.rb +65 -0
  132. data/lib/webhookdb/fixtures/database_documents.rb +27 -0
  133. data/lib/webhookdb/fixtures/faker.rb +41 -0
  134. data/lib/webhookdb/fixtures/logged_webhooks.rb +56 -0
  135. data/lib/webhookdb/fixtures/message_deliveries.rb +59 -0
  136. data/lib/webhookdb/fixtures/oauth_sessions.rb +24 -0
  137. data/lib/webhookdb/fixtures/organization_database_migrations.rb +37 -0
  138. data/lib/webhookdb/fixtures/organization_memberships.rb +54 -0
  139. data/lib/webhookdb/fixtures/organizations.rb +32 -0
  140. data/lib/webhookdb/fixtures/reset_codes.rb +23 -0
  141. data/lib/webhookdb/fixtures/service_integrations.rb +42 -0
  142. data/lib/webhookdb/fixtures/subscriptions.rb +33 -0
  143. data/lib/webhookdb/fixtures/sync_targets.rb +32 -0
  144. data/lib/webhookdb/fixtures/webhook_subscriptions.rb +35 -0
  145. data/lib/webhookdb/fixtures.rb +15 -0
  146. data/lib/webhookdb/formatting.rb +56 -0
  147. data/lib/webhookdb/front.rb +49 -0
  148. data/lib/webhookdb/github.rb +22 -0
  149. data/lib/webhookdb/google_calendar.rb +29 -0
  150. data/lib/webhookdb/heroku.rb +21 -0
  151. data/lib/webhookdb/http.rb +114 -0
  152. data/lib/webhookdb/icalendar.rb +17 -0
  153. data/lib/webhookdb/id.rb +17 -0
  154. data/lib/webhookdb/idempotency.rb +90 -0
  155. data/lib/webhookdb/increase.rb +42 -0
  156. data/lib/webhookdb/intercom.rb +23 -0
  157. data/lib/webhookdb/jobs/amigo_test_jobs.rb +118 -0
  158. data/lib/webhookdb/jobs/backfill.rb +32 -0
  159. data/lib/webhookdb/jobs/create_mirror_table.rb +18 -0
  160. data/lib/webhookdb/jobs/create_stripe_customer.rb +17 -0
  161. data/lib/webhookdb/jobs/customer_created_notify_internal.rb +22 -0
  162. data/lib/webhookdb/jobs/demo_mode_sync_data.rb +19 -0
  163. data/lib/webhookdb/jobs/deprecated_jobs.rb +19 -0
  164. data/lib/webhookdb/jobs/developer_alert_handle.rb +14 -0
  165. data/lib/webhookdb/jobs/durable_job_recheck_poller.rb +17 -0
  166. data/lib/webhookdb/jobs/emailer.rb +15 -0
  167. data/lib/webhookdb/jobs/icalendar_enqueue_syncs.rb +25 -0
  168. data/lib/webhookdb/jobs/icalendar_sync.rb +23 -0
  169. data/lib/webhookdb/jobs/logged_webhook_replay.rb +17 -0
  170. data/lib/webhookdb/jobs/logged_webhook_resilient_replay.rb +15 -0
  171. data/lib/webhookdb/jobs/message_dispatched.rb +16 -0
  172. data/lib/webhookdb/jobs/organization_database_migration_notify_finished.rb +21 -0
  173. data/lib/webhookdb/jobs/organization_database_migration_notify_started.rb +21 -0
  174. data/lib/webhookdb/jobs/organization_database_migration_run.rb +24 -0
  175. data/lib/webhookdb/jobs/prepare_database_connections.rb +22 -0
  176. data/lib/webhookdb/jobs/process_webhook.rb +47 -0
  177. data/lib/webhookdb/jobs/renew_watch_channel.rb +24 -0
  178. data/lib/webhookdb/jobs/replication_migration.rb +24 -0
  179. data/lib/webhookdb/jobs/reset_code_create_dispatch.rb +23 -0
  180. data/lib/webhookdb/jobs/scheduled_backfills.rb +77 -0
  181. data/lib/webhookdb/jobs/send_invite.rb +15 -0
  182. data/lib/webhookdb/jobs/send_test_webhook.rb +25 -0
  183. data/lib/webhookdb/jobs/send_webhook.rb +20 -0
  184. data/lib/webhookdb/jobs/sync_target_enqueue_scheduled.rb +16 -0
  185. data/lib/webhookdb/jobs/sync_target_run_sync.rb +38 -0
  186. data/lib/webhookdb/jobs/trim_logged_webhooks.rb +15 -0
  187. data/lib/webhookdb/jobs/webhook_resource_notify_integrations.rb +30 -0
  188. data/lib/webhookdb/jobs/webhook_subscription_delivery_attempt.rb +29 -0
  189. data/lib/webhookdb/jobs.rb +4 -0
  190. data/lib/webhookdb/json.rb +113 -0
  191. data/lib/webhookdb/liquid/expose.rb +27 -0
  192. data/lib/webhookdb/liquid/filters.rb +16 -0
  193. data/lib/webhookdb/liquid/liquification.rb +26 -0
  194. data/lib/webhookdb/liquid/partial.rb +12 -0
  195. data/lib/webhookdb/logged_webhook/resilient.rb +95 -0
  196. data/lib/webhookdb/logged_webhook.rb +194 -0
  197. data/lib/webhookdb/message/body.rb +25 -0
  198. data/lib/webhookdb/message/delivery.rb +127 -0
  199. data/lib/webhookdb/message/email_transport.rb +133 -0
  200. data/lib/webhookdb/message/fake_transport.rb +54 -0
  201. data/lib/webhookdb/message/liquid_drops.rb +29 -0
  202. data/lib/webhookdb/message/template.rb +89 -0
  203. data/lib/webhookdb/message/transport.rb +43 -0
  204. data/lib/webhookdb/message.rb +150 -0
  205. data/lib/webhookdb/messages/error_icalendar_fetch.rb +42 -0
  206. data/lib/webhookdb/messages/invite.rb +23 -0
  207. data/lib/webhookdb/messages/new_customer.rb +14 -0
  208. data/lib/webhookdb/messages/org_database_migration_finished.rb +23 -0
  209. data/lib/webhookdb/messages/org_database_migration_started.rb +24 -0
  210. data/lib/webhookdb/messages/specs.rb +57 -0
  211. data/lib/webhookdb/messages/verification.rb +23 -0
  212. data/lib/webhookdb/method_utilities.rb +82 -0
  213. data/lib/webhookdb/microsoft_calendar.rb +36 -0
  214. data/lib/webhookdb/nextpax.rb +14 -0
  215. data/lib/webhookdb/oauth/front.rb +58 -0
  216. data/lib/webhookdb/oauth/intercom.rb +58 -0
  217. data/lib/webhookdb/oauth/session.rb +24 -0
  218. data/lib/webhookdb/oauth.rb +80 -0
  219. data/lib/webhookdb/organization/alerting.rb +35 -0
  220. data/lib/webhookdb/organization/database_migration.rb +151 -0
  221. data/lib/webhookdb/organization/db_builder.rb +429 -0
  222. data/lib/webhookdb/organization.rb +506 -0
  223. data/lib/webhookdb/organization_membership.rb +58 -0
  224. data/lib/webhookdb/phone_number.rb +38 -0
  225. data/lib/webhookdb/plaid.rb +23 -0
  226. data/lib/webhookdb/platform.rb +27 -0
  227. data/lib/webhookdb/plivo.rb +52 -0
  228. data/lib/webhookdb/postgres/maintenance.rb +166 -0
  229. data/lib/webhookdb/postgres/model.rb +82 -0
  230. data/lib/webhookdb/postgres/model_utilities.rb +382 -0
  231. data/lib/webhookdb/postgres/testing_pixie.rb +16 -0
  232. data/lib/webhookdb/postgres/validations.rb +46 -0
  233. data/lib/webhookdb/postgres.rb +176 -0
  234. data/lib/webhookdb/postmark.rb +20 -0
  235. data/lib/webhookdb/redis.rb +35 -0
  236. data/lib/webhookdb/replicator/atom_single_feed_v1.rb +116 -0
  237. data/lib/webhookdb/replicator/aws_pricing_v1.rb +488 -0
  238. data/lib/webhookdb/replicator/base.rb +1185 -0
  239. data/lib/webhookdb/replicator/column.rb +482 -0
  240. data/lib/webhookdb/replicator/convertkit_broadcast_v1.rb +69 -0
  241. data/lib/webhookdb/replicator/convertkit_subscriber_v1.rb +200 -0
  242. data/lib/webhookdb/replicator/convertkit_tag_v1.rb +66 -0
  243. data/lib/webhookdb/replicator/convertkit_v1_mixin.rb +65 -0
  244. data/lib/webhookdb/replicator/docgen.rb +167 -0
  245. data/lib/webhookdb/replicator/email_octopus_campaign_v1.rb +84 -0
  246. data/lib/webhookdb/replicator/email_octopus_contact_v1.rb +159 -0
  247. data/lib/webhookdb/replicator/email_octopus_event_v1.rb +244 -0
  248. data/lib/webhookdb/replicator/email_octopus_list_v1.rb +101 -0
  249. data/lib/webhookdb/replicator/fake.rb +453 -0
  250. data/lib/webhookdb/replicator/front_conversation_v1.rb +45 -0
  251. data/lib/webhookdb/replicator/front_marketplace_root_v1.rb +55 -0
  252. data/lib/webhookdb/replicator/front_message_v1.rb +45 -0
  253. data/lib/webhookdb/replicator/front_v1_mixin.rb +22 -0
  254. data/lib/webhookdb/replicator/github_issue_comment_v1.rb +58 -0
  255. data/lib/webhookdb/replicator/github_issue_v1.rb +83 -0
  256. data/lib/webhookdb/replicator/github_pull_v1.rb +84 -0
  257. data/lib/webhookdb/replicator/github_release_v1.rb +47 -0
  258. data/lib/webhookdb/replicator/github_repo_v1_mixin.rb +250 -0
  259. data/lib/webhookdb/replicator/github_repository_event_v1.rb +45 -0
  260. data/lib/webhookdb/replicator/icalendar_calendar_v1.rb +465 -0
  261. data/lib/webhookdb/replicator/icalendar_event_v1.rb +334 -0
  262. data/lib/webhookdb/replicator/increase_account_number_v1.rb +77 -0
  263. data/lib/webhookdb/replicator/increase_account_transfer_v1.rb +61 -0
  264. data/lib/webhookdb/replicator/increase_account_v1.rb +63 -0
  265. data/lib/webhookdb/replicator/increase_ach_transfer_v1.rb +78 -0
  266. data/lib/webhookdb/replicator/increase_check_transfer_v1.rb +64 -0
  267. data/lib/webhookdb/replicator/increase_limit_v1.rb +78 -0
  268. data/lib/webhookdb/replicator/increase_transaction_v1.rb +74 -0
  269. data/lib/webhookdb/replicator/increase_v1_mixin.rb +121 -0
  270. data/lib/webhookdb/replicator/increase_wire_transfer_v1.rb +61 -0
  271. data/lib/webhookdb/replicator/intercom_contact_v1.rb +36 -0
  272. data/lib/webhookdb/replicator/intercom_conversation_v1.rb +38 -0
  273. data/lib/webhookdb/replicator/intercom_marketplace_root_v1.rb +69 -0
  274. data/lib/webhookdb/replicator/intercom_v1_mixin.rb +105 -0
  275. data/lib/webhookdb/replicator/oauth_refresh_access_token_mixin.rb +65 -0
  276. data/lib/webhookdb/replicator/plivo_sms_inbound_v1.rb +102 -0
  277. data/lib/webhookdb/replicator/postmark_inbound_message_v1.rb +94 -0
  278. data/lib/webhookdb/replicator/postmark_outbound_message_event_v1.rb +107 -0
  279. data/lib/webhookdb/replicator/schema_modification.rb +42 -0
  280. data/lib/webhookdb/replicator/shopify_customer_v1.rb +58 -0
  281. data/lib/webhookdb/replicator/shopify_order_v1.rb +64 -0
  282. data/lib/webhookdb/replicator/shopify_v1_mixin.rb +161 -0
  283. data/lib/webhookdb/replicator/signalwire_message_v1.rb +169 -0
  284. data/lib/webhookdb/replicator/sponsy_customer_v1.rb +54 -0
  285. data/lib/webhookdb/replicator/sponsy_placement_v1.rb +34 -0
  286. data/lib/webhookdb/replicator/sponsy_publication_v1.rb +125 -0
  287. data/lib/webhookdb/replicator/sponsy_slot_v1.rb +41 -0
  288. data/lib/webhookdb/replicator/sponsy_status_v1.rb +35 -0
  289. data/lib/webhookdb/replicator/sponsy_v1_mixin.rb +165 -0
  290. data/lib/webhookdb/replicator/state_machine_step.rb +69 -0
  291. data/lib/webhookdb/replicator/stripe_charge_v1.rb +77 -0
  292. data/lib/webhookdb/replicator/stripe_coupon_v1.rb +62 -0
  293. data/lib/webhookdb/replicator/stripe_customer_v1.rb +60 -0
  294. data/lib/webhookdb/replicator/stripe_dispute_v1.rb +77 -0
  295. data/lib/webhookdb/replicator/stripe_invoice_item_v1.rb +82 -0
  296. data/lib/webhookdb/replicator/stripe_invoice_v1.rb +116 -0
  297. data/lib/webhookdb/replicator/stripe_payout_v1.rb +67 -0
  298. data/lib/webhookdb/replicator/stripe_price_v1.rb +60 -0
  299. data/lib/webhookdb/replicator/stripe_product_v1.rb +60 -0
  300. data/lib/webhookdb/replicator/stripe_refund_v1.rb +101 -0
  301. data/lib/webhookdb/replicator/stripe_subscription_item_v1.rb +56 -0
  302. data/lib/webhookdb/replicator/stripe_subscription_v1.rb +75 -0
  303. data/lib/webhookdb/replicator/stripe_v1_mixin.rb +116 -0
  304. data/lib/webhookdb/replicator/transistor_episode_stats_v1.rb +141 -0
  305. data/lib/webhookdb/replicator/transistor_episode_v1.rb +169 -0
  306. data/lib/webhookdb/replicator/transistor_show_v1.rb +68 -0
  307. data/lib/webhookdb/replicator/transistor_v1_mixin.rb +65 -0
  308. data/lib/webhookdb/replicator/twilio_sms_v1.rb +156 -0
  309. data/lib/webhookdb/replicator/webhook_request.rb +5 -0
  310. data/lib/webhookdb/replicator/webhookdb_customer_v1.rb +74 -0
  311. data/lib/webhookdb/replicator.rb +224 -0
  312. data/lib/webhookdb/role.rb +42 -0
  313. data/lib/webhookdb/sentry.rb +35 -0
  314. data/lib/webhookdb/service/auth.rb +138 -0
  315. data/lib/webhookdb/service/collection.rb +91 -0
  316. data/lib/webhookdb/service/entities.rb +97 -0
  317. data/lib/webhookdb/service/helpers.rb +270 -0
  318. data/lib/webhookdb/service/middleware.rb +124 -0
  319. data/lib/webhookdb/service/types.rb +30 -0
  320. data/lib/webhookdb/service/validators.rb +32 -0
  321. data/lib/webhookdb/service/view_api.rb +63 -0
  322. data/lib/webhookdb/service.rb +219 -0
  323. data/lib/webhookdb/service_integration.rb +332 -0
  324. data/lib/webhookdb/shopify.rb +35 -0
  325. data/lib/webhookdb/signalwire.rb +13 -0
  326. data/lib/webhookdb/slack.rb +68 -0
  327. data/lib/webhookdb/snowflake.rb +90 -0
  328. data/lib/webhookdb/spec_helpers/async.rb +122 -0
  329. data/lib/webhookdb/spec_helpers/citest.rb +88 -0
  330. data/lib/webhookdb/spec_helpers/integration.rb +121 -0
  331. data/lib/webhookdb/spec_helpers/message.rb +41 -0
  332. data/lib/webhookdb/spec_helpers/postgres.rb +220 -0
  333. data/lib/webhookdb/spec_helpers/service.rb +432 -0
  334. data/lib/webhookdb/spec_helpers/shared_examples_for_columns.rb +56 -0
  335. data/lib/webhookdb/spec_helpers/shared_examples_for_replicators.rb +915 -0
  336. data/lib/webhookdb/spec_helpers/whdb.rb +139 -0
  337. data/lib/webhookdb/spec_helpers.rb +63 -0
  338. data/lib/webhookdb/sponsy.rb +14 -0
  339. data/lib/webhookdb/stripe.rb +37 -0
  340. data/lib/webhookdb/subscription.rb +203 -0
  341. data/lib/webhookdb/sync_target.rb +491 -0
  342. data/lib/webhookdb/tasks/admin.rb +49 -0
  343. data/lib/webhookdb/tasks/annotate.rb +36 -0
  344. data/lib/webhookdb/tasks/db.rb +82 -0
  345. data/lib/webhookdb/tasks/docs.rb +42 -0
  346. data/lib/webhookdb/tasks/fixture.rb +35 -0
  347. data/lib/webhookdb/tasks/message.rb +50 -0
  348. data/lib/webhookdb/tasks/regress.rb +87 -0
  349. data/lib/webhookdb/tasks/release.rb +27 -0
  350. data/lib/webhookdb/tasks/sidekiq.rb +23 -0
  351. data/lib/webhookdb/tasks/specs.rb +64 -0
  352. data/lib/webhookdb/theranest.rb +15 -0
  353. data/lib/webhookdb/transistor.rb +13 -0
  354. data/lib/webhookdb/twilio.rb +13 -0
  355. data/lib/webhookdb/typed_struct.rb +44 -0
  356. data/lib/webhookdb/version.rb +5 -0
  357. data/lib/webhookdb/webhook_response.rb +50 -0
  358. data/lib/webhookdb/webhook_subscription/delivery.rb +82 -0
  359. data/lib/webhookdb/webhook_subscription.rb +226 -0
  360. data/lib/webhookdb/windows_tz.rb +32 -0
  361. data/lib/webhookdb/xml.rb +92 -0
  362. data/lib/webhookdb.rb +224 -0
  363. data/lib/webterm/apps.rb +45 -0
  364. metadata +1129 -0
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "webhookdb/async/job"
4
+ require "stripe"
5
+ require "webhookdb/stripe"
6
+
7
+ class Webhookdb::Jobs::CreateStripeCustomer
8
+ extend Webhookdb::Async::Job
9
+
10
+ on "webhookdb.organization.created"
11
+
12
+ def _perform(event)
13
+ org = self.lookup_model(Webhookdb::Organization, event)
14
+ return if Webhookdb::Subscription.billing_disabled?
15
+ org.register_in_stripe
16
+ end
17
+ end
@@ -0,0 +1,22 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "webhookdb/async/job"
4
+
5
+ class Webhookdb::Jobs::CustomerCreatedNotifyInternal
6
+ extend Webhookdb::Async::Job
7
+
8
+ on "webhookdb.customer.created"
9
+
10
+ def _perform(event)
11
+ customer = self.lookup_model(Webhookdb::Customer, event)
12
+ Webhookdb::DeveloperAlert.new(
13
+ subsystem: "Customer Created",
14
+ emoji: ":hook:",
15
+ fallback: "New customer created: #{customer.inspect}",
16
+ fields: [
17
+ {title: "Id", value: customer.id, short: true},
18
+ {title: "Email", value: customer.email, short: true},
19
+ ],
20
+ ).emit
21
+ end
22
+ end
@@ -0,0 +1,19 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "webhookdb/async/job"
4
+
5
+ class Webhookdb::Jobs::DemoModeSyncData
6
+ extend Webhookdb::Async::Job
7
+
8
+ on "webhookdb.organization.syncdemodata"
9
+
10
+ def _perform(event)
11
+ org = self.lookup_model(Webhookdb::Organization, event)
12
+ if org.admin_connection_url.blank?
13
+ # If PrepareDatabaseConnections hasn't run, we can't sync yet.
14
+ # Retry every 1 second for a couple minutes until we have a database.
15
+ raise Amigo::Retry::OrDie.new(120, 1)
16
+ end
17
+ Webhookdb::DemoMode.sync_demo_data(org)
18
+ end
19
+ end
@@ -0,0 +1,19 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "amigo/deprecated_jobs"
4
+
5
+ Amigo::DeprecatedJobs.install(
6
+ Webhookdb,
7
+ # Put jobs here to die. If you just remove a job in Sidekiq, it may be queued up
8
+ # (like if it's scheduled or retrying),
9
+ # and will fail if the class does not exist.
10
+ #
11
+ # So, make the class exist, but noop so it won't be scheduled and won't be retried.
12
+ # Then it can be deleted later.
13
+ "Jobs::Test::DeprecatedJob",
14
+ "Jobs::ConvertKitBroadcastBackfill",
15
+ "Jobs::ConvertKitSubscriberBackfill",
16
+ "Jobs::ConvertKitTagBackfill",
17
+ "Jobs::RssBackfillPoller",
18
+ "Jobs::TwilioScheduledBackfill",
19
+ )
@@ -0,0 +1,14 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "webhookdb/async/job"
4
+
5
+ class Webhookdb::Jobs::DeveloperAlertHandle
6
+ extend Webhookdb::Async::Job
7
+
8
+ on "webhookdb.developeralert.emitted"
9
+
10
+ def _perform(event)
11
+ alert = Webhookdb::DeveloperAlert.new(**event.payload.first.symbolize_keys)
12
+ alert.handle
13
+ end
14
+ end
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "amigo/durable_job"
4
+ require "webhookdb/async/scheduled_job"
5
+ require "webhookdb/jobs"
6
+
7
+ class Webhookdb::Jobs::DurableJobRecheckPoller
8
+ extend Webhookdb::Async::ScheduledJob
9
+
10
+ cron "*/3 * * * *"
11
+ splay 5
12
+
13
+ def _perform
14
+ return if ENV["DISABLE_DURABLE_JOBS_POLL"]
15
+ Amigo::DurableJob.poll_jobs(self)
16
+ end
17
+ end
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "webhookdb/async/scheduled_job"
4
+
5
+ class Webhookdb::Jobs::Emailer
6
+ extend Webhookdb::Async::ScheduledJob
7
+
8
+ cron "* * * * *"
9
+ splay 5.seconds
10
+
11
+ def _perform
12
+ self.logger.info "Sending pending emails"
13
+ Webhookdb::Message.send_unsent
14
+ end
15
+ end
@@ -0,0 +1,25 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "webhookdb/async/scheduled_job"
4
+ require "webhookdb/jobs"
5
+
6
+ class Webhookdb::Jobs::IcalendarEnqueueSyncs
7
+ extend Webhookdb::Async::ScheduledJob
8
+
9
+ cron "*/30 * * * *" # Every 30 minutes
10
+ splay 30
11
+
12
+ def _perform
13
+ Webhookdb::ServiceIntegration.dataset.where_each(service_name: "icalendar_calendar_v1") do |sint|
14
+ sint.replicator.admin_dataset do |ds|
15
+ sint.replicator.rows_needing_sync(ds).each do |row|
16
+ calendar_external_id = row.fetch(:external_id)
17
+ self.with_log_tags(sint.log_tags) do
18
+ enqueued_job_id = Webhookdb::Jobs::IcalendarSync.perform_async(sint.id, calendar_external_id)
19
+ self.logger.info("enqueued_icalendar_sync", calendar_external_id:, enqueued_job_id:)
20
+ end
21
+ end
22
+ end
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,23 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "webhookdb/async/job"
4
+ require "webhookdb/jobs"
5
+
6
+ class Webhookdb::Jobs::IcalendarSync
7
+ extend Webhookdb::Async::Job
8
+
9
+ sidekiq_options retry: false
10
+
11
+ def perform(sint_id, calendar_external_id)
12
+ sint = self.lookup_model(Webhookdb::ServiceIntegration, sint_id)
13
+ self.with_log_tags(sint.log_tags.merge(calendar_external_id:)) do
14
+ row = sint.replicator.admin_dataset { |ds| ds[external_id: calendar_external_id] }
15
+ if row.nil?
16
+ self.logger.warn("icalendar_sync_row_miss", calendar_external_id:)
17
+ return
18
+ end
19
+ self.logger.info("icalendar_sync_start")
20
+ sint.replicator.sync_row(row)
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "webhookdb/async/job"
4
+ require "webhookdb/jobs"
5
+
6
+ class Webhookdb::Jobs::LoggedWebhooksReplay
7
+ extend Webhookdb::Async::Job
8
+
9
+ on "webhookdb.loggedwebhook.replay"
10
+
11
+ def _perform(event)
12
+ lwh = self.lookup_model(Webhookdb::LoggedWebhook, event)
13
+ self.with_log_tags(service_integration_opaque_id: lwh.service_integration_opaque_id) do
14
+ lwh.retry_one(truncate_successful: true)
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "webhookdb/async/scheduled_job"
4
+ require "webhookdb/jobs"
5
+
6
+ class Webhookdb::Jobs::LoggedWebhooksResilientReplay
7
+ extend Webhookdb::Async::ScheduledJob
8
+
9
+ cron "*/3 * * * *"
10
+ splay 5
11
+
12
+ def _perform
13
+ Webhookdb::LoggedWebhook.resilient_replay
14
+ end
15
+ end
@@ -0,0 +1,16 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "webhookdb/async/job"
4
+
5
+ class Webhookdb::Jobs::MessageDispatched
6
+ extend Webhookdb::Async::Job
7
+
8
+ on "webhookdb.message.delivery.dispatched"
9
+
10
+ def _perform(event)
11
+ delivery = self.lookup_model(Webhookdb::Message::Delivery, event)
12
+ Webhookdb::Idempotency.once_ever.under_key("message-dispatched-#{delivery.id}") do
13
+ delivery.send!
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,21 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "webhookdb/async/job"
4
+ require "webhookdb/messages/org_database_migration_finished"
5
+
6
+ class Webhookdb::Jobs::OrganizationDatabaseMigrationNotifyFinished
7
+ extend Webhookdb::Async::Job
8
+
9
+ on "webhookdb.organization.databasemigration.updated"
10
+
11
+ def _perform(event)
12
+ dbm = self.lookup_model(Webhookdb::Organization::DatabaseMigration, event)
13
+ case event.payload[1]
14
+ when changed(:finished_at, from: nil)
15
+ Webhookdb::Idempotency.once_ever.under_key("org-dbmigration-finish-#{dbm.id}") do
16
+ msg = Webhookdb::Messages::OrgDatabaseMigrationFinished.new(dbm)
17
+ dbm.organization.admin_customers.each { |c| msg.dispatch_email(c) }
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,21 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "webhookdb/async/job"
4
+ require "webhookdb/messages/org_database_migration_started"
5
+
6
+ class Webhookdb::Jobs::OrganizationDatabaseMigrationNotifyStarted
7
+ extend Webhookdb::Async::Job
8
+
9
+ on "webhookdb.organization.databasemigration.updated"
10
+
11
+ def _perform(event)
12
+ dbm = self.lookup_model(Webhookdb::Organization::DatabaseMigration, event)
13
+ case event.payload[1]
14
+ when changed(:started_at, from: nil)
15
+ Webhookdb::Idempotency.once_ever.under_key("org-dbmigration-start-#{dbm.id}") do
16
+ msg = Webhookdb::Messages::OrgDatabaseMigrationStarted.new(dbm)
17
+ dbm.organization.admin_customers.each { |c| msg.dispatch_email(c) }
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,24 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "amigo/durable_job"
4
+ require "webhookdb/async/job"
5
+
6
+ class Webhookdb::Jobs::OrganizationDatabaseMigrationRun
7
+ extend Webhookdb::Async::Job
8
+ include Amigo::DurableJob
9
+
10
+ on "webhookdb.organization.databasemigration.created"
11
+
12
+ def _perform(event)
13
+ dbm = self.lookup_model(Webhookdb::Organization::DatabaseMigration, event)
14
+ self.with_log_tags(
15
+ organization_id: dbm.organization.id,
16
+ organization_name: dbm.organization.name,
17
+ organization_database_migration_id: dbm.id,
18
+ ) do
19
+ dbm.migrate
20
+ rescue Webhookdb::Organization::DatabaseMigration::MigrationAlreadyFinished
21
+ self.logger.warn("org_database_migration_already_finished")
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,22 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "amigo/durable_job"
4
+ require "webhookdb/async/job"
5
+
6
+ class Webhookdb::Jobs::PrepareDatabaseConnections
7
+ extend Webhookdb::Async::Job
8
+ include Amigo::DurableJob
9
+
10
+ on "webhookdb.organization.created"
11
+ sidekiq_options queue: "critical"
12
+
13
+ def _perform(event)
14
+ org = self.lookup_model(Webhookdb::Organization, event)
15
+ org.db.transaction do
16
+ # If creating the public host fails, we end up with an orphaned database,
17
+ # but that's not a big deal- we can eventually see it's empty/unlinked and drop it.
18
+ org.prepare_database_connections
19
+ org.create_public_host_cname
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,47 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "amigo/durable_job"
4
+ require "amigo/queue_backoff_job"
5
+ require "amigo/semaphore_backoff_job"
6
+ require "webhookdb/async/job"
7
+
8
+ class Webhookdb::Jobs::ProcessWebhook
9
+ extend Webhookdb::Async::Job
10
+ include Amigo::DurableJob
11
+ include Amigo::QueueBackoffJob
12
+ include Amigo::SemaphoreBackoffJob
13
+
14
+ on "webhookdb.serviceintegration.webhook"
15
+ sidekiq_options queue: "webhook" # This is usually overridden.
16
+
17
+ def semaphore_expiry = 5.minutes.to_i
18
+ def dependent_queues = ["critical"]
19
+
20
+ def before_perform(*args)
21
+ event = Amigo::Event.from_json(args[0])
22
+ @sint = self.lookup_model(Webhookdb::ServiceIntegration, event)
23
+ end
24
+
25
+ def _perform(event)
26
+ self.with_log_tags(@sint.log_tags) do
27
+ kw = event.payload[1].symbolize_keys
28
+ svc = Webhookdb::Replicator.create(@sint)
29
+ # kwargs contains: :headers, :body, :request_path, :request_method
30
+ req = Webhookdb::Replicator::WebhookRequest.new(
31
+ body: kw.fetch(:body),
32
+ headers: kw.fetch(:headers),
33
+ path: kw.fetch(:request_path),
34
+ method: kw.fetch(:request_method),
35
+ )
36
+ svc.upsert_webhook(req)
37
+ end
38
+ end
39
+
40
+ def semaphore_key
41
+ return "semaphore-procwebhook-#{@sint.organization_id}"
42
+ end
43
+
44
+ def semaphore_size
45
+ return @sint.organization.job_semaphore_size
46
+ end
47
+ end
@@ -0,0 +1,24 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "webhookdb/async/job"
4
+ require "webhookdb/jobs"
5
+
6
+ # Generic helper to renew watch channels, enqueued by replicator-specific jobs
7
+ # like RenewGoogleWatchChannels.
8
+ # Must be emitted with [service integration id, {row_pk:, expirng_before:}]
9
+ # Calls #renew_watch_channel(row_pk:, expiring_before:).
10
+ class Webhookdb::Jobs::RenewWatchChannel
11
+ extend Webhookdb::Async::Job
12
+
13
+ on "webhookdb.serviceintegration.renewwatchchannel"
14
+
15
+ def _perform(event)
16
+ sint = self.lookup_model(Webhookdb::ServiceIntegration, event)
17
+ self.with_log_tags(sint.log_tags) do
18
+ opts = event.payload[1]
19
+ row_pk = opts.fetch("row_pk")
20
+ expiring_before = Time.parse(opts.fetch("expiring_before"))
21
+ sint.replicator.renew_watch_channel(row_pk:, expiring_before:)
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,24 @@
1
+ # frozen_string_literal: true
2
+
3
+ # See Organization::enqueue_migrate_all_replication_tables for more info.
4
+ class Webhookdb::Jobs::ReplicationMigration
5
+ include Sidekiq::Worker
6
+
7
+ def perform(org_id, target_release_created_at)
8
+ (org = Webhookdb::Organization[org_id]) or raise "Organization[#{org_id}] does not exist"
9
+ target_rca = Time.parse(target_release_created_at)
10
+ current_rca = Time.parse(Webhookdb::RELEASE_CREATED_AT)
11
+ if target_rca == current_rca
12
+ self.class.migrate_org(org)
13
+ elsif target_rca > current_rca
14
+ self.class.perform_in(1, org_id, target_release_created_at)
15
+ else
16
+ self.logger.warn("stale_replication_migration_job", target_release_created_at:)
17
+ end
18
+ end
19
+
20
+ # To make mocking easier.
21
+ def self.migrate_org(org)
22
+ org.migrate_replication_tables
23
+ end
24
+ end
@@ -0,0 +1,23 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "webhookdb/async/job"
4
+ require "webhookdb/messages/verification"
5
+
6
+ class Webhookdb::Jobs::ResetCodeCreateDispatch
7
+ extend Webhookdb::Async::Job
8
+
9
+ on "webhookdb.customer.resetcode.created"
10
+
11
+ def _perform(event)
12
+ code = self.lookup_model(Webhookdb::Customer::ResetCode, event)
13
+ Webhookdb::Idempotency.once_ever.under_key("reset-code-#{code.customer_id}-#{code.id}") do
14
+ msg = Webhookdb::Messages::Verification.new(code)
15
+ case code.transport
16
+ when "email"
17
+ msg.dispatch_email(code.customer)
18
+ else
19
+ raise "Unknown transport for #{code.inspect}"
20
+ end
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,77 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Webhookdb::Jobs
4
+ # Create a single way to do the common task of automatic scheduled backfills.
5
+ # Each integration that needs automated backfills can add a specification here.
6
+ module ScheduledBackfills
7
+ Spec = Struct.new(:klass, :service_name, :cron_expr, :splay, :incremental)
8
+
9
+ # @param spec [Spec]
10
+ def self.install(spec)
11
+ cls = Class.new do
12
+ extend Webhookdb::Async::ScheduledJob
13
+
14
+ cron spec.cron_expr
15
+ splay spec.splay
16
+
17
+ define_method(:_perform) do
18
+ Webhookdb::ServiceIntegration.dataset.where_each(service_name: spec.service_name) do |sint|
19
+ Webhookdb::BackfillJob.create(service_integration: sint, incremental: spec.incremental).enqueue
20
+ end
21
+ end
22
+ end
23
+ Webhookdb::Jobs.const_set(spec.klass, cls)
24
+ end
25
+
26
+ [
27
+ Spec.new(
28
+ "ConvertkitBroadcastBackfill", "convertkit_broadcast_v1",
29
+ "10 * * * *", 2.minutes, false,
30
+ ),
31
+ Spec.new(
32
+ "ConvertkitSubscriberBackfill", "convertkit_subscriber_v1",
33
+ "20 * * * *", 2.minutes, true,
34
+ ),
35
+ Spec.new(
36
+ "ConvertkitTagBackfill", "convertkit_tag_v1",
37
+ "30 * * * *", 2.minutes, false,
38
+ ),
39
+ Spec.new(
40
+ "EmailOctopusScheduledBackfill", "email_octopus_list_v1",
41
+ Webhookdb::EmailOctopus.cron_expression, 2.minutes, false,
42
+ ),
43
+ Spec.new(
44
+ "GithubRepoActivityScheduledBackfill", "github_repository_event_v1",
45
+ Webhookdb::Github.activity_cron_expression, 30.seconds, false,
46
+ ),
47
+ Spec.new(
48
+ "IntercomScheduledBackfill", "intercom_marketplace_root_v1",
49
+ "*/1 * * * *", 0, false,
50
+ ),
51
+ Spec.new(
52
+ "AtomSingleFeedPoller", "atom_single_feed_v1",
53
+ "11 * * * *", 10.seconds, true,
54
+ ),
55
+ Spec.new(
56
+ "SponsyScheduledBackfill", "sponsy_publication_v1",
57
+ Webhookdb::Sponsy.cron_expression, 30.seconds, true,
58
+ ),
59
+ Spec.new(
60
+ "TransistorEpisodeBackfill", "transistor_episode_v1",
61
+ Webhookdb::Transistor.episode_cron_expression, 2.minutes, true,
62
+ ),
63
+ Spec.new(
64
+ "TransistorShowBackfill", "transistor_show_v1",
65
+ Webhookdb::Transistor.show_cron_expression, 2.minutes, true,
66
+ ),
67
+ Spec.new(
68
+ "TwilioSmsBackfill", "twilio_sms_v1",
69
+ "*/1 * * * *", 0, true,
70
+ ),
71
+ Spec.new(
72
+ "SignalwireMessageBackfill", "signalwire_message_v1",
73
+ "*/1 * * * *", 0, true,
74
+ ),
75
+ ].each { |sp| self.install(sp) }
76
+ end
77
+ end
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "webhookdb/async/job"
4
+ require "webhookdb/messages/invite"
5
+
6
+ class Webhookdb::Jobs::SendInvite
7
+ extend Webhookdb::Async::Job
8
+
9
+ on "webhookdb.organizationmembership.invite"
10
+
11
+ def _perform(event)
12
+ membership = self.lookup_model(Webhookdb::OrganizationMembership, event)
13
+ Webhookdb::Messages::Invite.new(membership).dispatch(membership.customer)
14
+ end
15
+ end
@@ -0,0 +1,25 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "amigo/queue_backoff_job"
4
+ require "webhookdb/async/job"
5
+
6
+ class Webhookdb::Jobs::SendTestWebhook
7
+ extend Webhookdb::Async::Job
8
+ include Amigo::QueueBackoffJob
9
+
10
+ on "webhookdb.webhooksubscription.test"
11
+ sidekiq_options queue: "netout"
12
+
13
+ # If this job fails for a programmer error,
14
+ # we don't want to retry and randomly send a payload later.
15
+ sidekiq_options retry: false
16
+
17
+ def dependent_queues
18
+ return ["critical"]
19
+ end
20
+
21
+ def _perform(event)
22
+ webhook_sub = self.lookup_model(Webhookdb::WebhookSubscription, event)
23
+ webhook_sub.deliver_test_event
24
+ end
25
+ end
@@ -0,0 +1,20 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "amigo/durable_job"
4
+ require "webhookdb/async/job"
5
+ require "webhookdb/jobs"
6
+
7
+ class Webhookdb::Jobs::SendWebhook
8
+ extend Webhookdb::Async::Job
9
+ include Amigo::DurableJob
10
+
11
+ def _perform(event)
12
+ sint = self.lookup_model(Webhookdb::ServiceIntegration, event)
13
+ self.with_log_tags(sint.log_tags) do
14
+ sint.all_webhook_subscriptions_dataset.to_notify.each do |sub|
15
+ payload = {service_name: sint.service_name, table_name: sint.table_name, **event.payload[1]}
16
+ sub.enqueue_delivery(payload)
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,16 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "webhookdb/async/job"
4
+
5
+ class Webhookdb::Jobs::SyncTargetEnqueueScheduled
6
+ extend Webhookdb::Async::ScheduledJob
7
+
8
+ cron "*/1 * * * *"
9
+ splay 0
10
+
11
+ def _perform
12
+ Webhookdb::SyncTarget.due_for_sync(as_of: Time.now).select(:id, :period_seconds).each do |st|
13
+ Webhookdb::Jobs::SyncTargetRunSync.perform_in(st.jitter, st.id)
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,38 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "amigo/queue_backoff_job"
4
+ require "webhookdb/async/job"
5
+
6
+ class Webhookdb::Jobs::SyncTargetRunSync
7
+ extend Webhookdb::Async::Job
8
+ include Amigo::QueueBackoffJob
9
+
10
+ sidekiq_options queue: "netout"
11
+
12
+ def dependent_queues
13
+ return ["critical"]
14
+ end
15
+
16
+ def perform(sync_target_id)
17
+ stgt = Webhookdb::SyncTarget[sync_target_id]
18
+ if stgt.nil?
19
+ # A sync target may be enqueued, but destroyed before the sync runs.
20
+ # If so, log a warning. We see this on staging a lot,
21
+ # but it does happen on production too, and should be expected.
22
+ self.logger.info("missing_sync_target", sync_target_id:)
23
+ return
24
+ end
25
+ self.with_log_tags(
26
+ sync_target_id: stgt.id,
27
+ sync_target_connection_url: stgt.displaysafe_connection_url,
28
+ sync_target_service_integration_service: stgt.service_integration.service_name,
29
+ sync_target_service_integration_table: stgt.service_integration.table_name,
30
+ ) do
31
+ stgt.run_sync(now: Time.now)
32
+ rescue Webhookdb::SyncTarget::SyncInProgress
33
+ self.logger.info("sync_target_already_in_progress")
34
+ rescue Webhookdb::SyncTarget::Deleted
35
+ self.logger.info("sync_target_deleted")
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "webhookdb/async/scheduled_job"
4
+ require "webhookdb/jobs"
5
+
6
+ class Webhookdb::Jobs::TrimLoggedWebhooks
7
+ extend Webhookdb::Async::ScheduledJob
8
+
9
+ cron "17 8 * * *"
10
+ splay 300
11
+
12
+ def _perform
13
+ Webhookdb::LoggedWebhook.trim
14
+ end
15
+ end