Service - Notification Manager: Difference between revisions

From Izara Wiki
Jump to navigation Jump to search
No edit summary
No edit summary
Line 1: Line 1:
= Overview =
[[Service - Notification Manager]]


Consolidates and sends notifications to any number of receiver services. Will be used for user notifications but can have other types of receiver services added. Activities are received from [[Service - Activity Switchboard|Activity Switchboard]] service.
= Lambda Functions =


Notification groups set whether activities are considated (eg per day/per month/per x number of activities), if considated activities are stored here until sending is triggered, according to the considation rules. If not consolidated they are sent on immediately.
== RcvActivityMsg ==


= Repository =
<syntaxhighlight lang="JavaScript">
/**
* Receives one activity message from Activity Switchboard, find matching notification, stores for consolidation or sends immediately
* @param {Object[]} event.activityMsg
* @param {Object} event.activityMsg.messageAttributes
* @param {Object} event.activityMsg.message
* @param {String} event.uniqueId - In NotificationMgr, uniqueId is notificationId
* @param {Object[]} event.additionalData - additional params set in the trigger group
* @param {number} event.time
* @param {string} event.additionalData.notificationId - matches notificationId in notifications table
*
*/
</syntaxhighlight>
 
=== HdrSqs ===
 
Subscribes to [[Service - Activity Switchboard]] OutTriggerGroupPassed topic, (? filter policy limit) receiverTag = {this service's izServiceName}


https://bitbucket.org/stb_working/notification-manager/src/master/
=== logic ===
# get notification node by getNodeAndRelationship
#* nodeLabel: "notification"
#* nodeProperties.notificationId
#* relationshipType: "has_notification"
#* relationshipDirection: "incoming"
#* toNodeVersionedDataLabels: ["notificationGroupSettings"]
# if not found notification or notificationGroup node
#* throw new NoRetryError
# If have setting and consolidated = true
#* save ''activityMsg'' to ConsolidationPending table
# else
#* invoke [[#sendNotificationToReceiver]]


= DynamoDB tables =


== PendingConsolidation Table ==
== DisableNotificationGroups ==


; partition key
<syntaxhighlight lang="JavaScript">
* notificationGroupId
/**
: type: string
* Disables a set of matching notification groups
: comes from: random UUID
* @param {string} notificationGroupId - null if not supplied
; sort key
*
* time
*/
: type: number
</syntaxhighlight>
: {timestamp activity handled in Activity Switchboard}_{small random UUID}


= Object Schemas =
=== HdrSqs ===


; Additional Information: [[Per Service Schemas]]
Subscribes to InDisableNotificationGroups topic


== objType ==
=== logic ===


=== notificationGroup ===
# get notificationGroup node by GraphHandler getNodeAndRelationships
#* nodeLabel: "notificationGroup"
#* nodeProperties.notificationGroupId
#* relationshipType: "has_notification"
#* relationshipDirection: "outgoing"
# if not found notificationGroup or notification node
#* throw new NoRetryError
# else
#* get notificationId for each child notification node
# invoke [[#disableNotificationGroup]]


* Groups many notificatons together
== UpdateNotificationGroup ==
* Simplifies management of similar notifications
* Allows for consolidation of notifications at notification group level


<syntaxhighlight lang="JavaScript">
<syntaxhighlight lang="JavaScript">
{
/**
objectType: "notificationGroup",
* Update a notification group
canDelete: false,
* @param {string} notificationGroupId
    complexFilterServiceTag: "complexFilter",
* @param {string} notificationGroupName
addOnDataStructure: [
* @param {boolean} consolidated
{
* @param {string} consolidatedType
type: "versionedData",
* @param {..?} consolidatedFrequency
versionedDataLabel: "notificationGroupSettings",
* @param {boolean} consolidatedSendIfEmpty
storageResourceTag: "myGraph",
* @param {boolean} enabled
fieldNames: [
*
{ // fieldName in versionedData should now same in main objectSchema
*/
fieldName: "notificationGroupName",
type: "string",
requiredOnCreate: true, // default = false
canUpdate: true, // default = true
validation: {
pattern: pattern
}
},
{  
fieldName: "consolidated",
type: "boolean",
requiredOnCreate: true,
canUpdate: true,
validation: {
pattern: pattern
}
},
{
fieldName: "consolidatedType",
type: "string",
requiredOnCreate: true,
canUpdate: true,
validation: {
pattern: pattern
}
},
{
fieldName: "consolidatedFrequency",
type: "string",
requiredOnCreate: true,
canUpdate: true,
validation: {
pattern: pattern
}
},
{
fieldName: "consolidatedSendIfEmpty",
type: "boolean",
requiredOnCreate: true,
canUpdate: true,
validation: {
pattern: pattern
}
}
]
}
    ],
    overwriteGeneratedMainFunction: ["create", "get", "update"],
    storageResources: {
myGraph: {
storageType: "graph",
graphServerTag: "GraphHandler"
}
    },
    fieldNames: { // see Per Service Schemas
notificationGroupId: {
    type: "string",
optionalOnCreate: true,
canUpdate: false,
validation: {
pattern: pattern
},
storageResourceTags: ['myGraph']
},
receiverTag: {
type: "string",
requiredOnCreate: true,
canUpdate: false,
validation: {
pattern: pattern
},
storageResourceTags: ['myGraph']
},
additionalData: {
type: "object",
optionalOnCreate: true,
canUpdate: false,
validation: {
pattern: pattern
},
storageResourceTags: ['myGraph']
}
    },
    identifiers: [
{
type: "identifier",
fieldName: "notificationGroupId"
}
    ]
}
</syntaxhighlight>
</syntaxhighlight>


