Skip to content

Commit

Permalink
use dataloader to collect calls to DB fixes cap-js#30
Browse files Browse the repository at this point in the history
  • Loading branch information
d060338 authored and d060338 committed Oct 7, 2024
1 parent 457a2a0 commit 4d71c28
Show file tree
Hide file tree
Showing 3 changed files with 25 additions and 10 deletions.
13 changes: 7 additions & 6 deletions lib/change-log.js
Original file line number Diff line number Diff line change
Expand Up @@ -167,12 +167,12 @@ const _getChildChangeObjId = async function (
const _formatCompositionContext = async function (changes, reqData) {
const childNodeChanges = []

for (const change of changes) {
await Promise.all(changes.map(async (change) => {
if (typeof change.valueChangedTo === "object") {
if (!Array.isArray(change.valueChangedTo)) {
change.valueChangedTo = [change.valueChangedTo]
}
for (const childNodeChange of change.valueChangedTo) {
await Promise.all(change.valueChangedTo.map(async (childNodeChange) => {
const curChange = Object.assign({}, change)
const path = childNodeChange._path.split('/')
const curNodePathVal = path.pop()
Expand All @@ -184,10 +184,10 @@ const _formatCompositionContext = async function (changes, reqData) {
reqData
)
_formatCompositionValue(curChange, objId, childNodeChange, childNodeChanges)
}
}))
change.valueChangedTo = undefined
}
}
}))
changes.push(...childNodeChanges)
}

Expand Down Expand Up @@ -248,7 +248,7 @@ const _getObjectIdByPath = async function (

const _formatObjectID = async function (changes, reqData) {
const objectIdCache = new Map()
for (const change of changes) {
await Promise.all(changes.map(async (change) => {
const path = change.serviceEntityPath.split('/')
const curNodePathVal = path.pop()
const parentNodePathVal = path.pop()
Expand Down Expand Up @@ -276,7 +276,7 @@ const _formatObjectID = async function (changes, reqData) {
change.entityID = curNodeObjId
change.parentEntityID = parentNodeObjId
change.parentKey = getUUIDFromPathVal(parentNodePathVal)
}
}))
}

const _isCompositionContextPath = function (aPath, hasComp) {
Expand All @@ -290,6 +290,7 @@ const _isCompositionContextPath = function (aPath, hasComp) {
}

const _formatChangeLog = async function (changes, req) {
cds.context.dataloaders = {}
await _formatObjectID(changes, req.data)
await _formatAssociationContext(changes, req.data)
await _formatCompositionContext(changes, req.data)
Expand Down
19 changes: 15 additions & 4 deletions lib/entity-helper.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
const cds = require("@sap/cds")
const DataLoader = require("dataloader");
const LOG = cds.log("change-log")


Expand Down Expand Up @@ -29,11 +30,21 @@ const getObjIdElementNamesInArray = function (elements) {
else return []
}

const getCurObjFromDbQuery = async function (entityName, queryVal, /**optional*/ queryKey='ID') {
const getCurObjFromDbQuery = async function (entityName, queryVal, /**optional*/ queryKey = 'ID') {
if (!(entityName in cds.context.dataloaders)) {
cds.context.dataloaders[entityName] = new DataLoader(async (keys) => {
// REVISIT: This always reads all elements -> should read required ones only!
const results = await SELECT.from(entityName).where(queryKey, 'in', keys)
const resultsByKey = results.reduce((acc, instance) => {
const key = instance[queryKey]
acc[key] = instance
return acc
}, {})
return keys.map(key => resultsByKey[key] || {})
})
}
if (!queryVal) return {}
// REVISIT: This always reads all elements -> should read required ones only!
const obj = await SELECT.one.from(entityName).where({[queryKey]: queryVal})
return obj || {}
return cds.context.dataloaders[entityName].load(queryVal)
}

const getCurObjFromReqData = function (reqData, nodePathVal, pathVal) {
Expand Down
3 changes: 3 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -37,5 +37,8 @@
"model": "@cap-js/change-tracking"
}
}
},
"dependencies": {
"dataloader": "^2.2.2"
}
}

0 comments on commit 4d71c28

Please sign in to comment.