mirror of
https://github.com/discourse/discourse.git
synced 2024-12-05 12:23:38 +08:00
784c04ea81
Background: In order to redrive failed webhook events, an operator has to go through and click on each. This PR is adding a mechanism to retry all failed events to help resolve issues quickly once the underlying failure has been resolved. What is the change?: Previously, we had to redeliver each webhook event. This merge is adding a 'Redeliver Failed' button next to the webhook event filter to redeliver all failed events. If there is no failed webhook events to redeliver, 'Redeliver Failed' gets disabled. If you click it, a window pops up to confirm the operator. Failed webhook events will be added to the queue and webhook event list will show the redelivering progress. Every minute, a job will be ran to go through 20 events to redeliver. Every hour, a job will cleanup the redelivering events which have been stored more than 8 hours.
194 lines
5.3 KiB
Ruby
194 lines
5.3 KiB
Ruby
# frozen_string_literal: true
|
|
|
|
class Admin::WebHooksController < Admin::AdminController
|
|
before_action :fetch_web_hook,
|
|
only: %i[show update destroy list_events bulk_events ping redeliver_failed_events]
|
|
|
|
def index
|
|
limit = 50
|
|
offset = params[:offset].to_i
|
|
|
|
web_hooks =
|
|
WebHook
|
|
.limit(limit)
|
|
.offset(offset)
|
|
.includes(:web_hook_event_types)
|
|
.includes(:categories)
|
|
.includes(:groups)
|
|
|
|
data = serialize_data(web_hooks, AdminWebHookSerializer, root: "web_hooks")
|
|
|
|
serialized_grouped_event_types =
|
|
WebHookEventType.active_grouped.transform_values do |array|
|
|
serialize_data(array, WebHookEventTypeSerializer)
|
|
end
|
|
|
|
json = {
|
|
web_hooks: data.delete("web_hooks"),
|
|
extras:
|
|
data.merge(
|
|
grouped_event_types: serialized_grouped_event_types,
|
|
default_event_types:
|
|
serialize_data(WebHook.default_event_types, WebHookEventTypeSerializer),
|
|
content_types: WebHook.content_types.map { |name, id| { id: id, name: name } },
|
|
delivery_statuses:
|
|
WebHook.last_delivery_statuses.map { |name, id| { id: id, name: name.to_s } },
|
|
),
|
|
total_rows_web_hooks: WebHook.count,
|
|
load_more_web_hooks:
|
|
admin_web_hooks_path(limit: limit, offset: offset + limit, format: :json),
|
|
}
|
|
|
|
render json: MultiJson.dump(json), status: 200
|
|
end
|
|
|
|
def show
|
|
data = serialize_data(@web_hook, AdminWebHookSerializer, root: "web_hook")
|
|
web_hook = data.delete("web_hook")
|
|
data = { "extras" => data, "web_hook" => web_hook }
|
|
render json: MultiJson.dump(data), status: 200
|
|
end
|
|
|
|
def edit
|
|
data = serialize_data(@web_hook, AdminWebHookSerializer, root: "web_hook")
|
|
data["extras"] = { "categories" => data.delete(:categories) }
|
|
render json: MultiJson.dump(data), status: 200
|
|
end
|
|
|
|
def create
|
|
web_hook = WebHook.new(web_hook_params)
|
|
|
|
if web_hook.save
|
|
StaffActionLogger.new(current_user).log_web_hook(
|
|
web_hook,
|
|
UserHistory.actions[:web_hook_create],
|
|
)
|
|
render_serialized(web_hook, AdminWebHookSerializer, root: "web_hook")
|
|
else
|
|
render_json_error web_hook.errors.full_messages
|
|
end
|
|
end
|
|
|
|
def update
|
|
if @web_hook.update(web_hook_params)
|
|
StaffActionLogger.new(current_user).log_web_hook(
|
|
@web_hook,
|
|
UserHistory.actions[:web_hook_update],
|
|
changes: @web_hook.saved_changes,
|
|
)
|
|
render_serialized(@web_hook, AdminWebHookSerializer, root: "web_hook")
|
|
else
|
|
render_json_error @web_hook.errors.full_messages
|
|
end
|
|
end
|
|
|
|
def destroy
|
|
@web_hook.destroy!
|
|
StaffActionLogger.new(current_user).log_web_hook(
|
|
@web_hook,
|
|
UserHistory.actions[:web_hook_destroy],
|
|
)
|
|
render json: success_json
|
|
end
|
|
|
|
def list_events
|
|
limit = 50
|
|
offset = params[:offset].to_i
|
|
events = @web_hook.web_hook_events.includes(:redelivering_webhook_event)
|
|
status = params[:status]
|
|
if status == "successful"
|
|
events = events.successful
|
|
elsif status == "failed"
|
|
events = events.failed
|
|
end
|
|
|
|
total = events.count
|
|
events = events.limit(limit).offset(offset)
|
|
|
|
json = {
|
|
web_hook_events: serialize_data(events, AdminWebHookEventSerializer),
|
|
total_rows_web_hook_events: total,
|
|
load_more_web_hook_events:
|
|
web_hook_events_admin_api_index_path(
|
|
limit: limit,
|
|
offset: offset + limit,
|
|
status: status,
|
|
format: :json,
|
|
),
|
|
extras: {
|
|
web_hook_id: @web_hook.id,
|
|
},
|
|
}
|
|
|
|
render json: MultiJson.dump(json), status: 200
|
|
end
|
|
|
|
def bulk_events
|
|
params.require(:ids)
|
|
web_hook_events = @web_hook.web_hook_events.where(id: params[:ids])
|
|
render_serialized(web_hook_events, AdminWebHookEventSerializer)
|
|
end
|
|
|
|
def redeliver_event
|
|
web_hook_event = WebHookEvent.find_by(id: params[:event_id])
|
|
|
|
if web_hook_event
|
|
web_hook = web_hook_event.web_hook
|
|
emitter = WebHookEmitter.new(web_hook, web_hook_event)
|
|
emitter.emit!(headers: MultiJson.load(web_hook_event.headers), body: web_hook_event.payload)
|
|
render_serialized(web_hook_event, AdminWebHookEventSerializer, root: "web_hook_event")
|
|
else
|
|
render json: failed_json
|
|
end
|
|
end
|
|
|
|
def redeliver_failed_events
|
|
web_hook_events =
|
|
@web_hook
|
|
.web_hook_events
|
|
.includes(:redelivering_webhook_event)
|
|
.not_ping
|
|
.where(id: params[:event_ids])
|
|
|
|
raise Discourse::InvalidParameters if web_hook_events.count.zero?
|
|
|
|
web_hook_events.each do |web_hook_event|
|
|
if !web_hook_event.redelivering_webhook_event
|
|
RedeliveringWebhookEvent.create!(web_hook_event: web_hook_event)
|
|
end
|
|
end
|
|
render json: { event_ids: web_hook_events.map(&:id) }
|
|
end
|
|
|
|
def ping
|
|
Jobs.enqueue(
|
|
:emit_web_hook_event,
|
|
web_hook_id: @web_hook.id,
|
|
event_type: "ping",
|
|
event_name: "ping",
|
|
)
|
|
render json: success_json
|
|
end
|
|
|
|
private
|
|
|
|
def web_hook_params
|
|
params.require(:web_hook).permit(
|
|
:payload_url,
|
|
:content_type,
|
|
:secret,
|
|
:wildcard_web_hook,
|
|
:active,
|
|
:verify_certificate,
|
|
web_hook_event_type_ids: [],
|
|
group_ids: [],
|
|
tag_names: [],
|
|
category_ids: [],
|
|
)
|
|
end
|
|
|
|
def fetch_web_hook
|
|
@web_hook = WebHook.find(params[:id])
|
|
end
|
|
end
|