mirror of
https://github.com/openfoodfoundation/openfoodnetwork
synced 2026-02-27 01:43:22 +00:00
1. Add WebhookDeliveryJob
This job is responsible for delivering a payload for one webhook event only. It allows the action to run asynchronously (and not slow down the calling process).
This commit is contained in:
31
app/jobs/webhook_delivery_job.rb
Normal file
31
app/jobs/webhook_delivery_job.rb
Normal file
@@ -0,0 +1,31 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
require "faraday"
|
||||
|
||||
# Deliver a webhook payload
|
||||
# As a delayed job, it can run asynchronously and handle retries.
|
||||
class WebhookDeliveryJob < ApplicationJob
|
||||
queue_as :default
|
||||
|
||||
def perform(url, event, payload)
|
||||
body = {
|
||||
id: job_id,
|
||||
at: Time.zone.now.to_s,
|
||||
event: event,
|
||||
data: payload,
|
||||
}
|
||||
|
||||
notify_endpoint(url, body)
|
||||
end
|
||||
|
||||
def notify_endpoint(url, body)
|
||||
connection = Faraday.new(
|
||||
request: { timeout: 30 },
|
||||
headers: {
|
||||
'User-Agent' => 'openfoodnetwork_webhook/1.0',
|
||||
'Content-Type' => 'application/json',
|
||||
}
|
||||
)
|
||||
connection.post(url, body.to_json)
|
||||
end
|
||||
end
|
||||
47
spec/jobs/webhook_delivery_job_spec.rb
Normal file
47
spec/jobs/webhook_delivery_job_spec.rb
Normal file
@@ -0,0 +1,47 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
require 'spec_helper'
|
||||
|
||||
describe WebhookDeliveryJob do
|
||||
subject { WebhookDeliveryJob.new(url, event, data) }
|
||||
let(:url) { 'https://test/endpoint' }
|
||||
let(:event) { 'order_cycle.opened' }
|
||||
let(:data) {
|
||||
{
|
||||
order_cycle_id: 123, name: "Order cycle 1", open_at: 1.minute.ago.to_s, tags: ["tag1", "tag2"]
|
||||
}
|
||||
}
|
||||
|
||||
before do
|
||||
stub_request(:post, url)
|
||||
end
|
||||
|
||||
it "sends a request to specified url" do
|
||||
subject.perform_now
|
||||
expect(a_request(:post, url)).to have_been_made.once
|
||||
end
|
||||
|
||||
it "delivers a payload" do
|
||||
Timecop.freeze(Time.zone.now) do
|
||||
expected_body = {
|
||||
id: /.+/,
|
||||
at: Time.zone.now.to_s,
|
||||
event: event,
|
||||
data: data,
|
||||
}
|
||||
|
||||
subject.perform_now
|
||||
expect(a_request(:post, url).with(body: expected_body)).
|
||||
to have_been_made.once
|
||||
end
|
||||
end
|
||||
|
||||
# To be implemented in following commits
|
||||
pending "can't access local secrets" # see https://medium.com/in-the-weeds/all-about-paperclips-cve-2017-0889-server-side-request-forgery-ssrf-vulnerability-8cb2b1c96fe8
|
||||
|
||||
describe "retrying" do
|
||||
pending "doesn't retry on internal failure"
|
||||
pending "retries after external failure"
|
||||
pending "stops retrying after a while"
|
||||
end
|
||||
end
|
||||
Reference in New Issue
Block a user