==== fieldNames ====
=== HdrSqs ===


; notificationGroupId (identifier)
Subscribes to InUpdateNotificationGroup topic
: comes from: random UUID
; notificationGroupName
: string name set by reciever service, optional
; additionalData
: set by the creating service, gets added to notifications sent to the receiver
: eg: can include the actual userId and  used to make the groupingId
; receiverTag
: set by the creating service
: eg ContactMethodEmail
; consolidated
: true|false
: optional, if excluded (or value not true), defaults to false
; consolidatedType
: overview|detailed
: ''overview'' sends a count of each type of notification, ''detailed'' lists each activity message
; consolidatedFrequency
: not sure, maybe use some sort of standard like cron
; consolidatedNextSendDue
: timestamp for next due time to send notification
; consolidatedSendIfEmpty
: true|false


=== logic ===


=== notification ===
# get notificationGroup node by GraphHandler getNodeAndRelationships
#* nodeLabel: "notificationGroup"
#* nodeProperties.notificationGroupId
#* relationshipType: "has_notification"
#* relationshipDirection: "outgoing"
# if not found notificationGroup or notification node
#* throw new NoRetryError
# else
#* get notificationId for each child notification node
# update notificationGroup node by send message to [[Service - Graph Handler]] InCreateVersionedData
#* nodeStructure
#** nodeLabel: "notificationGroup"
#** nodeProperties.notificationGroupId
#* versionDataStructure
#** nodeLabel: "notificationGroupSetting"
#** nodeProperties: {notificationGroupName, consolidated, consolidatedType, consolidatedFrequency, consolidatedSendIfEmpty}
# if enabled = false
## invoke [[#disableNotificationGroup]]
# if enabled = true
## invoke [[#enableNotificationGroup]]
 
== DisableNotifications ==


<syntaxhighlight lang="JavaScript">
<syntaxhighlight lang="JavaScript">
{
/**
objectType: "notification",
* Disables a set of matching notification groups
canDelete: false,
* @param {string[]} notificationIds
complexFilterServiceTag: "complexFilter",
*
addOnDataStructure: [
*/
{
type: "versionedData",
versionedDataLabel: "notificationSettings",
storageResourceTag: "myGraph",
fieldNames: [
{ // fieldName in versionedData should now same in main objectSchema
fieldName: "notificationName",
type: "string",
requiredOnCreate: true, // default = false
canUpdate: true, // default = true
validation: {
pattern: pattern
}
}
]
}
    ],
    overwriteGeneratedMainFunction: ["create", "get", "update"],
    storageResources: {
myGraph: {
storageType: "graph",
graphServerTag: "GraphHandler"
}
    },
    fieldNames: {
notificationId: {
    type: "string",
optionalOnCreate: true,
canUpdate: false,
validation: {
pattern: pattern
},
storageResourceTags: ['myGraph']
},
    },
    identifiers: [
{
type: "identifier",
fieldName: "notificationId"
}
    ]
}
</syntaxhighlight>
</syntaxhighlight>


==== fieldNames ====
=== HdrSqs ===
 
Subscribes to InDisableNotifications topic


; notificationId (identifier)
=== logic ===
: comes from: random UUID
; notificationName
: string name set by reciever service, optional


# for each notificationIds
## change relationshipType to "disabled_notification" by send message to [[Service - Graph Handler]] InChangeRelationshipType
## send message to [[Service - Activity Switchboard]] InRemoveTriggerGroup
##* notificationId
## send message to OutNotificationDisabled topic
##* notificationId


=== notificationTrigger ===
== CreateNotificationGroup ==


