IFRCGo / cbs

Red Cross: Community-Based Surveillance
https://cbsrc.org/
Other
102 stars 110 forks source link

Design discussion on Notification Gateway #821

Open einari opened 6 years ago

einari commented 6 years ago

Goals Create a notification gateway that is independent and decoupled from the concrete communication channels. A person associated with the system can be configured to get notification through one or more channels:

The person should be having a primary channel and could also be made possible to push to multiple at the same time.

Design considerations In the system today the only type of person that is formalized is a DataCollector. Associated with a DataCollector is a set of information that is used typically in what is known as Volunteer Reporting. This bounded context is about to change and be merged with what is known as User Management and will be called Reporting. In the notification gateway, all of the details are not needed at this point, but the ID and the name is essential.

The Notification Gateway should subscribe to events for lifecycle management of datacollectors.

It should have commands and events for adding channel and details about the channel for a datacollector.

public class AddChannelToDataCollector
{
     public DataCollectorId DataCollectorId { get; set; }
     public ChannelID ChannelId { get; set; }
     public ChannelTarget Target { get; set; }
}

The ChannelTarget could then be telephone number or email address for instance. This design would fit very well with these two types of channels - but might not be enough for more complex channels that could require more details.

The event would be:

public class ChannelAddedToDataCollector
{
    public Guid DataCollectorId { get; }
    public Guid ChannelId { get; }
    public string Target { get; }
}

You can from this have multiple event processors, one that adds the channel and target information onto the readmodel of the DataCollector - which is holding details about the channel, target, if its primary and such. This would be an array on the DataCollector representation in Notification Gateway.

The other event processor would then save it as a key/value with the key being the channel Id and the value being the target.

For other bounded contexts to send, they would go through commands looking something like:

public class NotifyDataCollector 
{
     public DataCollectorId DataCollector { get; set; }
     public string Body { get; set; }
     public string Subject { get; set; } // If this is needed at all... ?? 
}
public class NotifyChannel
{
     public ChannelId Channel { get; set; }
     public string Body { get; set; }
     public string Subject { get; set; } // If this is needed at all... ?? 
}

You could then have 2 different aggregate roots; DataCollectorNotification & ChannelNotification. You'd expose the appropriate notify method on these and apply the relevant events. You could then have a policy processing an event for DataCollectorNotification that would then need to get the correct channel and then it could talk to the ChannelNotification aggregate and actually notify through it. You'd then end up in an event processor that would then delegate it to the appropriate destination based on the definition of the ChannelID- which could be linked to a well known Id per channel type.

With messages coming in, you'd know the channelId it was received on and you can identify the target information and put this on the MessageReceived event that other bounded contexts can then process.

jakhog commented 6 years ago

@babajon @AG-83