Service - Activity Switchboard: Difference between revisions

From Izara Wiki
Jump to navigation Jump to search
No edit summary
 
(46 intermediate revisions by 2 users not shown)
Line 1: Line 1:
= Overview =
= Overview =


Receives every message sent within the entire project's serverless flow, allows services to register triggers that check if values in each message match the triggers filters, when matches are found the specified endpoint is notified.
Receives most messages sent within the entire project's serverless flow, allows services to register a set of triggers that are checked when each message is received, if all triggers pass a message is sent out for subscribed services.


= Repository =
= Repository =


https://bitbucket.org/stb_working/activity-switchboard/src/master/
https://bitbucket.org/izara-core-shared/izara-core-shared-activity-switchboard


= DynamoDB tables =
= Object Schemas =
; Additional Information: [[Per Service Schemas]]


== [[Standard Config Table Per Service]] ==
== objType ==


=== Configuration tags ===
=== triggerGroup ===
 
* Groups many triggers, all triggers for a trigger group must pass for the trigger group to pass
* if multiple values are sent for a trigger we consider this an "or" check, any of the values can match. We do this by saving each value as a separate trigger, then when checking a trigger groups child triggers we have a counter that enables a check if any one of the values matches


; configKey = ''endpoint'', configTag = {tag for the endpoint config}
: configValue example
<syntaxhighlight lang="JavaScript">
<syntaxhighlight lang="JavaScript">
{
{
"endpoint": {eg: Lambda function name}
  objectType: "triggerGroup",
"service_type": {eg: "Lambda"} //service type tag, at the moment only "Lambda"
  canDelete: false,
  storageResources: {
    myGraph: {
      storageType: "graph",
      graphServerTag: "GraphHandler"
    }
  },
  fieldNames: {
    triggerGroupId: {
      type: "string",
      randomOnCreate: true,
      canUpdate: false,
      validation: {
    pattern: pattern
      },
      storageResourceTags: ['myGraph']
    }
  },
  identifiers: [
    {
      type: "identifier",
      fieldName: "triggerGroupId"
    }
  ]
}
}
</syntaxhighlight>
</syntaxhighlight>
; configKey = ''msgOutConfig'', configTag = {service tag}_{message_tag}
: propogated from [[Service - Message Config Manager|Message Config Manager]] service
: see [[Standard MsgOut Config]]


== TriggerGroup ==
=== trigger ===


* Groups many triggers, all triggers for a trigger group must pass for the trigger group to notify the endpoint
<syntaxhighlight lang="JavaScript">
{
  objectType: "trigger",
  canDelete: false,
  storageResources: {
    dynamoDB: {
      storageType: "dynamoDB",
      tableName: "Triggers"
    }
  },
  fieldNames: {
    triggerId: {
      type: "string",
      randomOnCreate: false,
      optionalOnCreate: true,
      canUpdate: false,
      validation: {
    pattern: pattern
      },
      storageResourceTags: ['dynamoDB']
    },
    valueType: {
      type: "string",
      requiredOnCreate: true,
      canUpdate: false,
      validation: {
    pattern: pattern
      },
      storageResourceTags: ['dynamoDB']
    },
    propertyValueString: {
      type: "string",
      optionalOnCreate: true,
      canUpdate: false,
      validation: {
    pattern: pattern
      },
      storageResourceTags: ['dynamoDB']
    },
    propertyValueNumber: {
      type: "number",
      optionalOnCreate: true,
      canUpdate: false,
      validation: {
    pattern: pattern
      },
      storageResourceTags: ['dynamoDB']
    },
    propertyName: {
      type: "string",
      optionalOnCreate: true,
      canUpdate: false,
      validation: {},
      storageResourceTags: ['dynamoDB']
    }
  },
  identifiers: [
    {
      type: "identifier",
      fieldName: "triggerId"
    }
  ]
}
</syntaxhighlight>


=== Fields ===
==== fieldNames ====


