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.
- checksums.yaml +7 -0
- data/data/messages/layouts/blank.email.liquid +10 -0
- data/data/messages/layouts/minimal.email.liquid +28 -0
- data/data/messages/layouts/standard.email.liquid +28 -0
- data/data/messages/partials/button.liquid +15 -0
- data/data/messages/partials/environment_banner.liquid +9 -0
- data/data/messages/partials/footer.liquid +22 -0
- data/data/messages/partials/greeting.liquid +3 -0
- data/data/messages/partials/logo_header.liquid +18 -0
- data/data/messages/partials/signoff.liquid +1 -0
- data/data/messages/styles/v1.liquid +346 -0
- data/data/messages/templates/errors/icalendar_fetch.email.liquid +29 -0
- data/data/messages/templates/invite.email.liquid +15 -0
- data/data/messages/templates/new_customer.email.liquid +24 -0
- data/data/messages/templates/org_database_migration_finished.email.liquid +7 -0
- data/data/messages/templates/org_database_migration_started.email.liquid +9 -0
- data/data/messages/templates/specs/_field_partial.liquid +1 -0
- data/data/messages/templates/specs/basic.email.liquid +2 -0
- data/data/messages/templates/specs/basic.fake.liquid +1 -0
- data/data/messages/templates/specs/with_field.email.liquid +2 -0
- data/data/messages/templates/specs/with_field.fake.liquid +1 -0
- data/data/messages/templates/specs/with_include.email.liquid +2 -0
- data/data/messages/templates/specs/with_partial.email.liquid +1 -0
- data/data/messages/templates/verification.email.liquid +14 -0
- data/data/messages/templates/verification.sms.liquid +1 -0
- data/data/messages/web/install-customer-login.liquid +48 -0
- data/data/messages/web/install-error.liquid +17 -0
- data/data/messages/web/install-success.liquid +35 -0
- data/data/messages/web/install.liquid +20 -0
- data/data/messages/web/partials/footer.liquid +4 -0
- data/data/messages/web/partials/form_error.liquid +1 -0
- data/data/messages/web/partials/header.liquid +3 -0
- data/data/messages/web/styles.liquid +134 -0
- data/data/windows_tz.txt +461 -0
- data/db/migrations/001_testing_pixies.rb +13 -0
- data/db/migrations/002_initial.rb +132 -0
- data/db/migrations/003_ux_overhaul.rb +20 -0
- data/db/migrations/004_incremental_backfill.rb +9 -0
- data/db/migrations/005_log_webhooks.rb +24 -0
- data/db/migrations/006_generalize_roles.rb +29 -0
- data/db/migrations/007_org_dns.rb +12 -0
- data/db/migrations/008_webhook_subscriptions.rb +19 -0
- data/db/migrations/009_nonunique_stripe_subscription_customer.rb +16 -0
- data/db/migrations/010_drop_integration_soft_delete.rb +14 -0
- data/db/migrations/011_webhook_subscriptions_created_at.rb +10 -0
- data/db/migrations/012_webhook_subscriptions_created_by.rb +9 -0
- data/db/migrations/013_default_org_membership.rb +30 -0
- data/db/migrations/014_webhook_subscription_deliveries.rb +26 -0
- data/db/migrations/015_dependent_integrations.rb +9 -0
- data/db/migrations/016_encrypted_columns.rb +9 -0
- data/db/migrations/017_skip_verification.rb +9 -0
- data/db/migrations/018_sync_targets.rb +25 -0
- data/db/migrations/019_org_schema.rb +9 -0
- data/db/migrations/020_org_database_migrations.rb +25 -0
- data/db/migrations/021_no_default_org_schema.rb +14 -0
- data/db/migrations/022_database_document.rb +15 -0
- data/db/migrations/023_sync_target_schema.rb +9 -0
- data/db/migrations/024_org_semaphore_jobs.rb +9 -0
- data/db/migrations/025_integration_backfill_cursor.rb +9 -0
- data/db/migrations/026_undo_integration_backfill_cursor.rb +9 -0
- data/db/migrations/027_sync_target_http_sync.rb +12 -0
- data/db/migrations/028_logged_webhook_path.rb +24 -0
- data/db/migrations/029_encrypt_columns.rb +97 -0
- data/db/migrations/030_org_sync_target_timeout.rb +9 -0
- data/db/migrations/031_org_max_query_rows.rb +9 -0
- data/db/migrations/032_remove_db_defaults.rb +12 -0
- data/db/migrations/033_backfill_jobs.rb +26 -0
- data/db/migrations/034_backfill_job_criteria.rb +9 -0
- data/db/migrations/035_synchronous_backfill.rb +9 -0
- data/db/migrations/036_oauth.rb +26 -0
- data/db/migrations/037_oauth_used.rb +9 -0
- data/lib/amigo/durable_job.rb +416 -0
- data/lib/pry/clipboard.rb +111 -0
- data/lib/sequel/advisory_lock.rb +65 -0
- data/lib/webhookdb/admin.rb +4 -0
- data/lib/webhookdb/admin_api/auth.rb +36 -0
- data/lib/webhookdb/admin_api/customers.rb +63 -0
- data/lib/webhookdb/admin_api/database_documents.rb +20 -0
- data/lib/webhookdb/admin_api/entities.rb +66 -0
- data/lib/webhookdb/admin_api/message_deliveries.rb +61 -0
- data/lib/webhookdb/admin_api/roles.rb +15 -0
- data/lib/webhookdb/admin_api.rb +34 -0
- data/lib/webhookdb/aggregate_result.rb +63 -0
- data/lib/webhookdb/api/auth.rb +122 -0
- data/lib/webhookdb/api/connstr_auth.rb +36 -0
- data/lib/webhookdb/api/db.rb +188 -0
- data/lib/webhookdb/api/demo.rb +14 -0
- data/lib/webhookdb/api/entities.rb +198 -0
- data/lib/webhookdb/api/helpers.rb +253 -0
- data/lib/webhookdb/api/install.rb +296 -0
- data/lib/webhookdb/api/me.rb +53 -0
- data/lib/webhookdb/api/organizations.rb +254 -0
- data/lib/webhookdb/api/replay.rb +64 -0
- data/lib/webhookdb/api/service_integrations.rb +402 -0
- data/lib/webhookdb/api/services.rb +27 -0
- data/lib/webhookdb/api/stripe.rb +22 -0
- data/lib/webhookdb/api/subscriptions.rb +67 -0
- data/lib/webhookdb/api/sync_targets.rb +232 -0
- data/lib/webhookdb/api/system.rb +37 -0
- data/lib/webhookdb/api/webhook_subscriptions.rb +96 -0
- data/lib/webhookdb/api.rb +92 -0
- data/lib/webhookdb/apps.rb +93 -0
- data/lib/webhookdb/async/audit_logger.rb +38 -0
- data/lib/webhookdb/async/autoscaler.rb +84 -0
- data/lib/webhookdb/async/job.rb +18 -0
- data/lib/webhookdb/async/job_logger.rb +45 -0
- data/lib/webhookdb/async/scheduled_job.rb +18 -0
- data/lib/webhookdb/async.rb +142 -0
- data/lib/webhookdb/aws.rb +98 -0
- data/lib/webhookdb/backfill_job.rb +107 -0
- data/lib/webhookdb/backfiller.rb +107 -0
- data/lib/webhookdb/cloudflare.rb +39 -0
- data/lib/webhookdb/connection_cache.rb +177 -0
- data/lib/webhookdb/console.rb +71 -0
- data/lib/webhookdb/convertkit.rb +14 -0
- data/lib/webhookdb/crypto.rb +66 -0
- data/lib/webhookdb/customer/reset_code.rb +94 -0
- data/lib/webhookdb/customer.rb +347 -0
- data/lib/webhookdb/database_document.rb +72 -0
- data/lib/webhookdb/db_adapter/column_types.rb +37 -0
- data/lib/webhookdb/db_adapter/default_sql.rb +187 -0
- data/lib/webhookdb/db_adapter/pg.rb +96 -0
- data/lib/webhookdb/db_adapter/snowflake.rb +137 -0
- data/lib/webhookdb/db_adapter.rb +208 -0
- data/lib/webhookdb/dbutil.rb +92 -0
- data/lib/webhookdb/demo_mode.rb +100 -0
- data/lib/webhookdb/developer_alert.rb +51 -0
- data/lib/webhookdb/email_octopus.rb +21 -0
- data/lib/webhookdb/enumerable.rb +18 -0
- data/lib/webhookdb/fixtures/backfill_jobs.rb +72 -0
- data/lib/webhookdb/fixtures/customers.rb +65 -0
- data/lib/webhookdb/fixtures/database_documents.rb +27 -0
- data/lib/webhookdb/fixtures/faker.rb +41 -0
- data/lib/webhookdb/fixtures/logged_webhooks.rb +56 -0
- data/lib/webhookdb/fixtures/message_deliveries.rb +59 -0
- data/lib/webhookdb/fixtures/oauth_sessions.rb +24 -0
- data/lib/webhookdb/fixtures/organization_database_migrations.rb +37 -0
- data/lib/webhookdb/fixtures/organization_memberships.rb +54 -0
- data/lib/webhookdb/fixtures/organizations.rb +32 -0
- data/lib/webhookdb/fixtures/reset_codes.rb +23 -0
- data/lib/webhookdb/fixtures/service_integrations.rb +42 -0
- data/lib/webhookdb/fixtures/subscriptions.rb +33 -0
- data/lib/webhookdb/fixtures/sync_targets.rb +32 -0
- data/lib/webhookdb/fixtures/webhook_subscriptions.rb +35 -0
- data/lib/webhookdb/fixtures.rb +15 -0
- data/lib/webhookdb/formatting.rb +56 -0
- data/lib/webhookdb/front.rb +49 -0
- data/lib/webhookdb/github.rb +22 -0
- data/lib/webhookdb/google_calendar.rb +29 -0
- data/lib/webhookdb/heroku.rb +21 -0
- data/lib/webhookdb/http.rb +114 -0
- data/lib/webhookdb/icalendar.rb +17 -0
- data/lib/webhookdb/id.rb +17 -0
- data/lib/webhookdb/idempotency.rb +90 -0
- data/lib/webhookdb/increase.rb +42 -0
- data/lib/webhookdb/intercom.rb +23 -0
- data/lib/webhookdb/jobs/amigo_test_jobs.rb +118 -0
- data/lib/webhookdb/jobs/backfill.rb +32 -0
- data/lib/webhookdb/jobs/create_mirror_table.rb +18 -0
- data/lib/webhookdb/jobs/create_stripe_customer.rb +17 -0
- data/lib/webhookdb/jobs/customer_created_notify_internal.rb +22 -0
- data/lib/webhookdb/jobs/demo_mode_sync_data.rb +19 -0
- data/lib/webhookdb/jobs/deprecated_jobs.rb +19 -0
- data/lib/webhookdb/jobs/developer_alert_handle.rb +14 -0
- data/lib/webhookdb/jobs/durable_job_recheck_poller.rb +17 -0
- data/lib/webhookdb/jobs/emailer.rb +15 -0
- data/lib/webhookdb/jobs/icalendar_enqueue_syncs.rb +25 -0
- data/lib/webhookdb/jobs/icalendar_sync.rb +23 -0
- data/lib/webhookdb/jobs/logged_webhook_replay.rb +17 -0
- data/lib/webhookdb/jobs/logged_webhook_resilient_replay.rb +15 -0
- data/lib/webhookdb/jobs/message_dispatched.rb +16 -0
- data/lib/webhookdb/jobs/organization_database_migration_notify_finished.rb +21 -0
- data/lib/webhookdb/jobs/organization_database_migration_notify_started.rb +21 -0
- data/lib/webhookdb/jobs/organization_database_migration_run.rb +24 -0
- data/lib/webhookdb/jobs/prepare_database_connections.rb +22 -0
- data/lib/webhookdb/jobs/process_webhook.rb +47 -0
- data/lib/webhookdb/jobs/renew_watch_channel.rb +24 -0
- data/lib/webhookdb/jobs/replication_migration.rb +24 -0
- data/lib/webhookdb/jobs/reset_code_create_dispatch.rb +23 -0
- data/lib/webhookdb/jobs/scheduled_backfills.rb +77 -0
- data/lib/webhookdb/jobs/send_invite.rb +15 -0
- data/lib/webhookdb/jobs/send_test_webhook.rb +25 -0
- data/lib/webhookdb/jobs/send_webhook.rb +20 -0
- data/lib/webhookdb/jobs/sync_target_enqueue_scheduled.rb +16 -0
- data/lib/webhookdb/jobs/sync_target_run_sync.rb +38 -0
- data/lib/webhookdb/jobs/trim_logged_webhooks.rb +15 -0
- data/lib/webhookdb/jobs/webhook_resource_notify_integrations.rb +30 -0
- data/lib/webhookdb/jobs/webhook_subscription_delivery_attempt.rb +29 -0
- data/lib/webhookdb/jobs.rb +4 -0
- data/lib/webhookdb/json.rb +113 -0
- data/lib/webhookdb/liquid/expose.rb +27 -0
- data/lib/webhookdb/liquid/filters.rb +16 -0
- data/lib/webhookdb/liquid/liquification.rb +26 -0
- data/lib/webhookdb/liquid/partial.rb +12 -0
- data/lib/webhookdb/logged_webhook/resilient.rb +95 -0
- data/lib/webhookdb/logged_webhook.rb +194 -0
- data/lib/webhookdb/message/body.rb +25 -0
- data/lib/webhookdb/message/delivery.rb +127 -0
- data/lib/webhookdb/message/email_transport.rb +133 -0
- data/lib/webhookdb/message/fake_transport.rb +54 -0
- data/lib/webhookdb/message/liquid_drops.rb +29 -0
- data/lib/webhookdb/message/template.rb +89 -0
- data/lib/webhookdb/message/transport.rb +43 -0
- data/lib/webhookdb/message.rb +150 -0
- data/lib/webhookdb/messages/error_icalendar_fetch.rb +42 -0
- data/lib/webhookdb/messages/invite.rb +23 -0
- data/lib/webhookdb/messages/new_customer.rb +14 -0
- data/lib/webhookdb/messages/org_database_migration_finished.rb +23 -0
- data/lib/webhookdb/messages/org_database_migration_started.rb +24 -0
- data/lib/webhookdb/messages/specs.rb +57 -0
- data/lib/webhookdb/messages/verification.rb +23 -0
- data/lib/webhookdb/method_utilities.rb +82 -0
- data/lib/webhookdb/microsoft_calendar.rb +36 -0
- data/lib/webhookdb/nextpax.rb +14 -0
- data/lib/webhookdb/oauth/front.rb +58 -0
- data/lib/webhookdb/oauth/intercom.rb +58 -0
- data/lib/webhookdb/oauth/session.rb +24 -0
- data/lib/webhookdb/oauth.rb +80 -0
- data/lib/webhookdb/organization/alerting.rb +35 -0
- data/lib/webhookdb/organization/database_migration.rb +151 -0
- data/lib/webhookdb/organization/db_builder.rb +429 -0
- data/lib/webhookdb/organization.rb +506 -0
- data/lib/webhookdb/organization_membership.rb +58 -0
- data/lib/webhookdb/phone_number.rb +38 -0
- data/lib/webhookdb/plaid.rb +23 -0
- data/lib/webhookdb/platform.rb +27 -0
- data/lib/webhookdb/plivo.rb +52 -0
- data/lib/webhookdb/postgres/maintenance.rb +166 -0
- data/lib/webhookdb/postgres/model.rb +82 -0
- data/lib/webhookdb/postgres/model_utilities.rb +382 -0
- data/lib/webhookdb/postgres/testing_pixie.rb +16 -0
- data/lib/webhookdb/postgres/validations.rb +46 -0
- data/lib/webhookdb/postgres.rb +176 -0
- data/lib/webhookdb/postmark.rb +20 -0
- data/lib/webhookdb/redis.rb +35 -0
- data/lib/webhookdb/replicator/atom_single_feed_v1.rb +116 -0
- data/lib/webhookdb/replicator/aws_pricing_v1.rb +488 -0
- data/lib/webhookdb/replicator/base.rb +1185 -0
- data/lib/webhookdb/replicator/column.rb +482 -0
- data/lib/webhookdb/replicator/convertkit_broadcast_v1.rb +69 -0
- data/lib/webhookdb/replicator/convertkit_subscriber_v1.rb +200 -0
- data/lib/webhookdb/replicator/convertkit_tag_v1.rb +66 -0
- data/lib/webhookdb/replicator/convertkit_v1_mixin.rb +65 -0
- data/lib/webhookdb/replicator/docgen.rb +167 -0
- data/lib/webhookdb/replicator/email_octopus_campaign_v1.rb +84 -0
- data/lib/webhookdb/replicator/email_octopus_contact_v1.rb +159 -0
- data/lib/webhookdb/replicator/email_octopus_event_v1.rb +244 -0
- data/lib/webhookdb/replicator/email_octopus_list_v1.rb +101 -0
- data/lib/webhookdb/replicator/fake.rb +453 -0
- data/lib/webhookdb/replicator/front_conversation_v1.rb +45 -0
- data/lib/webhookdb/replicator/front_marketplace_root_v1.rb +55 -0
- data/lib/webhookdb/replicator/front_message_v1.rb +45 -0
- data/lib/webhookdb/replicator/front_v1_mixin.rb +22 -0
- data/lib/webhookdb/replicator/github_issue_comment_v1.rb +58 -0
- data/lib/webhookdb/replicator/github_issue_v1.rb +83 -0
- data/lib/webhookdb/replicator/github_pull_v1.rb +84 -0
- data/lib/webhookdb/replicator/github_release_v1.rb +47 -0
- data/lib/webhookdb/replicator/github_repo_v1_mixin.rb +250 -0
- data/lib/webhookdb/replicator/github_repository_event_v1.rb +45 -0
- data/lib/webhookdb/replicator/icalendar_calendar_v1.rb +465 -0
- data/lib/webhookdb/replicator/icalendar_event_v1.rb +334 -0
- data/lib/webhookdb/replicator/increase_account_number_v1.rb +77 -0
- data/lib/webhookdb/replicator/increase_account_transfer_v1.rb +61 -0
- data/lib/webhookdb/replicator/increase_account_v1.rb +63 -0
- data/lib/webhookdb/replicator/increase_ach_transfer_v1.rb +78 -0
- data/lib/webhookdb/replicator/increase_check_transfer_v1.rb +64 -0
- data/lib/webhookdb/replicator/increase_limit_v1.rb +78 -0
- data/lib/webhookdb/replicator/increase_transaction_v1.rb +74 -0
- data/lib/webhookdb/replicator/increase_v1_mixin.rb +121 -0
- data/lib/webhookdb/replicator/increase_wire_transfer_v1.rb +61 -0
- data/lib/webhookdb/replicator/intercom_contact_v1.rb +36 -0
- data/lib/webhookdb/replicator/intercom_conversation_v1.rb +38 -0
- data/lib/webhookdb/replicator/intercom_marketplace_root_v1.rb +69 -0
- data/lib/webhookdb/replicator/intercom_v1_mixin.rb +105 -0
- data/lib/webhookdb/replicator/oauth_refresh_access_token_mixin.rb +65 -0
- data/lib/webhookdb/replicator/plivo_sms_inbound_v1.rb +102 -0
- data/lib/webhookdb/replicator/postmark_inbound_message_v1.rb +94 -0
- data/lib/webhookdb/replicator/postmark_outbound_message_event_v1.rb +107 -0
- data/lib/webhookdb/replicator/schema_modification.rb +42 -0
- data/lib/webhookdb/replicator/shopify_customer_v1.rb +58 -0
- data/lib/webhookdb/replicator/shopify_order_v1.rb +64 -0
- data/lib/webhookdb/replicator/shopify_v1_mixin.rb +161 -0
- data/lib/webhookdb/replicator/signalwire_message_v1.rb +169 -0
- data/lib/webhookdb/replicator/sponsy_customer_v1.rb +54 -0
- data/lib/webhookdb/replicator/sponsy_placement_v1.rb +34 -0
- data/lib/webhookdb/replicator/sponsy_publication_v1.rb +125 -0
- data/lib/webhookdb/replicator/sponsy_slot_v1.rb +41 -0
- data/lib/webhookdb/replicator/sponsy_status_v1.rb +35 -0
- data/lib/webhookdb/replicator/sponsy_v1_mixin.rb +165 -0
- data/lib/webhookdb/replicator/state_machine_step.rb +69 -0
- data/lib/webhookdb/replicator/stripe_charge_v1.rb +77 -0
- data/lib/webhookdb/replicator/stripe_coupon_v1.rb +62 -0
- data/lib/webhookdb/replicator/stripe_customer_v1.rb +60 -0
- data/lib/webhookdb/replicator/stripe_dispute_v1.rb +77 -0
- data/lib/webhookdb/replicator/stripe_invoice_item_v1.rb +82 -0
- data/lib/webhookdb/replicator/stripe_invoice_v1.rb +116 -0
- data/lib/webhookdb/replicator/stripe_payout_v1.rb +67 -0
- data/lib/webhookdb/replicator/stripe_price_v1.rb +60 -0
- data/lib/webhookdb/replicator/stripe_product_v1.rb +60 -0
- data/lib/webhookdb/replicator/stripe_refund_v1.rb +101 -0
- data/lib/webhookdb/replicator/stripe_subscription_item_v1.rb +56 -0
- data/lib/webhookdb/replicator/stripe_subscription_v1.rb +75 -0
- data/lib/webhookdb/replicator/stripe_v1_mixin.rb +116 -0
- data/lib/webhookdb/replicator/transistor_episode_stats_v1.rb +141 -0
- data/lib/webhookdb/replicator/transistor_episode_v1.rb +169 -0
- data/lib/webhookdb/replicator/transistor_show_v1.rb +68 -0
- data/lib/webhookdb/replicator/transistor_v1_mixin.rb +65 -0
- data/lib/webhookdb/replicator/twilio_sms_v1.rb +156 -0
- data/lib/webhookdb/replicator/webhook_request.rb +5 -0
- data/lib/webhookdb/replicator/webhookdb_customer_v1.rb +74 -0
- data/lib/webhookdb/replicator.rb +224 -0
- data/lib/webhookdb/role.rb +42 -0
- data/lib/webhookdb/sentry.rb +35 -0
- data/lib/webhookdb/service/auth.rb +138 -0
- data/lib/webhookdb/service/collection.rb +91 -0
- data/lib/webhookdb/service/entities.rb +97 -0
- data/lib/webhookdb/service/helpers.rb +270 -0
- data/lib/webhookdb/service/middleware.rb +124 -0
- data/lib/webhookdb/service/types.rb +30 -0
- data/lib/webhookdb/service/validators.rb +32 -0
- data/lib/webhookdb/service/view_api.rb +63 -0
- data/lib/webhookdb/service.rb +219 -0
- data/lib/webhookdb/service_integration.rb +332 -0
- data/lib/webhookdb/shopify.rb +35 -0
- data/lib/webhookdb/signalwire.rb +13 -0
- data/lib/webhookdb/slack.rb +68 -0
- data/lib/webhookdb/snowflake.rb +90 -0
- data/lib/webhookdb/spec_helpers/async.rb +122 -0
- data/lib/webhookdb/spec_helpers/citest.rb +88 -0
- data/lib/webhookdb/spec_helpers/integration.rb +121 -0
- data/lib/webhookdb/spec_helpers/message.rb +41 -0
- data/lib/webhookdb/spec_helpers/postgres.rb +220 -0
- data/lib/webhookdb/spec_helpers/service.rb +432 -0
- data/lib/webhookdb/spec_helpers/shared_examples_for_columns.rb +56 -0
- data/lib/webhookdb/spec_helpers/shared_examples_for_replicators.rb +915 -0
- data/lib/webhookdb/spec_helpers/whdb.rb +139 -0
- data/lib/webhookdb/spec_helpers.rb +63 -0
- data/lib/webhookdb/sponsy.rb +14 -0
- data/lib/webhookdb/stripe.rb +37 -0
- data/lib/webhookdb/subscription.rb +203 -0
- data/lib/webhookdb/sync_target.rb +491 -0
- data/lib/webhookdb/tasks/admin.rb +49 -0
- data/lib/webhookdb/tasks/annotate.rb +36 -0
- data/lib/webhookdb/tasks/db.rb +82 -0
- data/lib/webhookdb/tasks/docs.rb +42 -0
- data/lib/webhookdb/tasks/fixture.rb +35 -0
- data/lib/webhookdb/tasks/message.rb +50 -0
- data/lib/webhookdb/tasks/regress.rb +87 -0
- data/lib/webhookdb/tasks/release.rb +27 -0
- data/lib/webhookdb/tasks/sidekiq.rb +23 -0
- data/lib/webhookdb/tasks/specs.rb +64 -0
- data/lib/webhookdb/theranest.rb +15 -0
- data/lib/webhookdb/transistor.rb +13 -0
- data/lib/webhookdb/twilio.rb +13 -0
- data/lib/webhookdb/typed_struct.rb +44 -0
- data/lib/webhookdb/version.rb +5 -0
- data/lib/webhookdb/webhook_response.rb +50 -0
- data/lib/webhookdb/webhook_subscription/delivery.rb +82 -0
- data/lib/webhookdb/webhook_subscription.rb +226 -0
- data/lib/webhookdb/windows_tz.rb +32 -0
- data/lib/webhookdb/xml.rb +92 -0
- data/lib/webhookdb.rb +224 -0
- data/lib/webterm/apps.rb +45 -0
- metadata +1129 -0
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "rake/tasklib"
|
|
4
|
+
|
|
5
|
+
require "webhookdb"
|
|
6
|
+
require "webhookdb/postgres"
|
|
7
|
+
|
|
8
|
+
module Webhookdb::Tasks
|
|
9
|
+
class Fixture < Rake::TaskLib
|
|
10
|
+
def initialize
|
|
11
|
+
super()
|
|
12
|
+
namespace :fixture do
|
|
13
|
+
desc "Create a bunch of fake integrations and fill them with data."
|
|
14
|
+
task :full do
|
|
15
|
+
require "webhookdb"
|
|
16
|
+
Webhookdb.load_app
|
|
17
|
+
require "webhookdb/fixtures"
|
|
18
|
+
Webhookdb::Fixtures.load_all
|
|
19
|
+
org = Webhookdb::Fixtures.organization.create
|
|
20
|
+
org.prepare_database_connections?
|
|
21
|
+
sints = Array.new(3) { Webhookdb::Fixtures.service_integration(organization: org).create }
|
|
22
|
+
now = Time.now
|
|
23
|
+
sints.each do |sint|
|
|
24
|
+
svc = sint.replicator
|
|
25
|
+
svc.create_table
|
|
26
|
+
Array.new(5000) do |i|
|
|
27
|
+
svc.upsert_webhook_body({"my_id" => i.to_s, "at" => (now - i.seconds).iso8601})
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
puts "Created Webhookdb::Organization[#{org.id}]"
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
end
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "rake/tasklib"
|
|
4
|
+
|
|
5
|
+
module Webhookdb::Tasks
|
|
6
|
+
class Message < Rake::TaskLib
|
|
7
|
+
def initialize
|
|
8
|
+
super()
|
|
9
|
+
namespace :message do
|
|
10
|
+
desc "Render the specified message"
|
|
11
|
+
task :render, [:template_class, :out] do |_t, args|
|
|
12
|
+
template_class_name = args[:template_class] or
|
|
13
|
+
raise "Provide the template class name (NewCustomer or new_customer) as the first argument"
|
|
14
|
+
outpath = args[:out]
|
|
15
|
+
outpath = nil if outpath.blank? || outpath == "-"
|
|
16
|
+
if outpath
|
|
17
|
+
html_io = File.open(outpath, "w")
|
|
18
|
+
feedback_io = $stdout
|
|
19
|
+
else
|
|
20
|
+
html_io = $stdout
|
|
21
|
+
feedback_io = $stderr
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
ENV["WEBHOOKDB_DB_SLOW_QUERY_SECONDS"] ||= "1"
|
|
25
|
+
require "webhookdb"
|
|
26
|
+
Webhookdb.load_app
|
|
27
|
+
SemanticLogger.appenders.to_a.each { |a| SemanticLogger.remove_appender(a) }
|
|
28
|
+
SemanticLogger.add_appender(io: feedback_io)
|
|
29
|
+
|
|
30
|
+
commit = Webhookdb::RACK_ENV != "test"
|
|
31
|
+
delivery = Webhookdb::Message::Delivery.preview(template_class_name.classify, commit:)
|
|
32
|
+
feedback_io << "*** Created MessageDelivery: #{delivery.values}\n\n"
|
|
33
|
+
feedback_io << delivery.body_with_mediatype!("text/plain")&.content
|
|
34
|
+
feedback_io << "\n\n"
|
|
35
|
+
if outpath
|
|
36
|
+
feedback_io << "*** Writing HTML output to #{outpath}\n"
|
|
37
|
+
elsif html_io.tty?
|
|
38
|
+
feedback_io << "*** Writing HTML output to stdout.\n"
|
|
39
|
+
feedback_io << "*** Redirect it to a file (> temp.html), pass OUT to write it to a file (OUT=temp.html),\n"
|
|
40
|
+
feedback_io << "*** or view it at /admin_api/v1/message_deliveries/last\n\n"
|
|
41
|
+
else
|
|
42
|
+
feedback_io << "*** Writing HTML output to redirected stdout.\n"
|
|
43
|
+
end
|
|
44
|
+
html_io << delivery.body_with_mediatype!("text/html")&.content
|
|
45
|
+
html_io << "\n"
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
end
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "rake/tasklib"
|
|
4
|
+
require "sequel"
|
|
5
|
+
|
|
6
|
+
require "webhookdb"
|
|
7
|
+
require "webhookdb/postgres"
|
|
8
|
+
|
|
9
|
+
module Webhookdb::Tasks
|
|
10
|
+
class Regress < Rake::TaskLib
|
|
11
|
+
def initialize
|
|
12
|
+
super()
|
|
13
|
+
namespace :regress do
|
|
14
|
+
desc "Creates databases for all orgs that do not have them."
|
|
15
|
+
task :prepare do
|
|
16
|
+
Webhookdb.load_app
|
|
17
|
+
Webhookdb::Organization.where(readonly_connection_url_raw: nil).each do |org|
|
|
18
|
+
org.prepare_database_connections
|
|
19
|
+
org.migrate_replication_tables
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
desc "Prints out all service integrations that have untrimmed logged webhooks."
|
|
24
|
+
task :list_available do
|
|
25
|
+
Webhookdb.load_app
|
|
26
|
+
opaque_ids = Webhookdb::LoggedWebhook.where(truncated_at: nil).
|
|
27
|
+
distinct(:service_integration_opaque_id).
|
|
28
|
+
select_map(:service_integration_opaque_id)
|
|
29
|
+
sints = Webhookdb::ServiceIntegration.where(opaque_id: opaque_ids).all
|
|
30
|
+
self.print_service_integrations(sints)
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
desc "Replay the last :count webhooks going to the service integration with the given opaque id. " \
|
|
34
|
+
"Use -1 for all webhooks."
|
|
35
|
+
task :replay, [:opaque_id, :count] do |_, args|
|
|
36
|
+
opaque_id = args.fetch(:opaque_id)
|
|
37
|
+
count = args.fetch(:count).to_i
|
|
38
|
+
Webhookdb.load_app
|
|
39
|
+
ds = Webhookdb::LoggedWebhook.where(truncated_at: nil).
|
|
40
|
+
where(service_integration_opaque_id: opaque_id).
|
|
41
|
+
order(Sequel.asc(:inserted_at))
|
|
42
|
+
ds = ds.limit(count) if count >= 0
|
|
43
|
+
ds.paged_each do |lw|
|
|
44
|
+
good = lw.retry_one
|
|
45
|
+
puts "#{lw.pk} failed" unless good
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
desc "Prints out all service integrations that have backfill info available."
|
|
50
|
+
task :list_backfill do
|
|
51
|
+
Webhookdb.load_app
|
|
52
|
+
sints = Webhookdb::ServiceIntegration.exclude(backfill_key: nil).all
|
|
53
|
+
self.print_service_integrations(sints)
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
desc "Runs a backfill for the service integration with the given opaque id. " \
|
|
57
|
+
"Regression backfills are limited to one page."
|
|
58
|
+
task :backfill, [:opaque_id] do |_, args|
|
|
59
|
+
opaque_id = args.fetch(:opaque_id)
|
|
60
|
+
Webhookdb.load_app
|
|
61
|
+
sint = Webhookdb::ServiceIntegration[opaque_id:] or raise "No service integration for #{opaque_id}"
|
|
62
|
+
bfjob = Webhookdb::BackfillJob.create_recursive(service_integration: sint, incremental: false)
|
|
63
|
+
sint.replicator.backfill(bfjob)
|
|
64
|
+
end
|
|
65
|
+
end
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
def print_service_integrations(iter)
|
|
69
|
+
rows = iter.map do |sint|
|
|
70
|
+
name = "#{sint.organization.name} (#{sint.organization_id})"
|
|
71
|
+
[name, sint.service_name, sint.opaque_id, sint.table_name]
|
|
72
|
+
end
|
|
73
|
+
rows.sort!
|
|
74
|
+
self.table_print rows
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
def table_print(rows)
|
|
78
|
+
max_lengths = rows.each_with_object({}) do |row, m|
|
|
79
|
+
row.each_with_index { |value, idx| m[idx] = [m.fetch(idx, 0), value.to_s.length].max }
|
|
80
|
+
end
|
|
81
|
+
row_strings = rows.map do |row|
|
|
82
|
+
row.each_with_index.map { |value, idx| "%-#{max_lengths[idx]}s" % value }.join("\t")
|
|
83
|
+
end
|
|
84
|
+
puts row_strings
|
|
85
|
+
end
|
|
86
|
+
end
|
|
87
|
+
end
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "rake/tasklib"
|
|
4
|
+
|
|
5
|
+
require "webhookdb"
|
|
6
|
+
|
|
7
|
+
module Webhookdb::Tasks
|
|
8
|
+
class Release < Rake::TaskLib
|
|
9
|
+
def initialize
|
|
10
|
+
super()
|
|
11
|
+
desc "Migrate replication tables for each integration, ensure all columns and backfill new columns."
|
|
12
|
+
task :migrate_replication_tables do
|
|
13
|
+
Webhookdb.load_app
|
|
14
|
+
Webhookdb::Organization.enqueue_migrate_all_replication_tables
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
desc "Run the release script against the current environment."
|
|
18
|
+
task :release do
|
|
19
|
+
Rake::Task["db:migrate"].invoke
|
|
20
|
+
Rake::Task["migrate_replication_tables"].invoke
|
|
21
|
+
if ENV["HEROKU_APP_ID"] && (ENV["RUN_INTEGRATION_TESTS_ON_RELEASE"] == "true")
|
|
22
|
+
Rake::Task["specs:heroku_integration_step1"].invoke
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
end
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "rake/tasklib"
|
|
4
|
+
|
|
5
|
+
require "webhookdb"
|
|
6
|
+
|
|
7
|
+
module Webhookdb::Tasks
|
|
8
|
+
class Sidekiq < Rake::TaskLib
|
|
9
|
+
def initialize
|
|
10
|
+
super()
|
|
11
|
+
namespace :sidekiq do
|
|
12
|
+
desc "Clear the Sidekiq redis DB (flushdb). " \
|
|
13
|
+
"Only use on local, and only for legit reasons, " \
|
|
14
|
+
"not to paper over problems that will show on staging and prod " \
|
|
15
|
+
"(like removing a job class)."
|
|
16
|
+
task :reset do
|
|
17
|
+
require "webhookdb/async"
|
|
18
|
+
::Sidekiq.redis(&:flushdb)
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
end
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "rake/tasklib"
|
|
4
|
+
require "stringio"
|
|
5
|
+
|
|
6
|
+
require "webhookdb"
|
|
7
|
+
|
|
8
|
+
module Webhookdb::Tasks
|
|
9
|
+
class Specs < Rake::TaskLib
|
|
10
|
+
def initialize
|
|
11
|
+
super()
|
|
12
|
+
namespace :specs do
|
|
13
|
+
desc "Run API integration tests"
|
|
14
|
+
task :integration do
|
|
15
|
+
require "rspec/core"
|
|
16
|
+
require "slack-notifier"
|
|
17
|
+
require "webhookdb/spec_helpers/integration"
|
|
18
|
+
require "webhookdb/spec_helpers/citest"
|
|
19
|
+
Webhookdb::SpecHelpers::Citest.run_tests("integration")
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
desc "The release process needs to finish quickly, so start the integration tests in another dyno."
|
|
23
|
+
task :heroku_integration_step1 do
|
|
24
|
+
require "webhookdb/heroku"
|
|
25
|
+
Webhookdb::Heroku.client.dyno.create(
|
|
26
|
+
Webhookdb::Heroku.app_name,
|
|
27
|
+
command: "bundle exec rake specs:heroku_integration_step2",
|
|
28
|
+
attach: false,
|
|
29
|
+
time_to_live: 1.minute.to_i,
|
|
30
|
+
type: "run",
|
|
31
|
+
)
|
|
32
|
+
end
|
|
33
|
+
desc "Sleep 20 seconds to wait for the **next** one-off dyno to have the new code."
|
|
34
|
+
task :heroku_integration_step2 do
|
|
35
|
+
sleep(20)
|
|
36
|
+
require "webhookdb/heroku"
|
|
37
|
+
Webhookdb::Heroku.client.dyno.create(
|
|
38
|
+
Webhookdb::Heroku.app_name,
|
|
39
|
+
command: "bundle exec rake specs:integration_step3",
|
|
40
|
+
env: {"INTEGRATION_TESTS" => "true"},
|
|
41
|
+
attach: false,
|
|
42
|
+
time_to_live: 10.minute.to_i,
|
|
43
|
+
type: "run",
|
|
44
|
+
)
|
|
45
|
+
end
|
|
46
|
+
desc "Run the actual integration tests."
|
|
47
|
+
task :heroku_integration_step3 do
|
|
48
|
+
require "webhookdb/heroku"
|
|
49
|
+
Rake::Task["specs:integration"].invoke
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
desc "Do a thing through Rake so it's easy to run under the debugger"
|
|
53
|
+
task :debugtask do
|
|
54
|
+
require "webhookdb"
|
|
55
|
+
Webhookdb.load_app
|
|
56
|
+
sint = Webhookdb::ServiceIntegration[84]
|
|
57
|
+
row_pk = 710
|
|
58
|
+
expiring_before = 1.week.from_now
|
|
59
|
+
sint.replicator.renew_watch_channel(row_pk:, expiring_before:)
|
|
60
|
+
end
|
|
61
|
+
end
|
|
62
|
+
end
|
|
63
|
+
end
|
|
64
|
+
end
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "appydays/configurable"
|
|
4
|
+
|
|
5
|
+
module Webhookdb::Theranest
|
|
6
|
+
include Appydays::Configurable
|
|
7
|
+
|
|
8
|
+
configurable(:theranest) do
|
|
9
|
+
setting :cron_expression, "30 8 * * *" # default to midnight
|
|
10
|
+
setting :appointment_look_back_months, 12
|
|
11
|
+
setting :appointment_look_forward_months, 3
|
|
12
|
+
setting :page_size, 50
|
|
13
|
+
setting :http_timeout, 30
|
|
14
|
+
end
|
|
15
|
+
end
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "appydays/configurable"
|
|
4
|
+
|
|
5
|
+
module Webhookdb::Transistor
|
|
6
|
+
include Appydays::Configurable
|
|
7
|
+
|
|
8
|
+
configurable(:transistor) do
|
|
9
|
+
setting :episode_cron_expression, "30 * * * *"
|
|
10
|
+
setting :show_cron_expression, "0 0 */1 * *"
|
|
11
|
+
setting :http_timeout, 30
|
|
12
|
+
end
|
|
13
|
+
end
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "appydays/configurable"
|
|
4
|
+
require "appydays/loggable"
|
|
5
|
+
|
|
6
|
+
module Webhookdb::Twilio
|
|
7
|
+
include Appydays::Configurable
|
|
8
|
+
include Appydays::Loggable
|
|
9
|
+
|
|
10
|
+
configurable(:twilio) do
|
|
11
|
+
setting :http_timeout, 30
|
|
12
|
+
end
|
|
13
|
+
end
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
class Webhookdb::TypedStruct
|
|
4
|
+
def initialize(**kwargs)
|
|
5
|
+
self._apply(self._defaults.merge(kwargs))
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
def _defaults
|
|
9
|
+
return {}
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def [](k)
|
|
13
|
+
return self.send(k)
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
# Modify the receiver with kwargs.
|
|
17
|
+
def _apply(kwargs)
|
|
18
|
+
kwargs.each do |k, v|
|
|
19
|
+
raise TypeError, "invalid struct field #{k}" unless self.respond_to?(k)
|
|
20
|
+
self.instance_variable_set(:"@#{k}", v)
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def change(**)
|
|
25
|
+
c = self.dup
|
|
26
|
+
c._apply(**)
|
|
27
|
+
return c
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def as_json
|
|
31
|
+
return self.instance_values.as_json
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
protected def typecheck!(field, type, nullable: false)
|
|
35
|
+
value = self.send(field)
|
|
36
|
+
return if nullable && value.nil?
|
|
37
|
+
if type == :boolean
|
|
38
|
+
return if [true, false].include?(value)
|
|
39
|
+
elsif value.is_a?(type)
|
|
40
|
+
return
|
|
41
|
+
end
|
|
42
|
+
raise ArgumentError, "#{field} #{value.inspect} must be a #{type.name}"
|
|
43
|
+
end
|
|
44
|
+
end
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "webhookdb/typed_struct"
|
|
4
|
+
|
|
5
|
+
class Webhookdb::WebhookResponse < Webhookdb::TypedStruct
|
|
6
|
+
# The standard WebhookDB Secret header, in RFC header format (My-Hdr).
|
|
7
|
+
SECRET_HEADER_RFC = "Whdb-Webhook-Secret"
|
|
8
|
+
# The standard WebhookDB secret header, in Rack header format (HTTP_MY_HDR).
|
|
9
|
+
SECRET_HEADER_RACK = "HTTP_WHDB_WEBHOOK_SECRET"
|
|
10
|
+
|
|
11
|
+
# Compare the value of the SECRET_HEADER_RACK in the request header.
|
|
12
|
+
# @param [Rack::Request] request
|
|
13
|
+
# @param [String] webhook_secret
|
|
14
|
+
# @return [Webhookdb::WebhookResponse]
|
|
15
|
+
def self.for_standard_secret(request, webhook_secret, ok_status: 202)
|
|
16
|
+
hdr_secret = request.env[SECRET_HEADER_RACK]
|
|
17
|
+
return self.error("missing secret header") if hdr_secret.nil?
|
|
18
|
+
matches = ActiveSupport::SecurityUtils.secure_compare(webhook_secret, hdr_secret)
|
|
19
|
+
return self.error("secret mismatch") unless matches
|
|
20
|
+
return self.ok(status: ok_status)
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
attr_reader :status,
|
|
24
|
+
:headers,
|
|
25
|
+
:body,
|
|
26
|
+
:reason
|
|
27
|
+
|
|
28
|
+
def self.error(reason, status: 401)
|
|
29
|
+
return self.new(status:, json: {message: reason}, reason:)
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def self.ok(json: {o: "k"}, status: 202)
|
|
33
|
+
return self.new(status:, json:)
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def initialize(status:, body: nil, json: nil, reason: nil, headers: {})
|
|
37
|
+
raise "Reason must be provided if returning an error" if !reason && status >= 400
|
|
38
|
+
if json
|
|
39
|
+
body = json.to_json
|
|
40
|
+
headers["Content-Type"] = "application/json"
|
|
41
|
+
end
|
|
42
|
+
raise ":body or :json must be provided" if body.nil?
|
|
43
|
+
super(status:, body:, headers:, reason:)
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
# @return [Array<Integer, Hash, String>]
|
|
47
|
+
def to_rack
|
|
48
|
+
return [self.status, self.headers, self.body]
|
|
49
|
+
end
|
|
50
|
+
end
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "webhookdb/postgres/model"
|
|
4
|
+
|
|
5
|
+
require "webhookdb/webhook_subscription"
|
|
6
|
+
|
|
7
|
+
# Represents the attempted delivery of a rowupsert to a particular webhook subscription.
|
|
8
|
+
# See WebhookSubscription for more details.
|
|
9
|
+
class Webhookdb::WebhookSubscription::Delivery < Webhookdb::Postgres::Model(:webhook_subscription_deliveries)
|
|
10
|
+
plugin :timestamps
|
|
11
|
+
|
|
12
|
+
many_to_one :webhook_subscription, class: "Webhookdb::WebhookSubscription"
|
|
13
|
+
|
|
14
|
+
# See WebhookSubhscription#attempt_delivery
|
|
15
|
+
def attempt_delivery
|
|
16
|
+
self.webhook_subscription.attempt_delivery(self)
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
# Add an attempt to this instance.
|
|
20
|
+
def add_attempt(status:, at: Time.now)
|
|
21
|
+
self.attempt_timestamps << at
|
|
22
|
+
self.modified!(:attempt_timestamps)
|
|
23
|
+
self.attempt_http_response_statuses << status
|
|
24
|
+
self.modified!(:attempt_http_response_statuses)
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
# Create a list of Attempt instances.
|
|
28
|
+
def attempts
|
|
29
|
+
return self.attempt_timestamps.
|
|
30
|
+
zip(self.attempt_http_response_statuses).
|
|
31
|
+
map { |(at, status)| Attempt.new(at, status) }
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
# Fast path for getting the total attempt count.
|
|
35
|
+
def attempt_count
|
|
36
|
+
return self.attempt_timestamps.length
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
# Return the latest attempt, or nil if there have been no attempts.
|
|
40
|
+
def latest_attempt
|
|
41
|
+
cnt = self.attempt_count
|
|
42
|
+
return nil if cnt.zero?
|
|
43
|
+
ts = self.attempt_timestamps[cnt - 1]
|
|
44
|
+
status = self.attempt_http_response_statuses[cnt - 1]
|
|
45
|
+
return Attempt.new(ts, status)
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
# One of 'pending' (no attempts), 'success', or 'error'.
|
|
49
|
+
def latest_attempt_status
|
|
50
|
+
att = self.latest_attempt
|
|
51
|
+
return "pending" if att.nil?
|
|
52
|
+
return att.success ? "success" : "error"
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
class Attempt
|
|
56
|
+
attr_reader :at, :status, :success
|
|
57
|
+
|
|
58
|
+
def initialize(at, status)
|
|
59
|
+
@at = at
|
|
60
|
+
@status = status
|
|
61
|
+
@success = status < 300
|
|
62
|
+
end
|
|
63
|
+
end
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
# Table: webhook_subscription_deliveries
|
|
67
|
+
# ------------------------------------------------------------------------------------------------------------------------------
|
|
68
|
+
# Columns:
|
|
69
|
+
# id | integer | PRIMARY KEY GENERATED BY DEFAULT AS IDENTITY
|
|
70
|
+
# created_at | timestamp with time zone | NOT NULL DEFAULT now()
|
|
71
|
+
# attempt_timestamps | timestamp with time zone[] | NOT NULL DEFAULT ARRAY[]::timestamp with time zone[]
|
|
72
|
+
# attempt_http_response_statuses | smallint[] | NOT NULL DEFAULT ARRAY[]::smallint[]
|
|
73
|
+
# payload | jsonb | NOT NULL
|
|
74
|
+
# webhook_subscription_id | integer | NOT NULL
|
|
75
|
+
# Indexes:
|
|
76
|
+
# webhook_subscription_deliveries_pkey | PRIMARY KEY btree (id)
|
|
77
|
+
# webhook_subscription_deliveries_webhook_subscription_id_index | btree (webhook_subscription_id)
|
|
78
|
+
# Check constraints:
|
|
79
|
+
# balanced_attempts | (array_length(attempt_timestamps, 1) = array_length(attempt_http_response_statuses, 1))
|
|
80
|
+
# Foreign key constraints:
|
|
81
|
+
# webhook_subscription_deliveries_webhook_subscription_id_fkey | (webhook_subscription_id) REFERENCES webhook_subscriptions(id)
|
|
82
|
+
# ------------------------------------------------------------------------------------------------------------------------------
|