Ravn::BDE::Bolt::
DeliveryNotifications
module
Automated delivery notification Bolt
component. Equivalent of email “DSN” - Delivery Status Notification.
Emits: - direct.bolt.received.$bolt_id
Consumes: - direct.bolt.received.$bolt_id
apply( bolt_class, from: :default )
Add some dsn-specific configuration to bolts that have DSNs.
def self::apply( bolt_class, from: :default )
super
bolt_class.stateful_variable :expected_dsns, default: {}
self.log.debug "Applying DSN stuff from %p to %p" % [ self, bolt_class ]
from_segment = bolt_class.segment_for_config( from )
bolt_class.singleton_attr_accessor( :dsns_from )
bolt_class.dsns_from = from_segment
end
Returns true
if all expected DSNs have been received.
def all_dsns_received?
times = self.expected_dsns&.values or return false
return times.all?
end
event_payload_for( phase, originating_event )
Return the ‘data’ section for the bolt message emitted during the given phase
.
def event_payload_for( phase, originating_event )
payload = super
case phase
when :send
payload[ :expected_dsns ] = self.expected_dsns
when :summarize
if originating_event.type.start_with?( 'direct.bolt.received' )
callsign = originating_event.callsign
payload[ :expected_dsns ] = { callsign => self.expected_dsns[ callsign ] }
end
end
return payload
end
Returns true
if the bolt should be terminated and saved to history.
def ready_to_be_finished?
return super && self.all_dsns_received?
end
Overloaded to send the automated dsn.
def receive_phase( event )
super
data = {
instance_id: event.data[:instance_id]
}
fields = { to: event.callsign, data: data }
return self.send_message( 'direct.bolt.received.${bolt_id}', fields )
end
recipient_segment_members()
Fetch the map of who DSNs are expected from at the current moment as a Hash keyed by callsign.
def recipient_segment_members
segment_members = self.class.dsns_from.to_h
segment_members.delete( Ravn::BDE.callsign )
return segment_members
end
Overloaded to set up the expected dsn table.
def send_phase( event )
self.expected_dsns = self.recipient_segment_members
self.log.debug "Expecting DSN from %d recipients" % [ self.expected_dsns.size ]
super
end
Overloaded to record dsn. This may finish the bolt (via super
) if it was the last expected dsn.
def summarize_phase( event )
if self.is_target_of?( event )
if event.type.start_with?( 'direct.bolt.received' )
callsign = event.callsign or raise "event is missing a callsign"
self.log.info "Got DSN for %s [%s] from %s" %
[ self.class.name, self.id, callsign ]
self.expected_dsns = self.expected_dsns.merge( callsign => Ravn.time )
end
else
self.log.warn "Ignoring event from another instance! %p" % [ event ]
end
super
end