Service - Notification Manager: Difference between revisions

From Izara Wiki
Jump to navigation Jump to search
No edit summary
No edit summary
 
(10 intermediate revisions by 2 users not shown)
Line 1: Line 1:
[[Service - Notification Manager]]
= Overview =


= Lambda Functions =
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.


== RcvActivityMsg ==
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.


<syntaxhighlight lang="JavaScript">
= Repository =
/**
* 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 ===
https://bitbucket.org/izara-core-shared/izara-core-shared-notification-manager


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


=== logic ===
; Additional Information: [[Per Service Schemas]]
# 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]]  


== objType ==


== DisableNotificationGroups ==
=== notificationGroup ===


<syntaxhighlight lang="JavaScript">
* Groups many triggerGroups together
/**
* Disables a set of matching notification groups
* @param {string} notificationGroupId - null if not supplied
*
*/
</syntaxhighlight>
 
=== HdrSqs ===
 
Subscribes to InDisableNotificationGroups topic
 
=== logic ===
 
# 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]]
 
== UpdateNotificationGroup ==


<syntaxhighlight lang="JavaScript">
<syntaxhighlight lang="JavaScript">
/**
{
* Update a notification group
  objectType: "notificationGroup",
* @param {string} notificationGroupId
  canDelete: false,
* @param {string} notificationGroupName
  storageResources: {
* @param {boolean} consolidated
    myGraph: {
* @param {string} consolidatedType
      storageType: "graph",
* @param {..?} consolidatedFrequency
      graphServerTag: "GraphHandler"
* @param {boolean} consolidatedSendIfEmpty
    },
* @param {boolean} enabled
    dynamoDB: {
*
      storageType: "dynamoDB",
*/
      tableName: "NotificationGroupProcessing"
    }
  },
  addOnDataStructure: [
    {
      type: "versionedData",
      versionedDataLabel: "notificationGroupSettings",
      storageResourceTag: "myGraph",
      fieldNames: {
    "notificationGroupName": {
      type: "string",
      requiredOnCreate: true,
      canUpdate: true,
      validation: {
        pattern: pattern
      }
    },
    "consolidatedType": {
      type: "string",
      optionalOnCreate: true,
      requiredOnCreate: false,
      canUpdate: true,
      validation: {
        pattern: pattern
      }
    },
    "consolidatedFrequency": {
      type: "number",
      optionalOnCreate: true,
      requiredOnCreate: false,
      canUpdate: true,
      validation: {
        pattern: pattern
      }
    },
    "consolidatedSendIfEmpty": {
      type: "boolean",
      optionalOnCreate: true,
      requiredOnCreate: false,
      canUpdate: true,
      validation: {
        pattern: pattern
      }
    },
    "consolidatedMessageCount": {
      type: "number",
      optionalOnCreate: true,
      requiredOnCreate: false,
      canUpdate: true,
      validation: {
        pattern: pattern
      }
    },
    "consolidatedConfigs": {
      type: "array",
      optionalOnCreate: true,
      requiredOnCreate: false,
      canUpdate: true,
      validation: {
        pattern: pattern
      }
    }
      }
    }
  ],
  fieldNames: {
    notificationGroupId: {
      type: "string",
      randomOnCreate: true,
      canUpdate: false,
      validation: {
    pattern: pattern
      },
      storageResourceTags: ['myGraph', "dynamoDB"]
    },
    consolidatedLastTimeSent: {
      type: "number",
      optionalOnCreate: true,
      canUpdate: true,
      validation: {
    pattern: pattern
      },
      storageResourceTags: ["dynamoDB"]
    },
  },
  identifiers: [
    {
      type: "identifier",
      fieldName: "notificationGroupId"
    }
  ]
}
</syntaxhighlight>
</syntaxhighlight>


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


Subscribes to InUpdateNotificationGroup topic
; notificationGroupId (identifier)
: comes from: randomOnCreate
; consolidatedLastTimeSent
: start time for recurring or last time for send consolidated message
; notificationGroupName
: string name set by user
; consolidatedType
: none | recurring | messageCount
: ''none'' is not consolidated, process immediately
: ''recurring'' process at a specific frequency
: ''messageCount'' process when a specific number of messages have been received
; consolidatedFrequency
: for consolidatedType = recurring, number of milliseconds between each processing
; consolidatedSendIfEmpty
: setting for if have no consolidated message
: true = send message out
: false = not send message out
; consolidatedMessageCount
: send a consolidated message when the number of messages reaches
; consolidatedConfigs
: pattern for message to send data in consolidated message


