2020-12-19 - Category Tree Standard - Functions

From Izara Wiki
Jump to navigation Jump to search

Service - Category Tree Standard

Lambda Functions

CategoryNode/Create

/**
 * Create a categoryNode in the category tree
 * @param {string} catalogId
 * @param {string} categoryId
 * @param {string} [parentCategoryNodeId = ""] - if empty will be top level for this catalog
 * @param {string} searchType - sellOffer|product|variantProduct
 * @param {boolean} searchTypeMatchParent
 * @param {object} [filter={}]
 * @param {string} filterMatchParent - none|match|append
 * @param {object} [requiredData={}]
 * @param {string} requiredDataMatchParent - none|match|append
 * @param {string} userId
 *
 * @returns {string} vertexId
 */

Authorizer

  • Catalog level
  • Checks user has authorization to create a categoryNode for the submitted catalogId, so need to check in logic if parentCategoryNodeId, it's catalogId must match

HdrApi

  • Validator: (standard)

handler logic

  • userId = ?_izContext.authorized/signedInUser..?

logic

Expects categoryVertexId to already exist in the graph, might need to check this first or work into Graph Handler process somehow.

Currently any category can be added, if we want to restrict which CategoryServiceNameTags can be added to a Category Tree Standard hierarchy we could do so here

  1. const catalogGraphServiceName = {from Config table: CatalogGraphServiceName}
  2. // find the parentCategory details
  3. const parentNodeVertexTag = null
  4. const parentNodeVertexUniqueId = null
  5. if parentCategoryNodeId
    1. parentNodeVertexTag = NPM module - izara-market-shared#CategoryTreeStandardLib.categoryNodeGraphTag
    2. parentNodeVertexUniqueId = parentCategoryNodeId
  6. else
    1. parentNodeVertexTag = NPM module - izara-market-shared#CategoryTreeStandardLib.catalogNodeGraphTag
    2. parentNodeVertexUniqueId = catalogId
  7. // get parentNode and validate
  8. const parentNode = NPM module - izara-shared#graphSharedLib.getVertexByVertexTagAndVertexUniqueId
    1. graphServiceName: catalogGraphServiceName
    2. vertexTag: parentNodeVertexTag
    3. vertexUniqueId: parentNodeVertexUniqueId
  9. if parentNode not found
    1. throw error to client "unrecognized parentCategoryNodeId"
  10. if parentNode.catalogId != catalogId
    1. throw error to client "parentCategoryNodeId and catalogId mismatch"
  11. // get category to make sure exists
  12. const category = NPM module - izara-shared#graphSharedLib.getVertexByVertexTagAndVertexUniqueId
    1. graphServiceName: catalogGraphServiceName
    2. vertexTag: NPM module - izara-market-shared#CategoryStandardLib.categoryGraphTag
    3. vertexUniqueId: categoryId
  13. check if categoryId exists (could add additional restrictions on CategoryServiceNameTag here)
    1. if not maybe retry, or throw error?
  14. // get parentNode Settings
  15. const parentNodeSettings = NPM module - izara-shared#graphSharedLib.getCurrentVersionedDataByVertexTagAndVertexUniqueId
    1. graphServiceName: catalogGraphServiceName
    2. vertexTag: parentNodeVertexTag
    3. vertexUniqueId: parentNodeVertexUniqueId
    4. versionedDataTag: NPM module - izara-shared#graphSharedLib.settingsVersionedDataTag
  16. // prepare values ready for creating categoryNode child and versioned settings
  17. const categoryNodeId = #categoryNodeLib.createCategoryNodeId
    1. catalogId: catalogId
    2. categoryId: categoryId
    3. uuid: {random uuid})
  18. // categoryNodeSetting's vertex properties
  19. const categoryNodeSettingsProperties =
    1. searchType: searchType
    2. searchTypeMatchParent: searchTypeMatchParent
    3. filter: filter
    4. filterMatchParent: filterMatchParent
    5. requiredData: requiredData
    6. requiredDataMatchParent: requiredDataMatchParent

