Skip to content

Commit

Permalink
#1472: enable sequential creates for type asset to handle type-intern…
Browse files Browse the repository at this point in the history
…al dependencies
  • Loading branch information
JoernBerkefeld committed Aug 31, 2024
1 parent f856ba8 commit ed61d71
Show file tree
Hide file tree
Showing 2 changed files with 44 additions and 28 deletions.
2 changes: 1 addition & 1 deletion lib/metadataTypes/Asset.js
Original file line number Diff line number Diff line change
Expand Up @@ -259,7 +259,7 @@ class Asset extends MetadataType {
// assets can link to other assets (via template, content block reference and SSJS/AMPscript) and deployment would fail if we did not sort this here
metadataMap = await this._getUpsertOrder(metadataMap, deployDir);
}
return super.upsert(metadataMap, deployDir);
return super.upsert(metadataMap, deployDir, true);
}

/**
Expand Down
70 changes: 43 additions & 27 deletions lib/metadataTypes/MetadataType.js
Original file line number Diff line number Diff line change
Expand Up @@ -710,12 +710,14 @@ class MetadataType {
*
* @param {MetadataTypeMap} metadataMap metadata mapped by their keyField
* @param {string} deployDir directory where deploy metadata are saved
* @param {boolean} [runCreatesSequentially] when a type has self-dependencies creates need to run one at a time and created keys need to be cached to ensure following creates/updates have thoses keys available
* @returns {Promise.<MetadataTypeMap>} keyField => metadata map
*/
static async upsert(metadataMap, deployDir) {
static async upsert(metadataMap, deployDir, runCreatesSequentially = false) {
const orignalMetadataMap = structuredClone(metadataMap);
const metadataToUpdate = [];
const metadataToCreate = [];
let createResults = [];
let filteredByPreDeploy = 0;
for (const metadataKey in metadataMap) {
let hasError = false;
Expand Down Expand Up @@ -744,51 +746,65 @@ class MetadataType {
if (deployableMetadata) {
metadataMap[metadataKey] = deployableMetadata;
// create normalizedKey off of whats in the json rather than from "metadataKey" because preDeployTasks might have altered something (type asset)
await this.createOrUpdate(
const action = await this.createOrUpdate(
metadataMap,
metadataKey,
hasError,
metadataToUpdate,
metadataToCreate
);
if (runCreatesSequentially && action === 'create') {
// handle creates sequentially here becasue we might have interdepencies
const result = await this.create(metadataMap[metadataKey], deployDir);
if (result) {
createResults.push(result);

// make this newly created item available in cache for other itmes that might reference it
const newObject = {};
newObject[metadataKey] = metadataMap[metadataKey];
cache.mergeMetadata(this.definition.type, newObject);
}
}
} else {
filteredByPreDeploy++;
}
} catch (ex) {
Util.logger.errorStack(ex, `Upserting ${this.definition.type} failed`);
}
}
const createLimit = pLimit(10);
const createResults = (
await Promise.all(
metadataToCreate
.filter((r) => r !== undefined && r !== null)
.map((metadataEntry) =>
createLimit(() => this.create(metadataEntry, deployDir))
)
)
).filter((r) => r !== undefined && r !== null);
if (!runCreatesSequentially) {
const createLimit = pLimit(10);
createResults = (
await Promise.all(
metadataToCreate
.filter((r) => r !== undefined && r !== null)
.map((metadataEntry) =>
createLimit(() => this.create(metadataEntry, deployDir))
)
)
).filter((r) => r !== undefined && r !== null);
}

if (Util.OPTIONS.noUpdate && metadataToUpdate.length > 0) {
let updateResults = [];
if (Util.OPTIONS.noUpdate && metadataToUpdate.length) {
Util.logger.info(
` ☇ skipping update of ${metadataToUpdate.length} ${this.definition.type}${metadataToUpdate.length == 1 ? '' : 's'}: --noUpdate flag is set`
);
} else if (metadataToUpdate.length) {
const updateLimit = pLimit(10);
updateResults = (
await Promise.all(
metadataToUpdate
.filter((r) => r !== undefined && r !== null)
.map((metadataEntry) =>
updateLimit(() =>
this.update(metadataEntry.after, metadataEntry.before)
)
)
)
).filter((r) => r !== undefined && r !== null);
}

const updateLimit = pLimit(10);
const updateResults = Util.OPTIONS.noUpdate
? []
: (
await Promise.all(
metadataToUpdate
.filter((r) => r !== undefined && r !== null)
.map((metadataEntry) =>
updateLimit(() =>
this.update(metadataEntry.after, metadataEntry.before)
)
)
)
).filter((r) => r !== undefined && r !== null);
// Logging
Util.logger.info(
`${this.definition.type} upsert: ${createResults.length} of ${metadataToCreate.length} created / ${updateResults.length} of ${metadataToUpdate.length} updated` +
Expand Down

0 comments on commit ed61d71

Please sign in to comment.