; triggerGroupId
; triggerId
: (partition key)
: (identifier)
: comes from: {endpoint}_{unique id given be creating service}
: comes from: {hash of valueType(property|attribute).propertyName}_{hash of propertyValue (string or number)}
: or could be a random uuid
: or: serviceName_{hash of serviceName value}
; triggerIds
: or: topicName_{hash of topicName value}
: array (DynamoDB list) of triggerIds
: attributes is for message attributes
; endpoint
: property is from the data sent inside the message body
: matches an endpoint record in Config table
: hash property name and value so no ambiguity about underscores/spaces etc..
; additionalData
; valueType
: set by the service that creates this trigger group, gets added to the message sent to the endpoint
: property|attribute|serviceName|topicName
: often will include id needed by the receiving endpoing to match the trigger to its entity, eg to a notifcation record in [[Service - Notification Manager|Notification Manager]] service
; propertyName
: "serviceName" and "topicName" valueTypes do not have propertyName
: eg. property.propA.propB.propC (not validate nested object)
: eg. attribute.serviceName
; propertyValueString
: for value of propertyValue is string
; propertyValueNumber
: for value of propertyValue is number


== Triggers ==


* no sort key
== Object Relationships ==


=== Fields ===
=== hasTrigger ===
<syntaxhighlight lang="JavaScript">
{
  "hasTrigger": {
    canChangeToRelTypes: [
      {
    serviceTag: "ActivitySwitchboard",
    relationshipTag: "disabledTrigger"
      }
    ],
    fieldNames: {
      "originTimestamp": {
    type: "number", 
    requiredOnCreate: true,  // default = false
      canUpdate: true,          // default = true
    validation: {}            // ajv syntax
      }
    },
    storageResources: {
      dynamo: {
    storageType: "dynamoDB"
      }
    },
    links: [
      {
    storageResourceTags: ["dynamo"],
    from: {
      objType: {
        serviceTag: "ActivitySwitchboard",
        objectType: "triggerGroup"
      },
      linkType: "many",
      handler: true
    },
    to: {
      objType: {
        serviceTag: "ActivitySwitchboard",
        objectType: "trigger"
      },
      linkType: "many"
    }
      }
    ]
  }
}
</syntaxhighlight>


; triggerId
=== disabledTrigger ===
: (partition key)
<syntaxhighlight lang="JavaScript">
: comes from: {meta|property}_{hash of property name}_{hash of value}
{
: meta is for metadata fields such as the messageTag, message attributes
  "disabledTrigger": {
: property is from the data sent inside the message body
    canChangeToRelTypes: [
; triggerGroupId
      {
    serviceTag: "ActivitySwitchboard",
    relationshipTag: "hasTrigger"
      }
    ],
    fieldNames: {
      "originTimestamp": {
    type: "number",
    requiredOnCreate: true,  // default = false
    canUpdate: true,          // default = true
    validation: {}           // ajv syntax
      }
    },
    storageResources: {
      dynamo: {
    storageType: "dynamoDB"
      }
    },
    links: [
      {
    storageResourceTags: ["dynamo"],
    from: {
      objType: {
        serviceTag: "ActivitySwitchboard",
        objectType: "triggerGroup"
      },
      linkType: "many",
      handler: true
    },
    to: {
      objType: {
        serviceTag: "ActivitySwitchboard",
        objectType: "trigger"
      },
      linkType: "many"
    }
      }
    ]
  }
}
</syntaxhighlight>


= Notes =
= Efficiency =


* Service will result in a large number of queries to Triggers table, every message will need to make a query for every field set as an activityTrigger
* Service will result in a large number of queries to Triggers table, every message will need to make a query for every field set as an activityTrigger
* Try to make this as efficient as possible
* Try to make this as efficient as possible
* To reduce number of queries made to Tiggers table we use the MsgOut config for any message received, which sets which properties can be used as triggers
* To reduce number of queries made to Tiggers table we use the msgCfg for any message received
** MsgCfg sets which properties can be used as triggers, others are not queried
 
= Handling msgCfgs =
 
* msgCfgs get updated from [[Service - Message Config Manager|Message Config Manager]] service, we do this by subscribing to Message Config Manager's OutMsgCfgUpdate topic
* Only want to process messages from certain In/Out topics, it will be most topics but does not have to be all
* Set which topics to subscribe to by setting activitySwitchboard = true in msgCfg


