Yes, sure!
There is quite alot of code, pasting the functions in the order they are called.
Trigger definition:
{
"id": "5fa9016e8591bc0b25ca4207",
"name": "productCollectionTrigger",
"type": "DATABASE",
"config": {
"service_name": "mongodb-atlas",
"database": "custom-made",
"collection": "validatedProduct",
"operation_types": [
"INSERT",
"REPLACE"
],
"full_document": true
},
"function_name": "handleProductsCustomMadeAvailability",
"disabled": false
}
handeProductsCustomMadeAvailability:
exports = async (changeEvent, testDatabase) => {
const { fullDocument } = changeEvent
const { artnocol, validation } = fullDocument
const database = testDatabase || 'custom-made'
const cluster = context.services.get('mongodb-atlas')
const validatedCollection = cluster
.db(database)
.collection('validatedProduct')
let missingMeasurements = []
// ===> START: the following is what seems to affect the execution time (but only when called through the trigger)
try {
const { rulegroup, lectrabody: fit, lectracuff: cufflectra } = fullDocument
missingMeasurements = await context.functions.execute(
'findMissingMeasurements',
{ rulegroup, fit, cufflectra },
testDatabase
)
} catch (error) {
console.error('findMissingMeasurements:', error, 'for product')
}
// <==== END
const newAvailableCustomMade = validation ?
validation.isValid &&
validation.missingComponentTypes.length === 1 &&
validation.missingComponentTypes.includes('size') &&
validation.isInStock.result &&
missingMeasurements &&
missingMeasurements.length < 1
: false
try {
await validatedCollection.updateOne({ artnocol }, { $set: { availableCustomMade: newAvailableCustomMade, missingData: missingMeasurements} })
} catch (error) {
throw `Could not update document for product ${artnocol}: ${error}`
}
try {
var fullUpdatedDocument = await validatedCollection.findOne({ artnocol })
} catch (error) {
throw `Could not find updated document for product ${artnocol}: ${error}`
}
// send updated availability to Kinesis -> Product service
try {
const {
artnocol,
availableCustomMade,
lastValidatedAt,
priceGroup,
stock,
} = fullUpdatedDocument
const type = 'custom-made'
const message = {
sku: artnocol,
isAvailableCustomMade: availableCustomMade,
lastValidatedAt,
priceGroup: priceGroup || '',
stock: stock || 0,
}
const awsService = context.services.get('aws')
const response = await awsService
.kinesis('eu-west-1')
.PutRecord({
Data: JSON.stringify({ type, message }),
StreamName: context.values.get('aws-kinesis-stream'),
PartitionKey: '1',
})
if (response) {
console.log(`Succesfully sent custom made availability to kinesis for product ${artnocol}`)
}
} catch (error) {
throw `Could not send custom made availability to kinesis for product ${artnocol}: ${error}`
}
}
findMissingMeasurements:
exports = async (input, testDatabase) => {
const { rulegroup, fit, cufflectra } = input
const cluster = context.services.get('mongodb-atlas')
const database = 'custom-made-config'
let sizesDocument = ''
try {
sizesDocument = await cluster.db(database).collection('sizesPerFit').findOne({ fitno: fit })
} catch (error) {
throw `findMissingMeasurements: ${error}`
}
if (!sizesDocument) {
throw `findMissingMeasurements: could not find sizePerFit document for fit ${fit}`
}
const measurementPromiseArray = []
for (const size of sizesDocument.sizes) {
measurementPromiseArray.push(context.functions.execute(
'getDefaultMeasurements',
{
rulegroup,
fitno: fit,
size,
cufflectra,
},
testDatabase
))
}
try {
var measurementsPerSize = await Promise.all(measurementPromiseArray)
} catch (error) {
throw `findMissingMeasurements: getDefaultMeasurements: ${error}`
}
const measurementPoints = ['neck','waist','chest','length','cuffright','cuffleft', 'sleeveright', 'sleeveleft']
const missingMeasurements = []
for (let i = 0; i < sizesDocument.sizes.length; i++) {
const missingMeasurementsPerSize = { size: sizesDocument.sizes[i], missingMeasurements: [] }
for (const measurementPoint of measurementPoints) {
if (!(measurementPoint in measurementsPerSize[i])) {
missingMeasurementsPerSize.missingMeasurements.push(measurementPoint)
}
}
if (missingMeasurementsPerSize.missingMeasurements.length > 0) {
missingMeasurements.push(missingMeasurementsPerSize)
}
}
return missingMeasurements
}
getDefaultMeasurements:
exports = async (input, testDatabase) => {
const { rulegroup, fitno, size, cufflectra } = input
const expectedInput = {
rulegroup,
fitno,
size,
cufflectra,
}
const missingInformation = Object.keys(expectedInput).reduce((acc, key) => {
return !expectedInput[key] ? [...acc, `${key}: ${expectedInput[key]}`] : acc
}, [])
if (missingInformation.length) {
throw `getDefaultMeasurements: Missing the following input: ${missingInformation.join(
', '
)}`
}
const database = testDatabase || 'custom-made-component'
const db = context.services.get('mongodb-atlas').db(database)
const collection = db.collection('measurements')
let validMeasurements = {}
const measurementPoints = {
NECK: 'neck',
WAIST: 'waist',
CHEST: 'chest',
LENGTH: 'length',
CUFF_RIGHT: 'cuff right',
CUFF_LEFT: 'cuff left',
SLEEVE_RIGHT: 'right sleeve',
SLEEVE_LEFT: 'left sleeve',
SHORT_SLEEVE: 'short sleeve',
}
// Function to remove the ugly "Cuff <LECTRA> Left/Right" from the measurementpoint.
const removeLectraFromPoint = (measurementPoint) => {
let pointWords = measurementPoint.split(' ')
if (
pointWords[0] === 'cuff' &&
(pointWords[2] === 'right' || pointWords[2] === 'left')
) {
pointWords.splice(1, 1)
} else if (pointWords[0] === 'short') {
pointWords.splice(2, 1)
}
return pointWords.join(' ')
}
const setMeasurementByPoint = (measurement) => {
const actualPointName = removeLectraFromPoint(measurement.measuementpoint)
switch (actualPointName) {
case measurementPoints.NECK:
validMeasurements = {
...validMeasurements,
neck: measurement.defaultvalue,
}
break
case measurementPoints.WAIST:
validMeasurements = {
...validMeasurements,
waist: measurement.defaultvalue,
}
break
case measurementPoints.CHEST:
validMeasurements = {
...validMeasurements,
chest: measurement.defaultvalue,
}
break
case measurementPoints.LENGTH:
validMeasurements = {
...validMeasurements,
length: measurement.defaultvalue,
}
break
case measurementPoints.CUFF_RIGHT:
validMeasurements = {
...validMeasurements,
cuffright: measurement.defaultvalue,
}
break
case measurementPoints.CUFF_LEFT:
validMeasurements = {
...validMeasurements,
cuffleft: measurement.defaultvalue,
}
break
case measurementPoints.SLEEVE_RIGHT:
validMeasurements = {
...validMeasurements,
sleeveright: measurement.defaultvalue,
}
break
case measurementPoints.SLEEVE_LEFT:
validMeasurements = {
...validMeasurements,
sleeveleft: measurement.defaultvalue,
}
break
case measurementPoints.SHORT_SLEEVE:
validMeasurements = {
...validMeasurements,
sleeveright: measurement.defaultvalue,
sleeveleft: measurement.defaultvalue,
}
break
default:
return
}
}
try {
const measurements = await collection
.find({
rulegroup,
fitno,
size,
})
.toArray()
if (measurements && measurements.length > 0) {
const isValidForCuffPromiseArray = []
measurements.forEach(measurement => {
isValidForCuffPromiseArray.push(context.functions.execute(
'getMeasurementPointValidForCuff',
{ cufflectra },
{ measuementpoint: measurement.measuementpoint },
testDatabase
))
})
const isValidForCuffArray = await Promise.all(isValidForCuffPromiseArray)
isValidForCuffArray.forEach((isValidForCuff, index) => {
if (isValidForCuff && isValidForCuff.result) {
setMeasurementByPoint(measurements[index])
}
})
} else {
throw `getDefaultMeasurements: Cannot find any measurements matching: { rulegroup: ${rulegroup}, fitno: ${fitno}, size: ${size} }`
}
return validMeasurements
} catch (error) {
throw error
}
}
getMeasurementPointValidForCuff:
exports = async (input, source, testDatabase) => {
const { cufflectra, cuffgroup, fitno, rulegroup } = input
const { measuementpoint } = source
if (!measuementpoint) {
return {
error: `getMeasurementPointValidForCuff: No measurementpoint was included in the source argument`
}
}
const database = testDatabase || 'custom-made-component'
const cluster = context.services.get('mongodb-atlas')
const db = cluster.db(database)
const configCollection = cluster
.db('custom-made-config')
.collection('componentDetailPossibilities')
const chosenCuff =
(cufflectra || cuffgroup) &&
(await db.collection('cuffs').findOne({
...(cuffgroup && { cuffgroup }),
...(rulegroup && { rulegroup }),
...(fitno && { fitno }),
...(cufflectra && { cufflectra }),
}))
// Find digits in measuementpoint
const lectra = measuementpoint.match(/(\d+)/)
var lectraMatch = true
if (lectra) {
if (chosenCuff && (cufflectra || (cuffgroup && fitno && rulegroup)))
lectraMatch = chosenCuff.cufflectra === lectra[0]
else
return {
error: `Cuff measurement can not be determined 'valid for cuff' without cuffgroup, rulegroup and fit, or cufflectra`,
}
}
if (chosenCuff) {
const cuffDetailPossibilities = await configCollection.findOne({
componentname: 'cuff',
})
const componentvalue = chosenCuff[cuffDetailPossibilities.componentkey] // sleevelength = "Short" || "Long"
const detailoptionobjects = cuffDetailPossibilities.detailoptionobjects
for (const object of detailoptionobjects) {
if (object.stringValue === componentvalue) {
var measurementPointsValidForCuff = object.measurementpoints
}
}
}
const pointMatch = measurementPointsValidForCuff?.filter((point) => {
// Find spaces in point
if (/\s/.test(point)) {
const words = point.split(' ')
return (
measuementpoint.includes(words[0]) && measuementpoint.includes(words[1])
)
}
return measuementpoint.includes(point)
})
return {
result: pointMatch ? pointMatch.length > 0 && lectraMatch : false,
}
}