Module: PlanMyStuff::Notifications
- Defined in:
- lib/plan_my_stuff/notifications.rb
Overview
Central instrumentation helper. Domain classes call PlanMyStuff::Notifications.instrument at mutation points so consuming apps can subscribe for email, webhooks, Slack, etc.
Events are fired under the <event>.plan_my_stuff namespace via ActiveSupport::Notifications (Rails convention: event first, library last - matches sql.active_record, deliver.action_mailer). Subscribers run synchronously.
Constant Summary collapse
- EVENT_SUFFIX =
'plan_my_stuff'- SKIPPED_LOG_KEYS =
%i[user timestamp visibility visibility_allowlist].freeze
Class Method Summary collapse
-
.build_payload(resource, actor, extra) ⇒ Hash
Builds the payload hash for an event.
-
.infer_resource_key(resource) ⇒ Symbol
Maps a resource object to its payload key.
-
.instrument(event, resource, user: nil, **extra) ⇒ void
Fires <event>.plan_my_stuff with a normalized payload.
-
.log(event, payload) ⇒ void
Emits a debug log line for the event.
- .log_fields(payload) ⇒ String
- .rails_logger ⇒ Logger?
-
.resolve_current_user ⇒ Object?
Invokes
config.current_userif it responds tocall. -
.visibility_fields(resource) ⇒ Hash
Extracts visibility + allowlist from
Issue/Commentresources.
Class Method Details
.build_payload(resource, actor, extra) ⇒ Hash
Builds the payload hash for an event.
56 57 58 59 60 61 62 63 64 |
# File 'lib/plan_my_stuff/notifications.rb', line 56 def build_payload(resource, actor, extra) payload = { infer_resource_key(resource) => resource, :user => actor, :timestamp => Time.current, } payload.merge!(visibility_fields(resource)) payload.merge(extra) end |
.infer_resource_key(resource) ⇒ Symbol
Maps a resource object to its payload key.
72 73 74 75 76 77 78 79 |
# File 'lib/plan_my_stuff/notifications.rb', line 72 def infer_resource_key(resource) case resource when PlanMyStuff::Issue then :issue when PlanMyStuff::Comment then :comment when PlanMyStuff::BaseProjectItem then :project_item else :resource end end |
.instrument(event, resource, user: nil, **extra) ⇒ void
This method returns an undefined value.
Fires <event>.plan_my_stuff with a normalized payload.
30 31 32 33 34 35 |
# File 'lib/plan_my_stuff/notifications.rb', line 30 def instrument(event, resource, user: nil, **extra) actor = user || resolve_current_user payload = build_payload(resource, actor, extra) log(event, payload) ActiveSupport::Notifications.instrument("#{event}.#{EVENT_SUFFIX}", payload) end |
.log(event, payload) ⇒ void
This method returns an undefined value.
Emits a debug log line for the event. No-op when no logger is available (e.g. outside Rails).
114 115 116 117 118 119 |
# File 'lib/plan_my_stuff/notifications.rb', line 114 def log(event, payload) logger = rails_logger return if logger.nil? logger.debug { "[PlanMyStuff] #{event}.#{EVENT_SUFFIX} #{log_fields(payload)}" } end |
.log_fields(payload) ⇒ String
133 134 135 136 137 138 139 140 141 142 |
# File 'lib/plan_my_stuff/notifications.rb', line 133 def log_fields(payload) fields = [] fields << "user=#{payload[:user].inspect}" if payload.key?(:user) payload.each do |key, value| next if SKIPPED_LOG_KEYS.include?(key) fields << "#{key}=#{value.inspect}" end fields.join(' ') end |
.rails_logger ⇒ Logger?
122 123 124 125 126 127 |
# File 'lib/plan_my_stuff/notifications.rb', line 122 def rails_logger return unless defined?(Rails) return unless Rails.respond_to?(:logger) Rails.logger end |
.resolve_current_user ⇒ Object?
Invokes config.current_user if it responds to call.
41 42 43 44 45 46 |
# File 'lib/plan_my_stuff/notifications.rb', line 41 def resolve_current_user resolver = PlanMyStuff.configuration.current_user return if resolver.nil? resolver.respond_to?(:call) ? resolver.call : resolver end |
.visibility_fields(resource) ⇒ Hash
Extracts visibility + allowlist from Issue/Comment resources. Returns an empty hash for resources without visibility.
88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 |
# File 'lib/plan_my_stuff/notifications.rb', line 88 def visibility_fields(resource) case resource when PlanMyStuff::Issue { visibility: resource..visibility, visibility_allowlist: Array.wrap(resource..visibility_allowlist), } when PlanMyStuff::Comment parent_allowlist = resource.issue ? resource.issue..visibility_allowlist : [] { visibility: resource.visibility&.to_s, visibility_allowlist: Array.wrap(parent_allowlist), } else {} end end |