= Ideas =
= Ideas =
Line 66: Line 249:
* If more efficient can use cache for regular DynamoDB queries
* If more efficient can use cache for regular DynamoDB queries
* Could add other matching methods such as greater than or less than, in DynamoDB this might be more efficient to add as separate table with its own structure, eg: partition key is the field reference, sort key is the amount, then use sort key to return matching triggers. Danger of bad partitioning in DynamoDB (or hitting limits) due to large numbers of sort keys associated with one partition key
* Could add other matching methods such as greater than or less than, in DynamoDB this might be more efficient to add as separate table with its own structure, eg: partition key is the field reference, sort key is the amount, then use sort key to return matching triggers. Danger of bad partitioning in DynamoDB (or hitting limits) due to large numbers of sort keys associated with one partition key
* could consider how to incorporate includes or checking within a set of options set in the trigger, again might need specialized table structure
* Might be able to optimise by using SNS > stream instead of SNS > SQS for all incomming messages
* Might be able to optimise by using SNS > stream instead of SNS > SQS for all incomming messages
* One system level endpoint could be specialized logs, eg service per user/per product/etc logs
* One system level receiving service could be specialized logs, eg logs per service per user/per product/etc
* Topic name is not fixed part of the TriggersGroup structure, allow for trigger groups that are not connected to specific topics, but can pass messages from any topic that matches other triggers


= Working documents =
= Working documents =

Latest revision as of 04:19, 11 September 2025

Overview

Receives most messages sent within the entire project's serverless flow, allows services to register a set of triggers that are checked when each message is received, if all triggers pass a message is sent out for subscribed services.

Repository

https://bitbucket.org/izara-core-shared/izara-core-shared-activity-switchboard

Object Schemas

Additional Information
Per Service Schemas

objType

triggerGroup

  • Groups many triggers, all triggers for a trigger group must pass for the trigger group to pass
  • if multiple values are sent for a trigger we consider this an "or" check, any of the values can match. We do this by saving each value as a separate trigger, then when checking a trigger groups child triggers we have a counter that enables a check if any one of the values matches
{
  objectType: "triggerGroup",
  canDelete: false,
  storageResources: {
    myGraph: {
      storageType: "graph",
      graphServerTag: "GraphHandler"
    }
  },
  fieldNames: {
    triggerGroupId: {
      type: "string",
      randomOnCreate: true,
      canUpdate: false,
      validation: {
	    pattern: pattern
      },
      storageResourceTags: ['myGraph']
    }
  },
  identifiers: [
    {
      type: "identifier",
      fieldName: "triggerGroupId"
    }
  ]
}

trigger

{
  objectType: "trigger",
  canDelete: false,
  storageResources: {
    dynamoDB: {
      storageType: "dynamoDB",
      tableName: "Triggers"
    }
  },
  fieldNames: {
    triggerId: {
      type: "string",
      randomOnCreate: false,
      optionalOnCreate: true,
      canUpdate: false,
      validation: {
	    pattern: pattern
      },
      storageResourceTags: ['dynamoDB']
    },
    valueType: {
      type: "string",
      requiredOnCreate: true,
      canUpdate: false,
      validation: {
	    pattern: pattern
      },
      storageResourceTags: ['dynamoDB']
    },
    propertyValueString: {
      type: "string",
      optionalOnCreate: true,
      canUpdate: false,
      validation: {
	    pattern: pattern
      },
      storageResourceTags: ['dynamoDB']
    },
    propertyValueNumber: {
      type: "number",
      optionalOnCreate: true,
      canUpdate: false,
      validation: {
	    pattern: pattern
      },
      storageResourceTags: ['dynamoDB']
    },
    propertyName: {
      type: "string",
      optionalOnCreate: true,
      canUpdate: false,
      validation: {},
      storageResourceTags: ['dynamoDB']
    }
  },
  identifiers: [
    {
      type: "identifier",
      fieldName: "triggerId"
    }
  ]
}

fieldNames