<syntaxhighlight lang="JavaScript">
<syntaxhighlight lang="JavaScript">
{
/**
objectType: "notificationTrigger",
* Creates one notification group
canDelete: false,
* @param {string} notificationGroupId
    complexFilterServiceTag: "complexFilter",
* @param {string} notificationGroupName
    overwriteGeneratedMainFunction: ["create", "get"],
* @param {boolean} consolidated
    storageResources: {
* @param {string} consolidatedType
myGraph: {
* @param {..?} consolidatedFrequency
storageType: "graph",
* @param {boolean} consolidatedSendIfEmpty
graphServerTag: "GraphHandler"
* @param {Object} additionalData
}
*
    },
*/
    fieldNames: {
notificationTriggerId: {
type: "string",
optionalOnCreate: true,
canUpdate: false,
validation: {
pattern: pattern
},
storageResourceTags: ['myGraph']
},
propertyName: {
type: "string",
optionalOnCreate: true,
canUpdate: false,
validation: {
pattern: pattern
},
storageResourceTags: ['myGraph']
},
valueType: {
type: "string",
requiredOnCreate: true,
canUpdate: false,
validation: {
pattern: pattern
},
storageResourceTags: ['myGraph']
},
valueString: {
type: "string",
optionalOnCreate: true,
canUpdate: false,
validation: {
pattern: pattern
},
storageResourceTags: ['myGraph']
},
valueNumber: {
type: "number",
optionalOnCreate: true,
canUpdate: false,
validation: {
pattern: pattern
},
storageResourceTags: ['myGraph']
},
values: {
type: "arrayMixed",
optionalOnCreate: true,
canUpdate: false,
validation: {
pattern: pattern
},
storageResourceTags: ['myGraph']
}
    },
    identifiers: [
{
type: "identifier",
fieldName: "notificationTriggerId"
}
    ]
}
</syntaxhighlight>
</syntaxhighlight>


==== fieldNames ====
=== HdrSqs ===
 
Subscribes to InCreateNotificationGroup topic


; notificationTriggerId (identifier)
Validator:
: comes from: random UUID
* notificationGroupId cannot be empty string
; propertyName
   
: can be a nested property, use dot notation
=== logic ===
: "serviceName" and "topicName" valueTypes do not have propertyName
; valueType
: property|attribute|serviceName|topicName
; valueString
: type: string
; valueNumber
: type: number
; values
: type: arrayMixed


# if ''consolidated'' = true, validate:
## consolidatedType must equal "overview"|"detailed"
## consolidatedFrequency ..?
## consolidatedSendIfEmpty, set to false if not boolean and set to true
# create notificationGroup by send message to [[Service - Graph Handler]] InCreateNodeWithVersionedData
#* nodeStructure
#** nodeLabel: "notificationGroup"
#** nodeProperties: {notificationGroupId, additionalData}
#* versionedDatas
#** nodeLabel: "notificationGroupSetting"
#** nodeProperties: {notificationGroupName, consolidated, consolidatedType, consolidatedFrequency, consolidatedSendIfEmpty}
# send message to OutNotificationGroupCreated topic, can include full notificationGroup object


=== consolidated ===
== CreateNotifications ==


<syntaxhighlight lang="JavaScript">
<syntaxhighlight lang="JavaScript">
{
/**
objectType: "consolidated",
* Creates muti notifications
canDelete: false,
* @param {string} userId
    complexFilterServiceTag: "complexFilter",
* @param {string} notificationGroupId
    storageResources: {
* @param {Object[]} notifications
dynamoDB: {
* @param {string} [notifications.notificationName]
storageType: "dynamoDB",
* @param {Object[]} notifications.triggers
tableName: "PendingConsolidation"
* @param {string} notifications.triggers.propertyName
}
* @param {string} notifications.triggers.valueType - property|attribute
    },
* @param {string} [notifications.triggers.value] - either value or values will be set
    fieldNames: {
* @param {string[]} [notifications.triggers.values] - either value or values will be set
notificationGroupId: {
*
type: "string",
*/
requiredOnCreate: true,
canUpdate: false,
validation: {
pattern: pattern
},
storageResourceTags: ['dynamoDB'],
fromServiceNameTag: "NotificationMgr" ,
fromObjectType: "notificationGroup"
},
time: {
type: "number",
requiredOnCreate: true,
canUpdate: false,
validation: {
pattern: pattern
},
storageResourceTags: ['dynamoDB']
},
activityMsg: {
type: "object",
requiredOnCreate: true,
canUpdate: false,
validation: {
pattern: pattern
},
storageResourceTags: ['dynamoDB']
}
    },
    identifiers: [
{
type: "partitionKey",
fieldName: "notificationGroupId"
},
{
type: "sortKey",
fieldName: "time"
}
    ]
}
</syntaxhighlight>
</syntaxhighlight>


==== fieldNames ====
=== HdrSqs ===


; notificationGroupId (partition key)
Subscribes to InCreateNotifications topic
: comes from: random UUID
; time (sort key)
: comes from {timestamp activity handled in Activity Switchboard}_{small random UUID}
: adding the UUID to ensure no clashing records with the same timestamp and notificationGroupId
; activityMsg
: copy of the message delivered from Activity Switchboard