// categoryNode's vertex properties

  1. const categoryNodeProperties = #categoryNodeLib.calculateCategoryNodeProperties
    1. searchType: searchType
    2. searchTypeMatchParent: searchTypeMatchParent
    3. filter: filter
    4. filterMatchParent: filterMatchParent
    5. requiredData: requiredData
    6. requiredDataMatchParent: requiredDataMatchParent
    7. parentNodeSettings: parentNodeSettings
  2. categoryNodeProperties.catalogId = catalogId
  3. // create a timestamp for the edge, this can be used to protect against race conditions when recalculating categoryNode settings
  4. const edgeTimestamp = current timestamp
  5. // create the new node vertex and settings
  6. publish message to catalogGraphServiceName InCreateChildNodeWithVersionedDataAndRelationship topic:
    1. subjectVertexTag: parentNodeVertexTag
    2. subjectVertexUniqueId: parentNodeVertexUniqueId
    3. vertexTag: NPM module - izara-market-shared#CategoryTreeStandardLib.categoryNodeGraphTag
    4. vertexUniqueId: categoryNodeId
    5. createdByUserId: userId
    6. versionedDataTag: NPM module - izara-shared#graphSharedLib.settingsVersionedDataTag
    7. dataVertexProperties: categoryNodeSettingsProperties
    8. edgeLabel: NPM module - izara-market-shared#CategoryTreeStandardLib.hasChildCategoryNodeEdgeLabel
    9. vertexProperties: categoryNodeProperties
    10. edgeProperties: {
      1. edgeTimestamp: edgeTimestamp
  7. // create an edge connecting the new categoryNodeId to its category node
  8. publish message to catalogGraphServiceName In(?..CreateEdgeFromVertexTagsAndUniqueIds) topic:
    1. subjectVertexTag: NPM module - izara-market-shared#CategoryTreeStandardLib.categoryNodeGraphTag
    2. subjectVertexUniqueId: categoryNodeId
    3. edgeLabel: NPM module - izara-market-shared#CategoryTreeStandardLib.isCategoryEdgeLabel
    4. objectVertexTag: NPM module - izara-market-shared#CategoryStandardLib.categoryGraphTag
    5. objectVertexUniqueId categoryId
  9. // create an SQS message to recalculate parents filter
  10. send message to own InRecalculateCategoryNodeFilter topic:
    1. vertexTag = parentNodeVertexTag
    2. vertexUniqueId: parentNodeVertexUniqueId
  11. // **** start process to rebuild/regenerate other nodes according to this new node, eg parent's filters, not yet worked out how to do this serverless and avoid race conditions
  12. // report the new category tree node
  13. send message to own OutCatalogCreated topic:
    1. catalogId: catalogId
    2. categoryId: categoryId
    3. vertexTag: NPM module - izara-market-shared#CategoryTreeStandardLib.categoryNodeGraphTag
    4. vertexUniqueId: categoryNodeId
    5. userId: userId

CategoryNode/BuildBrowseRequest

/**
 * Builds a complete request ready to be sent to Search Result service 
 * @param {string} catalogId
 * @param {string} [categoryNodeId=""] - empty means no category specified, top level catalog browse
 * @param {string} [searchType=""] - overwrite default searchType
 * @param {Object} [filter={}] - complex filter object, adds additional filters
 * @param {Object} [requiredData={}] - overwrite default requiredData
 *
 * @returns {Object} searchResultRequest
 */

HdrInv

  • Validator: (standard)

handler logic

  • (standard)

logic

  1. const catalogGraphServiceName = {from Config table: CatalogGraphServiceName}
  2. // find the category/catalog node identified
  3. const nodeVertexTag = null
  4. const nodeVertexUniqueId = null
  5. if categoryNodeId
    1. nodeVertexTag = NPM module - izara-market-shared#CategoryTreeStandardLib.categoryNodeGraphTag
    2. nodeVertexUniqueId = categoryNodeId
  6. else
    1. nodeVertexTag = NPM module - izara-market-shared#CategoryTreeStandardLib.catalogNodeGraphTag
    2. nodeVertexUniqueId = catalogId
  7. const categoryNode = NPM module - izara-shared#graphSharedLib.getVertexByVertexTagAndVertexUniqueId
    1. graphServiceName: catalogGraphServiceName
    2. vertexTag: nodeVertexTag
    3. vertexUniqueId: nodeVertexUniqueId
  8. if no record found return error
  9. const browseRequest = {
    1. searchType: use searchType in params if set, else use categoryNode.searchType
    2. filter: if filter empty use categoryNode.filter, otherwise group both into their own blocks and join with an AND logical
    3. requiredData: use requiredData in params if set, else use categoryNode.requiredData
  10. return browseRequest

CategoryNode/UpdateSettings

/**
 * Set a categoryNode to be enabled or disabled, will do nothing if setting same as current setting
 * @param {string} catalogId
 * @param {string} categoryNodeId
 * @param {string} setting - enabled|disabled
 * @param {string} userId
 * @param {string} searchType - sellOffer|product|variantProduct
 * @param {boolean} searchTypeMatchParent
 * @param {object} [filter={}]
 * @param {string} filterMatchParent - none|match|append
 * @param {object} [requiredData={}]
 * @param {string} requiredDataMatchParent - none|match|append
 *
 */

Authorizer

  • Catalog level
  • Checks user has authorization to update categoryNode for the submitted catalogId, so need to check in logic categoryNodeId's catalogId matches

HdrApi

  • Validator: (standard)

handler logic

  • userId = ?_izContext.authorized/signedInUser..?

logic

  1. const catalogGraphServiceName = {from Config table: CatalogGraphServiceName}
  2. // find the categoryNode
  3. const categoryNode = NPM module - izara-shared#graphSharedLib.getVertexByVertexTagAndVertexUniqueId
    1. graphServiceName: catalogGraphServiceName
    2. vertexTag: NPM module - izara-market-shared#CategoryTreeStandardLib.categoryNodeGraphTag
    3. vertexUniqueId: categoryNodeId
  4. // validate request
  5. if no record found return error
  6. if categoryNode.catalogId != catalogId
    1. throw error to client "categoryNodeId and catalogId mismatch"
  7. // create a timestamp for the new Settings edge, this can be used to protect against race conditions when recalculating categoryNode settings
  8. const edgeTimestamp = current timestamp

// get the parentNode

  1. const parentNode = NPM module - izara-shared#graphSharedLib.getVertexInEdgesAndVerticesByVertexTagAndVertexUniqueId
    1. graphServiceName: catalogGraphServiceName
    2. objectVertexTag: NPM module - izara-market-shared#CategoryTreeStandardLib.categoryNodeGraphTag
    3. objectVertexUniqueId: categoryNodeId
    4. edgeLabel: NPM module - izara-market-shared#CategoryTreeStandardLib.hasChildCategoryNodeEdgeLabel
  2. // get parentNode Settings, parent node might be catalog or categoryNode so use the vertexId
  3. const parentNodeSettings = NPM module - izara-shared#graphSharedLib.getCurrentVersionedDataByVertexId
    1. graphServiceName: catalogGraphServiceName
    2. vertexId: parentNode.vertexId
    3. versionedDataTag: NPM module - izara-shared#graphSharedLib.settingsVersionedDataTag
  4. // categoryNodeSetting's vertex properties
  5. const categoryNodeSettingsProperties =
    1. searchType: searchType
    2. searchTypeMatchParent: searchTypeMatchParent
    3. filter: filter
    4. filterMatchParent: filterMatchParent
    5. requiredData: requiredData
    6. requiredDataMatchParent: requiredDataMatchParent
  6. // create new versionedData vertex
  7. publish message to catalogGraphServiceName InCreateVersionedData topic:
    1. vertexTag: NPM module - izara-market-shared#CategoryTreeStandardLib.categoryNodeGraphTag
    2. vertexUniqueId: categoryNodeId
    3. createdByUserId: userId
    4. versionedDataTag: NPM module - izara-shared#graphSharedLib.settingsVersionedDataTag
    5. dataVertexProperties: categoryNodeSettingsProperties
    6. timestamp: edgeTimestamp

// categoryNode's vertex properties

  1. const categoryNodeProperties = #categoryNodeLib.calculateCategoryNodeProperties
    1. searchType: searchType
    2. searchTypeMatchParent: searchTypeMatchParent
    3. filter: filter
    4. filterMatchParent: filterMatchParent
    5. requiredData: requiredData
    6. requiredDataMatchParent: requiredDataMatchParent
    7. parentNodeSettings: parentNodeSettings

// update categoryNode's vertex properties

  1. publish message to catalogGraphServiceName InUpdateNodeProperties topic:
    1. vertexTag: NPM module - izara-market-shared#CategoryTreeStandardLib.categoryNodeGraphTag
    2. vertexUniqueId: categoryNodeId
    3. vertexProperties: categoryNodeProperties
  2. // **** start process to rebuild/regenerate parent/child node filters etc, not yet worked out how to do this serverless and avoid race conditions
  3. // report the action
  4. send message to own OutCategoryNodeSettingsUpdated topic:
    1. categoryNodeId
    2. userId

CategoryNode/EnableDisable

/**
 * Set a categoryNode to be enabled or disabled, will do nothing if setting same as current setting
 * @param {string} catalogId
 * @param {string} categoryNodeId
 * @param {string} setting - enabled|disabled
 * @param {string} userId
 *
 */

Authorizer

  • Catalog level
  • Checks user has authorization to create a categoryNode for the submitted catalogId, so need to check in logic categoryNodeId's catalogId matches

HdrApi

  • Validator: (standard)

handler logic

  • userId = ?_izContext.authorized/signedInUser..?

logic

  1. const catalogGraphServiceName = {from Config table: CatalogGraphServiceName}
  2. // find the categoryNode
  3. const categoryNode = NPM module - izara-shared#graphSharedLib.getVertexByVertexTagAndVertexUniqueId
    1. graphServiceName: catalogGraphServiceName
    2. vertexTag: NPM module - izara-market-shared#CategoryTreeStandardLib.categoryNodeGraphTag
    3. vertexUniqueId: categoryNodeId
  4. // validate request
  5. if no record found return error
  6. if categoryNode.catalogId != catalogId
    1. throw error to client "categoryNodeId and catalogId mismatch"
  7. // prepare edge change
  8. const fromEdgeLabel = null
  9. const toEdgeLabel = null
  10. const replacedByEdgeLabel = null
  11. const msgTagText = ""
  12. if(setting == "disabled")
    1. fromEdgeLabel = NPM module - izara-market-shared#CategoryTreeStandardLib.hasChildCategoryNodeEdgeLabel
    2. toEdgeLabel = NPM module - izara-market-shared#CategoryTreeStandardLib.hasDisabledChildCategoryNodeEdgeLabel
    3. replacedByEdgeLabel = NPM module - izara-market-shared#CategoryTreeStandardLib.disabledByEdgeLabel
    4. msgTagText = "Disabled"
  13. else
    1. fromEdgeLabel = NPM module - izara-market-shared#CategoryTreeStandardLib.hasDisabledChildCategoryNodeEdgeLabel
    2. toEdgeLabel = NPM module - izara-market-shared#CategoryTreeStandardLib.hasChildCategoryNodeEdgeLabel
    3. replacedByEdgeLabel = NPM module - izara-market-shared#CategoryTreeStandardLib.enabledByEdgeLabel
    4. msgTagText = "Enabled"
  14. // get existing edge label
  15. const existingEdgeAndParentNode = NPM module - izara-shared#graphSharedLib.getVertexInEdgesAndVerticesByVertexTagAndVertexUniqueId
    1. graphServiceName: catalogGraphServiceName
    2. objectVertexTag: NPM module - izara-market-shared#CategoryTreeStandardLib.categoryNodeGraphTag
    3. objectVertexUniqueId: categoryNodeId
    4. edgeLabel: fromEdgeLabel
  16. // check not already set to toEdgeLabel
  17. if(!existingEdgeAndParentNode)
    1. throw error to client "categoryNodeId already setting"
  18. // create a timestamp for the edge, this can be used to protect against race conditions when recalculating categoryNode settings
  19. const edgeTimestamp = current timestamp
  20. // swap the edges
  21. publish message to catalogGraphServiceName InReplaceRelationship topic:
    1. fromEdgeId: existingEdgeAndParentNode.edge.edgeId
    2. toEdgeLabel: toEdgeLabel
    3. replacedByUserId: userId
    4. replacedByEdgeLabel: replacedByEdgeLabel
    5. toEdgeProperties: {edgeTimestamp: edgeTimestamp}
  22. // **** start process to rebuild/regenerate parent node filter if disabled, child then parent nodes if enabled, not yet worked out how to do this serverless and avoid race conditions
  23. // report the action
  24. send message to own Out (...?) "CategoryNode" + msgTagText topic:
    1. catalogId
    2. categoryNodeId
    3. userId

CategoryNode/RecalculateCategoryNodeFilter

/**
 * Create a new vertex for the subject of translations
 * @param {string} vertexTag
 * @param {string} vertexUniqueId
 *
 */

HdrSqs

  • Triggered from InRecalculateCategoryNodeFilter topic:
  • Validator: (standard)

handler logic

  • (standard)

logic

... need to work out how to mitigate race conditions

  1. .. need to pull filters of all children and combine with own filter

Functions

categoryNodeLib.createCategoryNodeId

/**
 * @param {string} catalogId
 * @param {string} categoryId
 * @param {string} uuid
 *
 * @returns {string} categoryNodeVertexId
 */

logic

  1. return catalogId + '_' + categoryId + '_' + uuid

categoryNodeLib.calculateCategoryNodeProperties

/**
 * @param {string} searchType
 * @param {boolean} searchTypeMatchParent
 * @param {object} [filter={}]
 * @param {string} filterMatchParent
 * @param {object} [requiredData={}]
 * @param {string} requiredDataMatchParent
 * @param {object} parentNodeSettings
 *
 * @returns {object} categoryNodeProperties
 */

logic

  1. // create the new categoryNode's calculated settings, defaulting to submitted values (no parent matching)
  2. const categoryNodeProperties =
    1. searchType: searchType
    2. filter: filter
    3. requiredData: requiredData
  3. // calculate searchType value
  4. if searchTypeMatchParent == none
    1. categoryNodeProperties.searchType = searchType
  5. elseif searchTypeMatchParent == match
    1. categoryNodeProperties.searchType = parentNodeSettings.searchType
  6. // calculate filter value
  7. if filterMatchParent == match
    1. categoryNodeProperties.filter = parentNodeSettings.filter
  8. elseif filterMatchParent == append
    1. categoryNodeProperties.filter = {wrap parentNodeSettings.filter in level + AND element + wrap filter in level}
  9. // calculate requiredData value
  10. if requiredDataMatchParent == none
    1. if requiredData empty
      1. throw error "requiredData cannot be empty if not matching parent setting"
  11. elseif requiredDataMatchParent == match
    1. categoryNodeProperties.requiredData = parentNodeSettings.requiredData
  12. elseif requiredDataMatchParent == append
    1. categoryNodeProperties.requiredData = {join parentNodeSettings.requiredData and requiredData, removing any duplicates}
  13. return categoryNodeProperties