Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix registration of event_bridge and pub_sub webhooks #1635

Merged
merged 6 commits into from
Jul 25, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
Unreleased
----------
* Fixes typo in webhook generator [#1704](https://github.com/Shopify/shopify_app/pull/1704)
* Fix registration of event_bridge and pub_sub webhooks [#1635](https://github.com/Shopify/shopify_app/pull/1635)

21.6.0 (July 11, 2023)
----------
Expand Down
36 changes: 35 additions & 1 deletion docs/shopify_app/webhooks.md
Original file line number Diff line number Diff line change
Expand Up @@ -82,4 +82,38 @@ We have three mandatory GDPR webhooks

The `generate shopify_app` command generated three job templates corresponding to all three of these webhooks.
To pass our approval process you will need to set these webhooks in your partner dashboard.
You can read more about that [here](https://shopify.dev/apps/webhooks/configuration/mandatory-webhooks).
You can read more about that [here](https://shopify.dev/apps/webhooks/configuration/mandatory-webhooks).

## EventBridge and PubSub Webhooks

You can also register webhooks for delivery to Amazon EventBridge or Google Cloud Pub/Sub. In this case the `path` argument to needs to be of a specific form.

For EventBridge, the `path` must be the ARN of the partner event source.

```rb
ShopifyApp.configure do |config|
config.webhooks = [
{
delivery_method: :event_bridge,
topic: 'carts/update',
path: 'arn:aws:events....'
}
]
end
```

For Pub/Sub, the `path` must be of the form `pubsub://[PROJECT-ID]:[PUB-SUB-TOPIC-ID]`. For example, if you created a topic with id `red` in the project `blue`, then the value of path would be `pubsub://blue:red`.

```rb
ShopifyApp.configure do |config|
config.webhooks = [
{
delivery_method: :pub_sub,
topic: 'carts/update',
path: 'pubsub://project-id:pub-sub-topic-id'
}
]
end
```

When registering for an EventBridge or PubSub Webhook you'll need to implement a handler that will fetch webhooks from the queue and process them yourself.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do you have an example you could provide here?

Copy link

@kcamcam kcamcam Feb 8, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey @nelsonwittwer, I opened one of the issues being addressed here #1505. If it's ok I'm going to jump in here to try and speed this up, since its been causing my team some issues.

In our GCP implementation, all Shopify events (webhooks) are sent to the same subscriber endpoint (ex: /shopify/events) which dispatches (handles) the jobs. The naming conventions for the jobs are the same for HTTP and Pub/Sub. Here is an example:

module Shopify::EventsController < ApplicationController
    def dispatch
      event_job_klass.perform_later(topic: event_topic, shop: event_shop, body: event_body)
      head :created
    end

    private

    def event_topic
      params[:message][:attributes]['X-Shopify-Topic']
    end

    def event_shop
      params[:message][:attributes]['X-Shopify-Shop-Domain']
    end

    def event_body
      JSON.parse(Base64.decode64(params[:message][:data])).to_h
    end

    def event_job_klass
      event_job_klass_name.constantize
    end

    def event_job_klass_name
      "#{event_jobs_namespace}/#{event_topic.sub('/', '_')}_job".classify
    end

    def event_jobs_namespace
      ShopifyApp.configuration.webhook_jobs_namespace
    end
  end
end

Thanks for the fix @kirillplatonov 🙏 Hopefully this makes it into the next release 🤞

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@nelsonwittwer Unfortunately, I can't share publicly the code we use for the EventBridge dispatcher. But the way it works is by pulling events from the SQS and delegating them to webhook jobs using the same convention as HTTP webhooks. The example above from @kcamcam for pub_sub is similar.

It would be very helpful to create built-in event_bridge and pub_sub handlers for that gem. But that's a topic for another pull request. For now, it would be great if we could merge this tiny fix that will allow everyone to at least start using their own handlers with shopify_app.

5 changes: 3 additions & 2 deletions lib/shopify_app/managers/webhooks_manager.rb
Original file line number Diff line number Diff line change
Expand Up @@ -43,12 +43,13 @@ def add_registrations
ShopifyApp::Logger.debug("Adding registrations to webhooks")
ShopifyApp.configuration.webhooks.each do |attributes|
webhook_path = path(attributes)
delivery_method = attributes[:delivery_method] || :http

ShopifyAPI::Webhooks::Registry.add_registration(
topic: attributes[:topic],
delivery_method: attributes[:delivery_method] || :http,
delivery_method: delivery_method,
path: webhook_path,
handler: webhook_job_klass(webhook_path),
handler: delivery_method == :http ? webhook_job_klass(webhook_path) : nil,
fields: attributes[:fields],
)
end
Expand Down