=== logic ===
=== consolidated ===
 
 
# get notificationGroup node by GraphHandler getNodeAndRelationships
<syntaxhighlight lang="JavaScript">
#* nodeLabel: "notificationGroup"
{
#* nodeProperties.notificationGroupId
  objectType: "consolidated",
#* relationshipType: "has_notification"
  canDelete: false,
#* relationshipDirection: "outgoing"
  storageResources: {
# if not found notificationGroup or notification node
    dynamoDB: {
#* throw new NoRetryError
      storageType: "dynamoDB",
# else
      tableName: "PendingConsolidation"
#* get notificationId for each child notification node
    }
# update notificationGroup node by send message to [[Service - Graph Handler]] InCreateVersionedData
  },
#* nodeStructure
  fieldNames: {
#** nodeLabel: "notificationGroup"
    notificationGroupId: {
#** nodeProperties.notificationGroupId
      type: "string",
#* versionDataStructure
      canUpdate: false,
#** nodeLabel: "notificationGroupSetting"
      storageResourceTags: ['dynamoDB'],
#** nodeProperties: {notificationGroupName, consolidated, consolidatedType, consolidatedFrequency, consolidatedSendIfEmpty}
      fromObjType: {
# if enabled = false
    serviceTag: "NotificationManager",
## invoke [[#disableNotificationGroup]]
    objectType: "notificationGroup"
# if enabled = true
      }
## invoke [[#enableNotificationGroup]]
    },
 
    checkedTriggerTime: {
== DisableNotifications ==
      type: "string",
 
      requiredOnCreate: true,
<syntaxhighlight lang="JavaScript">
      canUpdate: false,
/**
      validation: {
* Disables a set of matching notification groups
    pattern: pattern
* @param {string[]} notificationIds
      },
*
      storageResourceTags: ['dynamoDB']
*/
    },
    activityMsg: {
      type: "object",
      requiredOnCreate: true,
      canUpdate: false,
      validation: {
    pattern: pattern
      },
      storageResourceTags: ['dynamoDB']
    },
    flowTag: {
      type: "string",
      requiredOnCreate: true,
      canUpdate: false,
      validation: {
    pattern: pattern
      },
      storageResourceTags: ['dynamoDB']
    },
    flowStep: {
      type: "string",
      requiredOnCreate: true,
      canUpdate: false,
      validation: {
    pattern: pattern
      },
      storageResourceTags: ['dynamoDB']
    }
  },
  identifiers: [
    {
      type: "partitionKey",
      fieldName: "notificationGroupId"
    },
    {
      type: "sortKey",
      fieldName: "checkedTriggerTime"
    }
  ]
}
</syntaxhighlight>
</syntaxhighlight>


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


Subscribes to InDisableNotifications topic
; notificationGroupId (partition key)
: comes from: randomOnCreate
; checkedTriggerTime (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
: the message delivered from Activity Switchboard
; flowTag
: defines the consolidated configuration for the notification group
; flowType
: defines the consolidated configuration for the notification group


=== logic ===
== Object Relationships ==
 
# 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
 
== CreateNotificationGroup ==


=== ownsNotificationGroup ===
<syntaxhighlight lang="JavaScript">
<syntaxhighlight lang="JavaScript">
/**
{
* Creates one notification group
  "ownsNotificationGroup": {
* @param {string} notificationGroupId
    fieldNames: {
* @param {string} notificationGroupName
      "originTimestamp": {
* @param {boolean} consolidated
    type: "number",
* @param {string} consolidatedType
    requiredOnCreate: true,  // default = false
* @param {..?} consolidatedFrequency
    canUpdate: true,          // default = true
* @param {boolean} consolidatedSendIfEmpty
    validation: {}           // ajv syntax
* @param {Object} additionalData
      }
*
    },
*/
    storageResources: {
      myGraph: {
    storageType: "graph",
    graphServerTag: "GraphHandler"
      }
    },
    links: [
      {
    storageResourceTags: ["myGraph"],
    from: {
      objType: {
        serviceTag: "UserAccount",
        objectType: "user"
      },
      linkType: "one",
    },
    to: {
      objType: {
        serviceTag: "NotificationManager",
        objectType: "notificationGroup"
      },
      requiredOnCreate: true,
      linkType: "many",
      handler: true
    }
      }
    ]
  }
}
</syntaxhighlight>
</syntaxhighlight>
: links the user to their created notification group


=== HdrSqs ===
=== hasTriggerGroup ===
 
Subscribes to InCreateNotificationGroup topic
 
Validator:
* notificationGroupId cannot be empty string
   
=== logic ===
 
# 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
 
== CreateNotifications ==
 