Validator:
* notificationGroupId cannot be empty string
* notifications cannot be an empty array? Can limit number of notifications in array?
   
=== logic ===


== Object Relationships ==
# get notificationGroup node by invoke graphSharedLib.getNode
#* nodeStructure
#** nodeLabel: "notificationGroup"
#** nodeProperties: {notificationId}
#* versionedDataLabels: ["notificationGroupSetting"]
# if not found notificationGroup node
## send message to OutCreateNotificationsFailed topic
##* notificationGroupId
##* notifications
##* errorsFound: "NotificationGroupNotFound"
## return
# for each ''notifications'':
## create an object that contains
##* notificationName
##* triggers
## hash this object into variable named ''notificationId''
## create child notification node and relationship
### send message to [[Service - Graph Handler]] InCreateChildNodeAndRelationship
###* parentNodeStructure
###** nodeLabel: "notificationGroup"
###** nodeProperties: {notificationGroupId}
###* createChildNodeStructure
###** nodeStructure
###*** nodeLabel: "notification"
###*** nodePropertis: {notificationId}
###* createRelationshipStructure
###** relationshipStructure
###*** relationshipType: "has_notification"
###*** relationshipDirection: "outgoing"
## for each ''notifications.triggers'':
### create ''notificationTriggerId'' by {notificationId} + "_" + {randon UUID}
### create child notificationTrigger node and relationship
#### send message to [[Service - Graph Handler]] InCreateChildNodeAndRelationship
####* parentNodeStructure
####** nodeLabel: "notification"
####** nodeProperties: {notificationId}
####* createChildNodeStructure
####** nodeStructure
####*** nodeLabel: "notificationTrigger"
####*** nodePropertis: {notificationTriggerId}
####* createRelationshipStructure
####** relationshipStructure
####*** relationshipType: "has_notificationTrigger"
####*** relationshipDirection: "outgoing"
## create an object that contains 'notificationId' and 'triggers' for invoke sharedCreateTriggerGroup.sharedCreateTriggerGroup
## invoke sharedCreateTriggerGroup.sharedCreateTriggerGroup
### send message to [[Service - Activity Switchboard]] InCreateTriggerGroup topic
###* uniqueId: {notificationId}
###* additionalData: {}
###* triggers: {notification.triggers}
## send message to OutNotificationCreated topic, can include full notification object
 
== NotificationGroup/List ==


=== has_notificationGroup ===
<syntaxhighlight lang="JavaScript">
<syntaxhighlight lang="JavaScript">
{
/**
"has_notificationGroup": {
* Lists all notification groups for one primary key (notificationGroupId/uniqueId)
properties: {
* @param {string} receiverTag
"originTimestamp": {
* @param {string} groupingId
    type: "number",            // "string" | "number" ...
* @param {string} [uniqueIdPrefix=null]
requiredOnCreate: false,  // default=false
*
canUpdate: true,          // default = true
* @returns {Object[]} array of objects, each object is one notification group
validation: {}           // ajv syntax
*/
}
},
storageResources: {
myGraph: {
storageType: "graph",
graphServerTag: "graphHandler"
}
},
links: [
{
storageResourceTags: ["myGraph"],
from: {
objType: {
serviceTag: "ContactMethodEmail",
objectType: "email"
},
linkType: "one",
},
to: {
objType: {
serviceTag: "NotificationMgr",
objectType: "notificationGroup"
},
requiredOnCreate: true,
linkType: "many",
handler: true
}
}
]
}
}
</syntaxhighlight>
</syntaxhighlight>
: links email to notificationGroup


=== disabled_notificationGroup ===
=== HdrApi ===
<syntaxhighlight lang="JavaScript">
{
"disabled_notificationGroup": {
properties: {
"originTimestamp": {
    type: "number",            // "string" | "number" ...
requiredOnCreate: false,  // default=false
canUpdate: true,          // default = true
validation: {}            // ajv syntax
}
},
storageResources: {
myGraph: {
storageType: "graph",
graphServerTag: "GraphHandler"
}
},
links: [
{
storageResourceTags: ["myGraph"],
from: {
objType: {
serviceTag: "ContactMethodEmail",
objectType: "email"
},
linkType: "one"
},
to: {
objType: {
serviceTag: "NotificationMgr",
objectType: "notificationGroup"
},
linkType: "many",
handler: true
}
}
]
}
}
</syntaxhighlight>


Validator:
* receiverTag
* groupingId
* uniqueIdPrefix with default value


