54 lines
1.6 KiB
Ruby
54 lines
1.6 KiB
Ruby
# frozen_string_literal: true
|
|
|
|
module Integrations
|
|
class SlackEventWorker
|
|
include ApplicationWorker
|
|
|
|
EVENTS = {
|
|
'app_home_opened' => SlackEvents::AppHomeOpenedService
|
|
}.freeze
|
|
|
|
feature_category :integrations
|
|
data_consistency :delayed
|
|
urgency :low
|
|
deduplicate :until_executed
|
|
idempotent!
|
|
worker_has_external_dependencies!
|
|
|
|
def self.event?(slack_event)
|
|
EVENTS.key?(slack_event)
|
|
end
|
|
|
|
def perform(args)
|
|
args = args.with_indifferent_access
|
|
|
|
log_extra_metadata_on_done(:slack_event, args[:slack_event])
|
|
log_extra_metadata_on_done(:slack_user_id, args.dig(:params, :event, :user))
|
|
log_extra_metadata_on_done(:slack_workspace_id, args.dig(:params, :team_id))
|
|
|
|
unless self.class.event?(args[:slack_event])
|
|
Sidekiq.logger.error(
|
|
message: 'Unknown slack_event',
|
|
slack_event: args[:slack_event]
|
|
)
|
|
|
|
return
|
|
end
|
|
|
|
# Ensure idempotency by taking out an exclusive lease keyed to `params.event_id`.
|
|
# The `event_id` is "a unique identifier for this specific event, globally unique
|
|
# across all workspaces" and guaranteed to be present as part of the Slack event JSON schema.
|
|
# See https://api.slack.com/types/event.
|
|
lease = Gitlab::ExclusiveLease.new("slack_event:#{args[:params][:event_id]}", timeout: 1.hour.to_i)
|
|
return unless lease.try_obtain
|
|
|
|
service_class = EVENTS[args[:slack_event]]
|
|
response = service_class.new(args[:params]).execute
|
|
|
|
lease.cancel if response.error?
|
|
rescue StandardError => e
|
|
lease.cancel
|
|
raise e
|
|
end
|
|
end
|
|
end
|