<syntaxhighlight lang="JavaScript">
<syntaxhighlight lang="JavaScript">
/**
{
* Creates muti notifications
  "hasTriggerGroup": {
* @param {string} userId
    canChangeToRelTypes: [
* @param {string} notificationGroupId
      {
* @param {Object[]} notifications
    serviceTag: "NotificationManager",
* @param {string} [notifications.notificationName]
    relationshipTag: "disabledTriggerGroup"
* @param {Object[]} notifications.triggers
      }
* @param {string} notifications.triggers.propertyName
    ],
* @param {string} notifications.triggers.valueType - property|attribute
    fieldNames: {
* @param {string} [notifications.triggers.value] - either value or values will be set
      "originTimestamp": {
* @param {string[]} [notifications.triggers.values] - either value or values will be set
    type: "number",            // "string" | "number" ...
*
    requiredOnCreate: true,  // default = false
*/
    canUpdate: true,          // default = true
    validation: {}            // ajv syntax
      }
    },
    storageResources: {
      myGraph: {
    storageType: "graph",
    graphServerTag: "GraphHandler"
      }
    },
    links: [
      {
    storageResourceTags: ["myGraph"],
    from: {
      objType: {
        serviceTag: "NotificationManager",
        objectType: "notificationGroup"
      },
      linkType: "many",
      handler: true
    },
    to: {
      objType: {
        serviceTag: "ActivitySwitchboard",
        objectType: "triggerGroup"
      },
      linkType: "many"
    }
      }
    ]
  }
}
</syntaxhighlight>
</syntaxhighlight>


=== HdrSqs ===
=== disabledTriggerGroup ===
 
Subscribes to InCreateNotifications topic
 
Validator:
* notificationGroupId cannot be empty string
* notifications cannot be an empty array? Can limit number of notifications in array?
   
=== logic ===
 
# 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 ==
 
<syntaxhighlight lang="JavaScript">
<syntaxhighlight lang="JavaScript">
/**
{
* Lists all notification groups for one primary key (notificationGroupId/uniqueId)
  "disabledTriggerGroup": {
* @param {string} receiverTag
    canChangeToRelTypes: [
* @param {string} groupingId
      {
* @param {string} [uniqueIdPrefix=null]
    serviceTag: "NotificationManager",
*
    relationshipTag: "hasTriggerGroup"
* @returns {Object[]} array of objects, each object is one notification group
      }
*/
    ],
    fieldNames: {
      "originTimestamp": {
    type: "number",            // "string" | "number" ...
    requiredOnCreate: true,  // default = false
    canUpdate: true,          // default = true
    validation: {}           // ajv syntax
      }
    },
    storageResources: {
      myGraph: {
    storageType: "graph",
    graphServerTag: "GraphHandler"
      }
    },
    links: [
      {
    storageResourceTags: ["myGraph"],
    from: {
      objType: {
        serviceTag: "NotificationManager",
        objectType: "notificationGroup"
      },
      linkType: "many",
      handler: true
    },
    to: {
      objType: {
        serviceTag: "ActivitySwitchboard",
        objectType: "triggerGroup"
      },
      linkType: "many"
    }
      }
    ]
  }
}
</syntaxhighlight>
</syntaxhighlight>


=== HdrApi ===
= value or values array =
 
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.
* 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.


= Functions =
* 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.


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


<syntaxhighlight lang="JavaScript">
= serviceName and topicName triggers =
/**
* 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
*/
</syntaxhighlight>


=== logic ===
* Notifications do not have to set their serviceName and/or topicName, if not set then any message that matches the properties will pass
* 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


# get notificationGroup node by getNodeAndRelationships
= Consolidated notifications =
#* 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


;  [[Service - User Contact Manager]] and [[Service - Contact Method Email]] will change logic or structure
== How to trigger processing for time based consolidations ==


== disableNotificationGroup ==
* ....
* 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)


<syntaxhighlight lang="JavaScript">
= Formating the notification body =
/**
* @param {Object} notificationGroup
*
*/
</syntaxhighlight>


=== logic ===
* Initially the format will be hardwired and simple, but in the future we could create templates for formating the notification body
* The notificationBody is currently sent to receiver as a JSON stringified object containing all activityMsgs


# for each notificationId
= Ideas =
## 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


== enableNotificationGroup ==
* ''overview'' notifications currently count per notification, but could be extended to do aggregates on a per notification, per field level
* 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


<syntaxhighlight lang="JavaScript">
= Working documents =
/**
* @param {Object} notificationGroup
*
*/
</syntaxhighlight>