=== has_notification ===
==== handler logic ====
<syntaxhighlight lang="JavaScript">
{
"has_notification": {
properties: {
"originTimestamp": {
    type: "number",            // "string" | "number" ...
requiredOnCreate: false,  // default=false
canUpdate: true,          // default = true
validation: {}            // ajv syntax
}
},
storageResources: {
myGraph: {
storageType: "graph",
graphServerTag: "GraphHandler"
}
},
links: [
{
storageResourceTags: ["myGraph"],
from: {
objType: {
serviceTag: "NotificationMgr",
objectType: "notificationGroup"
},
linkType: "one",
handler: true
},
to: {
objType: {
serviceTag: "NotificationMgr",
objectType: "notification"
},
requiredOnCreate: true,
linkType: "many",
handler: true
}
}
]
}
}
</syntaxhighlight>


(standard)


=== disabled_notification ===
=== logic ===
<syntaxhighlight lang="JavaScript">
{
"disabled_notification": {
properties: {
"originTimestamp": {
    type: "number",            // "string" | "number" ...
requiredOnCreate: false,  // default=false
canUpdate: true,          // default = true
validation: {}            // ajv syntax
}
},
storageResources: {
myGraph: {
storageType: "graph",
graphServerTag: "graphHandler"
}
},
links: [
{
storageResourceTags: ["myGraph"],
from: {
objType: {
serviceTag: "NotificationMgr",
objectType: "notificationGroup"
},
linkType: "one",
handler: true
},
to: {
objType: {
serviceTag: "NotificationMgr",
objectType: "notification"
},
linkType: "many",
handler: true
}
}
]
}
}
</syntaxhighlight>


Query NotificationGroups table for all records that match notificationGroupId and if uniqueIdPrefix not null uniqueId ''starts_with'' uniqueIdPrefix, and return.


=== has_notificationTrigger ===
= Functions =
<syntaxhighlight lang="JavaScript">
{
"has_notificationTrigger": {
properties: {
"originTimestamp": {
    type: "number",            // "string" | "number" ...
requiredOnCreate: false,  // default=false
canUpdate: true,          // default = true
validation: {}            // ajv syntax
}
},
storageResources: {
myGraph: {
storageType: "graph",
graphServerTag: "graphHandler"
}
},
links: [
{
storageResourceTags: ["myGraph"],
from: {
objType: {
serviceTag: "NotificationMgr",
objectType: "notification"
},
linkType: "one",
handler: true
},
to: {
objType: {
serviceTag: "NotificationMgr",
objectType: "notificationTrigger"
},
requiredOnCreate: true,
linkType: "many",
handler: true
}
}
]
}
}
</syntaxhighlight>


== sendNotificationToReceiver ==


=== disabled_notificationTrigger ===
<syntaxhighlight lang="JavaScript">
<syntaxhighlight lang="JavaScript">
{
/**
"disabled_notificationTrigger": {
* Send message to receiver endpoint
properties: {
* @param {Object} notification - object from the Notifications table
"originTimestamp": {
* @param {Object} notificationGroup - object from the NotificationGroups table
    type: "number",            // "string" | "number" ...
* @param {string} notificationBody - string sent to receiver
requiredOnCreate: false,  // default=false
*/
canUpdate: true,          // default = true
validation: {}           // ajv syntax
}
},
storageResources: {
myGraph: {
storageType: "graph",
graphServerTag: "graphHandler"
}
},
links: [
{
storageResourceTags: ["myGraph"],
from: {
objType: {
serviceTag: "NotificationMgr",
objectType: "notification"
},
linkType: "one",
handler: true
},
to: {
objType: {
serviceTag: "NotificationMgr",
objectType: "notificationTrigger"
},
linkType: "many",
handler: true
}
}
]
}
}
</syntaxhighlight>
</syntaxhighlight>


== value or values array ==
=== logic ===


* Either 'value' or 'values' should be set, not both, if 'values' is used it means any of the elements in the 'values' array can match.
# get notificationGroup node by getNodeAndRelationships
#* nodeLabel: "notificationGroup"
#* nodeProperties.notificationGroupId
#* relationshipType: "has_notificationGroup"
#* relationshipDirection: "incoming"
#:return; notificationGroup and email node (in future; will have another service eg. SMS, site notification)
# send message to OutNewNotification topic, adding below properties:
#* uniqueId: {emailId}
#* notificationBody
#* additionalData
#* (? filter policy limit) receiverTag gets added to message attributes so can be filtered for by receiving service


* To achieve this on Activity Switchboard a new trigger group is created for each element, each activity group has the full list of other triggers, and one option from this trigger's ''values'' array. If a notification has multiple ''values'' type triggers than a new trigger group on Activity Switchboard is created for each combination.
;  [[Service - User Contact Manager]] and [[Service - Contact Method Email]] will change logic or structure


* "serviceName" and "topicName" valueTypes do not have propertyName
== disableNotificationGroup ==


