Shopify / shopify_app

A Rails Engine for building Shopify Apps
MIT License
1.74k stars 683 forks source link

Webhooks don't subscribe correctly #1871

Open BaggioGiacomo opened 1 week ago

BaggioGiacomo commented 1 week ago

Issue summary

Before opening this issue, I have:

I've added the app/uninstalled webhook using the generator provided by this gem: rails g shopify_app:add_webhook --topic app/uninstalled --path webhooks/app_uninstalled

Here's the config on the shopify_app.rb file:

config.webhooks = [
  { topic: "app/uninstalled", path: "webhooks/app_uninstalled" }
]

app/jobs/app_uninstalled_job.rb file has been created:

class AppUninstalledJob < ActiveJob::Base
  extend ShopifyAPI::Webhooks::Handler

  class << self
    def handle(topic:, shop:, body:)
      perform_later(topic: topic, shop_domain: shop, webhook: body)
    end
  end

  def perform(topic:, shop_domain:, webhook:)
    shop = Shop.find_by(shopify_domain: shop_domain)

    if shop.nil?
      logger.error("#{self.class} failed: cannot find shop with domain '#{shop_domain}'")

      raise ActiveRecord::RecordNotFound, "Shop Not Found"
    end

    shop.destroy
  end
end

When I run the app and install it on one store, the webhook isn't added to the webhooks scription. If I run this GraphQL query, I get an empty array:

query webhookSubscriptions{
  webhookSubscriptions(first: 20){
    nodes{
      id
      topic
      createdAt
    }
  }
}

Expected behavior

I expect all the webhooks I have on the config.webhooks to be always subscribed.

Actual behavior

Sometimes the webhooks are not subscribed

Steps to reproduce the problem

  1. Create a Shopify app
  2. Add a webhook using the generator: rails g shopify_app:add_webhook --topic app/uninstalled --path webhooks/app_uninstalled
  3. Run the app
  4. Install it on your store
  5. Check which webhook subscriptions you have using the graphQL query:
    query webhookSubscriptions{
    webhookSubscriptions(first: 20){
    nodes{
      id
      topic
      createdAt
    }
    }
    }

Logs

image

More context

BaggioGiacomo commented 6 days ago

Since none haven't answered yet, I've taken a deeper look to the post authenticate task/webhooks installing process This is what happens:

  1. The default post authenticate task enqueue the ShopifyApp::WebhooksManagerJob
  2. This job calls a method from the ShopifyAPI library -> ShopifyAPI::Webhooks::Registry.register_all(session: session)
  3. The register_all method takes all the keys from the @registry variable and then register each topic

My question is, who is actually populating the @registry variable? Isn't it empty? I've seen that only the ShopifyApp::WebhooksManager.register_all populates the @registry but this method is only called by recreate_webhooks! method

I hope to get an answer soon because the documentation doesn't explain this concept well and receiving support from the support team takes ages.

Thanks

matteodepalo commented 6 days ago

Hi @BaggioGiacomo, thank you for opening this issue, the team will take a look.