=== logic ===
[[:Category:Working documents - Notification Manager|Working documents - Notification Manager]]
 
# for each notificationId
## 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
 
= Sample notification object sent to receiver service =
 
<syntaxhighlight lang="JavaScript">
{
notificationBody: [
{
messageAttributes: {
// xxx: yyy
},
message: {
// full body of message received
}
},
],
additionalData: {
userId: ...
},
uniqueId: {emailId}
}
</syntaxhighlight>


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

Latest revision as of 05:59, 11 September 2025

Overview

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 Activity Switchboard service.

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.

Repository

https://bitbucket.org/izara-core-shared/izara-core-shared-notification-manager

Object Schemas

Additional Information
Per Service Schemas

objType

notificationGroup

  • Groups many triggerGroups together
{
  objectType: "notificationGroup",
  canDelete: false,
  storageResources: {
    myGraph: {
      storageType: "graph",
      graphServerTag: "GraphHandler"
    },
    dynamoDB: {
      storageType: "dynamoDB",
      tableName: "NotificationGroupProcessing"
    }
  },
  addOnDataStructure: [
    {
      type: "versionedData",
      versionedDataLabel: "notificationGroupSettings",
      storageResourceTag: "myGraph",
      fieldNames: {
	    "notificationGroupName": {
	      type: "string",
	      requiredOnCreate: true,
	      canUpdate: true,
	      validation: {
	        pattern: pattern
	      }
	    },
	    "consolidatedType": {
	      type: "string",
	      optionalOnCreate: true,
	      requiredOnCreate: false,
	      canUpdate: true,
	      validation: {
	        pattern: pattern
	      }
	    },
	    "consolidatedFrequency": {
	      type: "number",
	      optionalOnCreate: true,
	      requiredOnCreate: false,
	      canUpdate: true,
	      validation: {
	        pattern: pattern
	      }
	    },
	    "consolidatedSendIfEmpty": {
	      type: "boolean",
	      optionalOnCreate: true,
	      requiredOnCreate: false,
	      canUpdate: true,
	      validation: {
	        pattern: pattern
	      }
	    },
	    "consolidatedMessageCount": {
	      type: "number",
	      optionalOnCreate: true,
	      requiredOnCreate: false,
	      canUpdate: true,
	      validation: {
	        pattern: pattern
	      }
    	},
	    "consolidatedConfigs": {
	      type: "array",
    	  optionalOnCreate: true,
    	  requiredOnCreate: false,
    	  canUpdate: true,
	      validation: {
	        pattern: pattern
	      }
    	}
      }
    }
  ],
  fieldNames: {
    notificationGroupId: {
      type: "string",
      randomOnCreate: true,
      canUpdate: false,
      validation: {
	    pattern: pattern
      },
      storageResourceTags: ['myGraph', "dynamoDB"]
    },
    consolidatedLastTimeSent: {
      type: "number",
      optionalOnCreate: true,
      canUpdate: true,
      validation: {
	    pattern: pattern
      },
      storageResourceTags: ["dynamoDB"]
    },
  },	
  identifiers: [
    {
      type: "identifier",
      fieldName: "notificationGroupId"
    }
  ]
}

fieldNames

notificationGroupId (identifier)
comes from: randomOnCreate
consolidatedLastTimeSent
start time for recurring or last time for send consolidated message
notificationGroupName
string name set by user
consolidatedType
none | recurring | messageCount
none is not consolidated, process immediately
recurring process at a specific frequency
messageCount process when a specific number of messages have been received
consolidatedFrequency
for consolidatedType = recurring, number of milliseconds between each processing
consolidatedSendIfEmpty
setting for if have no consolidated message
true = send message out
false = not send message out
consolidatedMessageCount
send a consolidated message when the number of messages reaches
consolidatedConfigs
pattern for message to send data in consolidated message

consolidated

					
{
  objectType: "consolidated",
  canDelete: false,
  storageResources: {
    dynamoDB: {
      storageType: "dynamoDB",
      tableName: "PendingConsolidation"
    }
  },
  fieldNames: {
    notificationGroupId: {
      type: "string",
      canUpdate: false,
      storageResourceTags: ['dynamoDB'],
      fromObjType: {
	    serviceTag: "NotificationManager",
	    objectType: "notificationGroup"
      }
    },
    checkedTriggerTime: {
      type: "string",
      requiredOnCreate: true,
      canUpdate: false,
      validation: {
	    pattern: pattern
      },
      storageResourceTags: ['dynamoDB']
    },
    activityMsg: {
      type: "object",
      requiredOnCreate: true,
      canUpdate: false,
      validation: {
	    pattern: pattern
      },
      storageResourceTags: ['dynamoDB']
    },
    flowTag: {
      type: "string",
      requiredOnCreate: true,
      canUpdate: false,
      validation: {
	    pattern: pattern
      },
      storageResourceTags: ['dynamoDB']
    },
    flowStep: {
      type: "string",
      requiredOnCreate: true,
      canUpdate: false,
      validation: {
	    pattern: pattern
      },
      storageResourceTags: ['dynamoDB']
    }
  },
  identifiers: [
    {
      type: "partitionKey",
      fieldName: "notificationGroupId"
    },
    {
      type: "sortKey",
      fieldName: "checkedTriggerTime"
    }
  ]
}