= serviceName and topicName triggers =
<syntaxhighlight lang="JavaScript">
/**
* @param {Object} notificationGroup
*
*/
</syntaxhighlight>


* Notifications do not have to set their serviceName and/or topicName, if not set then any message that matches the properties will pass
=== logic ===
* Can set only the serviceName, then any message that passess the properties and is from that serviceName passes
* Can set serviceName+topicName, then only messages in that topic will pass
* serviceName and topicName can both be submitted as "values" array, creating multiple trigger groups for each combination


= Consolidated notifications =
# for each notificationId
## change relationshipType to "disabled_notification" by send message to [[Service - Graph Handler]] InChangeRelationshipType
## send message to [[Service - Activity Switchboard]] InRemoveTriggerGroup
##* notificationId
## send message to OutNotificationDisabled topic
##* notificationId
# change relationshipType to "disabled_notificationGroup" by send message to [[Service - Graph Handler]] InChangeRelationshipType
# send message to OutNotificationGroupDisabled topic
#* notificationGroupId


== How to trigger processing for time based consolidations ==  
== enableNotificationGroup ==


* ....
<syntaxhighlight lang="JavaScript">
* maybe can use some sort of queue to store a list of NotificationGroup’s that are due to be sent (either because consolidatedSendIfEmpty == true or there are some activities waiting to be processed)
/**
* @param {Object} notificationGroup
*
*/
</syntaxhighlight>


= Formating the notification body =  
=== logic ===


* Initially the format will be hardwired and simple, but in the future we could create templates for formating the notification body
# for each notificationId
* The notificationBody is currently sent to receiver as a JSON stringified object containing all activityMsgs
## get notification node by GraphHandler getNodeAndRelationships
##* nodeLabel: "notification"
##* nodeProperties.notificationId
##* relationshipType: "has_notificationTrigger"
##* relationshipDirection: "outgoing"
## change relationshipType to "has_notification" by send message to [[Service - Graph Handler]] InChangeRelationshipType
## invoke sharedCreateTriggerGroup.sharedCreateTriggerGroup
### send message to [[Service - Activity Switchboard]] InCreateTriggerGroup
###* uniqueId: notificationId
###* additionalData: {}
###* requestedTriggers: [{notificationTriggers}]
## send message to OutNotificationEnabled topic
##* notificationId
# change relationshipType to "has_notificationGroup" by send message to [[Service - Graph Handler]] InChangeRelationshipType
# send message to OutNotificationGroupEnabled topic
#* notificationGroupId


= Ideas =  
= Sample notification object sent to receiver service =  


* ''overview'' notifications currently count per notification, but could be extended to do aggregates on a per notification, per field level
<syntaxhighlight lang="JavaScript">
* If set to ''overview'' maybe can store just aggregate/s needed for the consolidated notification, at the moment store entire messages, create the overview once when sending notification
{
 
notificationBody: [
= Working documents =
{
 
messageAttributes: {
[[:Category:Working documents - Notification Manager|Working documents - Notification Manager]]
// xxx: yyy
},
message: {
// full body of message received
}
},
],
additionalData: {
userId: ...
},
uniqueId: {emailId}
}
</syntaxhighlight>


[[Category:Backend services| Notification Manager]]
[[Category:Working documents| 2020-11-08]]
[[Category:Working documents - Notification Manager| 2020-11-08]]

Revision as of 03:09, 12 July 2024

Service - Notification Manager

Lambda Functions

RcvActivityMsg

/**
 * Receives one activity message from Activity Switchboard, find matching notification, stores for consolidation or sends immediately
 * @param {Object[]} event.activityMsg
 * @param {Object} event.activityMsg.messageAttributes
 * @param {Object} event.activityMsg.message
 * @param {String} event.uniqueId - In NotificationMgr, uniqueId is notificationId
 * @param {Object[]} event.additionalData - additional params set in the trigger group
 * @param {number} event.time 
 * @param {string} event.additionalData.notificationId - matches notificationId in notifications table
 *
 */

HdrSqs