triggerId
(identifier)
comes from: {hash of valueType(property|attribute).propertyName}_{hash of propertyValue (string or number)}
or: serviceName_{hash of serviceName value}
or: topicName_{hash of topicName value}
attributes is for message attributes
property is from the data sent inside the message body
hash property name and value so no ambiguity about underscores/spaces etc..
valueType
property|attribute|serviceName|topicName
propertyName
"serviceName" and "topicName" valueTypes do not have propertyName
eg. property.propA.propB.propC (not validate nested object)
eg. attribute.serviceName
propertyValueString
for value of propertyValue is string
propertyValueNumber
for value of propertyValue is number


Object Relationships

hasTrigger

{
  "hasTrigger": {
    canChangeToRelTypes: [
      {
	    serviceTag: "ActivitySwitchboard",
	    relationshipTag: "disabledTrigger"
      }
    ],
    fieldNames: {
      "originTimestamp": {
	    type: "number",  			
	    requiredOnCreate: true,  	// default = false
  	    canUpdate: true,          	// default = true
	    validation: {}            	// ajv syntax
      }
    },
    storageResources: {
      dynamo: {
	    storageType: "dynamoDB"
      }
    },
    links: [
      {
	    storageResourceTags: ["dynamo"],
	    from: {
 	      objType: {
	        serviceTag: "ActivitySwitchboard",	
	        objectType: "triggerGroup"
	      },
	      linkType: "many",
	      handler: true		
	    },
	    to: {
	      objType: {
	        serviceTag: "ActivitySwitchboard",	
	        objectType: "trigger"		
	      },				
	      linkType: "many"
	    }
      }
    ]
  }
}

disabledTrigger

{
  "disabledTrigger": {
    canChangeToRelTypes: [
      {
	    serviceTag: "ActivitySwitchboard",
	    relationshipTag: "hasTrigger"
      }
    ],
    fieldNames: {
      "originTimestamp": {
	    type: "number",
	    requiredOnCreate: true,  	// default = false
	    canUpdate: true,          	// default = true
	    validation: {}            	// ajv syntax
      }
    },
    storageResources: {
      dynamo: {
	    storageType: "dynamoDB"
      }
    },
    links: [
      {
	    storageResourceTags: ["dynamo"],
	    from: {
	      objType: {
	        serviceTag: "ActivitySwitchboard",
	        objectType: "triggerGroup"
	      },
	      linkType: "many",
	      handler: true
	    },
	    to: {
	      objType: {
	        serviceTag: "ActivitySwitchboard",	
 	        objectType: "trigger"	
	      },
	      linkType: "many"
	    }
      }
    ]
  }
}

Efficiency

  • Service will result in a large number of queries to Triggers table, every message will need to make a query for every field set as an activityTrigger
  • Try to make this as efficient as possible
  • To reduce number of queries made to Tiggers table we use the msgCfg for any message received
    • MsgCfg sets which properties can be used as triggers, others are not queried

Handling msgCfgs

  • msgCfgs get updated from Message Config Manager service, we do this by subscribing to Message Config Manager's OutMsgCfgUpdate topic
  • Only want to process messages from certain In/Out topics, it will be most topics but does not have to be all
  • Set which topics to subscribe to by setting activitySwitchboard = true in msgCfg

Ideas

  • If more efficient can use cache for regular DynamoDB queries
  • Could add other matching methods such as greater than or less than, in DynamoDB this might be more efficient to add as separate table with its own structure, eg: partition key is the field reference, sort key is the amount, then use sort key to return matching triggers. Danger of bad partitioning in DynamoDB (or hitting limits) due to large numbers of sort keys associated with one partition key
  • could consider how to incorporate includes or checking within a set of options set in the trigger, again might need specialized table structure
  • Might be able to optimise by using SNS > stream instead of SNS > SQS for all incomming messages
  • One system level receiving service could be specialized logs, eg logs per service per user/per product/etc
  • Topic name is not fixed part of the TriggersGroup structure, allow for trigger groups that are not connected to specific topics, but can pass messages from any topic that matches other triggers

Working documents

Working_documents - Activity Switchboard