fieldNames

notificationGroupId (partition key)
comes from: randomOnCreate
checkedTriggerTime (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
the message delivered from Activity Switchboard
flowTag
defines the consolidated configuration for the notification group
flowType
defines the consolidated configuration for the notification group

Object Relationships

ownsNotificationGroup

{
  "ownsNotificationGroup": {
     fieldNames: {
       "originTimestamp": {
	     type: "number",
	     requiredOnCreate: true,  	// default = false
	    canUpdate: true,          	// default = true
	    validation: {}            	// ajv syntax
      }
    },
    storageResources: {
      myGraph: {
	    storageType: "graph",
	    graphServerTag: "GraphHandler"
      }
    },
    links: [
      {
	    storageResourceTags: ["myGraph"],
	    from: {
	      objType: {
	        serviceTag: "UserAccount",
	        objectType: "user"
	      },
	      linkType: "one",
	    },
	    to: {
	      objType: {
	        serviceTag: "NotificationManager",
	        objectType: "notificationGroup"
	      },
	      requiredOnCreate: true,
	      linkType: "many",
	      handler: true
	    }
      }
    ]
  }
}
links the user to their created notification group

hasTriggerGroup

{
  "hasTriggerGroup": {
    canChangeToRelTypes: [
      {
	    serviceTag: "NotificationManager",
	    relationshipTag: "disabledTriggerGroup"
      }
    ],
    fieldNames: {
      "originTimestamp": {
	    type: "number",            	// "string" | "number" ...
	    requiredOnCreate: true,  	// default = false
	    canUpdate: true,          	// default = true
	    validation: {}            	// ajv syntax
      }
    },
    storageResources: {
      myGraph: {
	    storageType: "graph",
	    graphServerTag: "GraphHandler"
      }
    },
    links: [
      {
	    storageResourceTags: ["myGraph"],
	    from: {
	      objType: {
	        serviceTag: "NotificationManager",
	        objectType: "notificationGroup"
    	  },
	      linkType: "many",
	      handler: true
    	},
	    to: {
	      objType: {
	        serviceTag: "ActivitySwitchboard",
	        objectType: "triggerGroup"
	      },
	      linkType: "many"
    	}
      }
    ]
  }
}

disabledTriggerGroup

{
  "disabledTriggerGroup": {
    canChangeToRelTypes: [
      {
	    serviceTag: "NotificationManager",
	    relationshipTag: "hasTriggerGroup"
      }
    ],
    fieldNames: {
      "originTimestamp": {
	    type: "number",            	// "string" | "number" ...
	    requiredOnCreate: true,  	// default = false
	    canUpdate: true,          	// default = true
	    validation: {}            	// ajv syntax
      }
    },
    storageResources: {
      myGraph: {
	    storageType: "graph",
	    graphServerTag: "GraphHandler"
      }
    },
    links: [
      {
	    storageResourceTags: ["myGraph"],
	    from: {
	      objType: {
	        serviceTag: "NotificationManager",
	        objectType: "notificationGroup"
	      },
	      linkType: "many",
	      handler: true
	    },
	    to: {
	      objType: {
	        serviceTag: "ActivitySwitchboard",
	        objectType: "triggerGroup"
	      },
	      linkType: "many"
    	}
      }
    ]
  }
}

value or values array

  • 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.
  • 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.
  • "serviceName" and "topicName" valueTypes do not have propertyName

serviceName and topicName triggers

  • Notifications do not have to set their serviceName and/or topicName, if not set then any message that matches the properties will pass
  • 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

How to trigger processing for time based consolidations

  • ....
  • 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)

Formating the notification body

  • Initially the format will be hardwired and simple, but in the future we could create templates for formating the notification body
  • The notificationBody is currently sent to receiver as a JSON stringified object containing all activityMsgs

Ideas

  • overview notifications currently count per notification, but could be extended to do aggregates on a per notification, per field level
  • 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

Working documents

Working documents - Notification Manager