Subscribes to Service - Activity Switchboard OutTriggerGroupPassed topic, (? filter policy limit) receiverTag = {this service's izServiceName}

logic

  1. get notification node by getNodeAndRelationship
    • nodeLabel: "notification"
    • nodeProperties.notificationId
    • relationshipType: "has_notification"
    • relationshipDirection: "incoming"
    • toNodeVersionedDataLabels: ["notificationGroupSettings"]
  2. if not found notification or notificationGroup node
    • throw new NoRetryError
  3. If have setting and consolidated = true
    • save activityMsg to ConsolidationPending table
  4. else


DisableNotificationGroups

/**
 * Disables a set of matching notification groups
 * @param {string} notificationGroupId - null if not supplied
 *
 */

HdrSqs

Subscribes to InDisableNotificationGroups topic

logic

  1. get notificationGroup node by GraphHandler getNodeAndRelationships
    • nodeLabel: "notificationGroup"
    • nodeProperties.notificationGroupId
    • relationshipType: "has_notification"
    • relationshipDirection: "outgoing"
  2. if not found notificationGroup or notification node
    • throw new NoRetryError
  3. else
    • get notificationId for each child notification node
  4. invoke #disableNotificationGroup

UpdateNotificationGroup

/**
 * Update a notification group
 * @param {string} notificationGroupId
 * @param {string} notificationGroupName
 * @param {boolean} consolidated
 * @param {string} consolidatedType
 * @param {..?} consolidatedFrequency
 * @param {boolean} consolidatedSendIfEmpty
 * @param {boolean} enabled
 *
 */

HdrSqs

Subscribes to InUpdateNotificationGroup topic

logic

  1. get notificationGroup node by GraphHandler getNodeAndRelationships
    • nodeLabel: "notificationGroup"
    • nodeProperties.notificationGroupId
    • relationshipType: "has_notification"
    • relationshipDirection: "outgoing"
  2. if not found notificationGroup or notification node
    • throw new NoRetryError
  3. else
    • get notificationId for each child notification node
  4. update notificationGroup node by send message to Service - Graph Handler InCreateVersionedData
    • nodeStructure
      • nodeLabel: "notificationGroup"
      • nodeProperties.notificationGroupId
    • versionDataStructure
      • nodeLabel: "notificationGroupSetting"
      • nodeProperties: {notificationGroupName, consolidated, consolidatedType, consolidatedFrequency, consolidatedSendIfEmpty}
  5. if enabled = false
    1. invoke #disableNotificationGroup
  6. if enabled = true
    1. invoke #enableNotificationGroup

DisableNotifications

/**
 * Disables a set of matching notification groups
 * @param {string[]} notificationIds
 *
 */

HdrSqs

Subscribes to InDisableNotifications topic

logic

  1. for each notificationIds
    1. change relationshipType to "disabled_notification" by send message to Service - Graph Handler InChangeRelationshipType
    2. send message to Service - Activity Switchboard InRemoveTriggerGroup
      • notificationId
    3. send message to OutNotificationDisabled topic
      • notificationId

CreateNotificationGroup

/**
 * Creates one notification group
 * @param {string} notificationGroupId
 * @param {string} notificationGroupName
 * @param {boolean} consolidated
 * @param {string} consolidatedType
 * @param {..?} consolidatedFrequency
 * @param {boolean} consolidatedSendIfEmpty
 * @param {Object} additionalData
 *
 */

HdrSqs

Subscribes to InCreateNotificationGroup topic

Validator:

  • notificationGroupId cannot be empty string

logic

  1. if consolidated = true, validate:
    1. consolidatedType must equal "overview"|"detailed"
    2. consolidatedFrequency ..?
    3. consolidatedSendIfEmpty, set to false if not boolean and set to true
  2. create notificationGroup by send message to Service - Graph Handler InCreateNodeWithVersionedData
    • nodeStructure
      • nodeLabel: "notificationGroup"
      • nodeProperties: {notificationGroupId, additionalData}
    • versionedDatas
      • nodeLabel: "notificationGroupSetting"
      • nodeProperties: {notificationGroupName, consolidated, consolidatedType, consolidatedFrequency, consolidatedSendIfEmpty}
  3. send message to OutNotificationGroupCreated topic, can include full notificationGroup object

CreateNotifications

/**
 * Creates muti notifications
 * @param {string} userId
 * @param {string} notificationGroupId
 * @param {Object[]} notifications
 * @param {string} [notifications.notificationName]
 * @param {Object[]} notifications.triggers
 * @param {string} notifications.triggers.propertyName
 * @param {string} notifications.triggers.valueType - property|attribute
 * @param {string} [notifications.triggers.value] - either value or values will be set
 * @param {string[]} [notifications.triggers.values] - either value or values will be set
 *
 */

HdrSqs

Subscribes to InCreateNotifications topic

Validator:

  • notificationGroupId cannot be empty string
  • notifications cannot be an empty array? Can limit number of notifications in array?

logic

  1. get notificationGroup node by invoke graphSharedLib.getNode
    • nodeStructure
      • nodeLabel: "notificationGroup"
      • nodeProperties: {notificationId}
    • versionedDataLabels: ["notificationGroupSetting"]
  2. if not found notificationGroup node
    1. send message to OutCreateNotificationsFailed topic
      • notificationGroupId
      • notifications
      • errorsFound: "NotificationGroupNotFound"
    2. return
  3. for each notifications:
    1. create an object that contains
      • notificationName
      • triggers
    2. hash this object into variable named notificationId
    3. create child notification node and relationship
      1. send message to Service - Graph Handler InCreateChildNodeAndRelationship
        • parentNodeStructure
          • nodeLabel: "notificationGroup"
          • nodeProperties: {notificationGroupId}
        • createChildNodeStructure
          • nodeStructure
            • nodeLabel: "notification"
            • nodePropertis: {notificationId}
        • createRelationshipStructure
          • relationshipStructure
            • relationshipType: "has_notification"
            • relationshipDirection: "outgoing"
    4. for each notifications.triggers:
      1. create notificationTriggerId by {notificationId} + "_" + {randon UUID}
      2. create child notificationTrigger node and relationship
        1. send message to Service - Graph Handler InCreateChildNodeAndRelationship
          • parentNodeStructure
            • nodeLabel: "notification"
            • nodeProperties: {notificationId}
          • createChildNodeStructure
            • nodeStructure
              • nodeLabel: "notificationTrigger"
              • nodePropertis: {notificationTriggerId}
          • createRelationshipStructure
            • relationshipStructure
              • relationshipType: "has_notificationTrigger"
              • relationshipDirection: "outgoing"
    5. create an object that contains 'notificationId' and 'triggers' for invoke sharedCreateTriggerGroup.sharedCreateTriggerGroup
    6. invoke sharedCreateTriggerGroup.sharedCreateTriggerGroup
      1. send message to Service - Activity Switchboard InCreateTriggerGroup topic
        • uniqueId: {notificationId}
        • additionalData: {}
        • triggers: {notification.triggers}
    7. send message to OutNotificationCreated topic, can include full notification object

NotificationGroup/List

/**
 * Lists all notification groups for one primary key (notificationGroupId/uniqueId)
 * @param {string} receiverTag
 * @param {string} groupingId
 * @param {string} [uniqueIdPrefix=null]
 *
 * @returns {Object[]} array of objects, each object is one notification group
 */

HdrApi

Validator:

  • receiverTag
  • groupingId
  • uniqueIdPrefix with default value

handler logic

(standard)

logic

Query NotificationGroups table for all records that match notificationGroupId and if uniqueIdPrefix not null uniqueId starts_with uniqueIdPrefix, and return.

Functions

sendNotificationToReceiver

/**
 * Send message to receiver endpoint
 * @param {Object} notification - object from the Notifications table
 * @param {Object} notificationGroup - object from the NotificationGroups table
 * @param {string} notificationBody - string sent to receiver
 */

logic

  1. get notificationGroup node by getNodeAndRelationships
    • nodeLabel: "notificationGroup"
    • nodeProperties.notificationGroupId
    • relationshipType: "has_notificationGroup"
    • relationshipDirection: "incoming"
    return; notificationGroup and email node (in future; will have another service eg. SMS, site notification)
  2. send message to OutNewNotification topic, adding below properties:
    • uniqueId: {emailId}
    • notificationBody
    • additionalData
    • (? filter policy limit) receiverTag gets added to message attributes so can be filtered for by receiving service
Service - User Contact Manager and Service - Contact Method Email will change logic or structure

disableNotificationGroup

/**
 * @param {Object} notificationGroup
 *
 */

logic

  1. for each notificationId
    1. change relationshipType to "disabled_notification" by send message to Service - Graph Handler InChangeRelationshipType
    2. send message to Service - Activity Switchboard InRemoveTriggerGroup
      • notificationId
    3. send message to OutNotificationDisabled topic
      • notificationId
  2. change relationshipType to "disabled_notificationGroup" by send message to Service - Graph Handler InChangeRelationshipType
  3. send message to OutNotificationGroupDisabled topic
    • notificationGroupId

enableNotificationGroup

/**
 * @param {Object} notificationGroup
 *
 */

logic

  1. for each notificationId
    1. get notification node by GraphHandler getNodeAndRelationships
      • nodeLabel: "notification"
      • nodeProperties.notificationId
      • relationshipType: "has_notificationTrigger"
      • relationshipDirection: "outgoing"
    2. change relationshipType to "has_notification" by send message to Service - Graph Handler InChangeRelationshipType
    3. invoke sharedCreateTriggerGroup.sharedCreateTriggerGroup
      1. send message to Service - Activity Switchboard InCreateTriggerGroup
        • uniqueId: notificationId
        • additionalData: {}
        • requestedTriggers: [{notificationTriggers}]
    4. send message to OutNotificationEnabled topic
      • notificationId
  2. change relationshipType to "has_notificationGroup" by send message to Service - Graph Handler InChangeRelationshipType
  3. send message to OutNotificationGroupEnabled topic
    • notificationGroupId

Sample notification object sent to receiver service

{
	notificationBody: [
		{
			messageAttributes: {
				// xxx: yyy
			},
			message: {
				// full body of message received
			}
		},
	],
	additionalData: {
		userId: ...
	},
	uniqueId: {emailId}
}