Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

#1034: pause, execute, schedule now return the list of keys that were affected #1035

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
84 changes: 42 additions & 42 deletions docs/dist/documentation.md

Large diffs are not rendered by default.

80 changes: 42 additions & 38 deletions lib/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -734,7 +734,7 @@ class Mcdev {
* @param {string} businessUnit name of BU
* @param {TYPE.SupportedMetadataTypes} [selectedType] limit to given metadata types
* @param {string[]} [keys] customerkey of the metadata
* @returns {Promise.<boolean>} true if all started successfully, false if not
* @returns {Promise.<Object.<string, string[]>>} key: business unit name, value: list of scheduled item keys
*/
static async schedule(businessUnit, selectedType, keys) {
this.setOptions({ schedule: true });
Expand All @@ -746,7 +746,7 @@ class Mcdev {
* @param {string} businessUnit name of BU
* @param {TYPE.SupportedMetadataTypes} [selectedType] limit to given metadata types
* @param {string[]} [keys] customerkey of the metadata
* @returns {Promise.<boolean>} true if all started successfully, false if not
* @returns {Promise.<Object.<string, string[]>>} key: business unit name, value: list of executed item keys
*/
static async execute(businessUnit, selectedType, keys) {
return this.#runMethod('execute', businessUnit, selectedType, keys);
Expand All @@ -757,7 +757,7 @@ class Mcdev {
* @param {string} businessUnit name of BU
* @param {TYPE.SupportedMetadataTypes} [selectedType] limit to given metadata types
* @param {string[]} [keys] customerkey of the metadata
* @returns {Promise.<boolean>} true if all started successfully, false if not
* @returns {Promise.<Object.<string, string[]>>} key: business unit name, value: list of paused item keys
*/
static async pause(businessUnit, selectedType, keys) {
return this.#runMethod('pause', businessUnit, selectedType, keys);
Expand All @@ -769,13 +769,15 @@ class Mcdev {
* @param {string} businessUnit name of BU
* @param {TYPE.SupportedMetadataTypes} [selectedType] limit to given metadata types
* @param {string[]} [keys] customerkey of the metadata
* @returns {Promise.<boolean>} true if all started successfully, false if not
* @returns {Promise.<Object.<string, string[]>>} key: business unit name, value: list of affected item keys
*/
static async #runMethod(methodName, businessUnit, selectedType, keys) {
Util.startLogger();
let lang_past;
let lang_present;
let requireKeyOrLike;
const resultObj = {};

switch (methodName) {
case 'execute': {
lang_past = 'executed';
Expand All @@ -794,19 +796,18 @@ class Mcdev {
Util.logger.info(`mcdev:: ${methodName} ${selectedType}`);
const properties = await config.getProperties();
let counter_credBu = 0;
let counter_failed = 0;
if (!(await config.checkProperties(properties))) {
// return null here to avoid seeing 2 error messages for the same issue
return false;
return resultObj;
}
if (!Util._isValidType(selectedType)) {
return false;
return resultObj;
}
if (!Object.prototype.hasOwnProperty.call(MetadataTypeInfo[selectedType], methodName)) {
Util.logger.error(
` ☇ skipping ${selectedType}: ${methodName} is not supported yet for ${selectedType}`
);
return false;
return resultObj;
}

if (
Expand All @@ -815,15 +816,15 @@ class Mcdev {
(!Util.OPTIONS.like || !Object.keys(Util.OPTIONS.like).length)
) {
Util.logger.error('At least one key or a --like filter is required.');
return false;
return resultObj;
} else if (
Array.isArray(keys) &&
keys.length &&
Util.OPTIONS.like &&
Object.keys(Util.OPTIONS.like).length
) {
Util.logger.error('You can either specify keys OR a --like filter.');
return false;
return resultObj;
}

if (businessUnit === '*') {
Expand All @@ -833,13 +834,17 @@ class Mcdev {
let counter_credTotal = 0;
for (const cred in properties.credentials) {
Util.logger.info(`:: ${lang_present} ${selectedType} on all BUs for ${cred}`);

// reset counter per cred
counter_credBu = 0;
for (const bu in properties.credentials[cred].businessUnits) {
if (await this.#runOnBU(methodName, cred, bu, selectedType, keys)) {
counter_credBu++;
} else {
counter_failed++;
}
resultObj[cred + '/' + bu] = await this.#runOnBU(
methodName,
cred,
bu,
selectedType,
keys
);
counter_credBu++;
Util.startLogger(true);
}
counter_credTotal += counter_credBu;
Expand All @@ -865,40 +870,41 @@ class Mcdev {
true
);
if (buObject === null) {
return false;
return resultObj;
} else {
cred = buObject.credential;
bu = buObject.businessUnit;
}
}
if (bu === '*' && properties.credentials && properties.credentials[cred]) {
Util.logger.info(`:: ${lang_present} ${selectedType} on all BUs for ${cred}`);
let counter_credBu = 0;
for (const bu in properties.credentials[cred].businessUnits) {
if (await this.#runOnBU(methodName, cred, bu, selectedType, keys)) {
counter_credBu++;
} else {
counter_failed++;
}
resultObj[cred + '/' + bu] = await this.#runOnBU(
methodName,
cred,
bu,
selectedType,
keys
);
counter_credBu++;
Util.startLogger(true);
}
Util.logger.info(
`:: ${lang_past} ${selectedType} on ${counter_credBu} BUs for ${cred}`
);
} else {
// execute runMethod for the entity on one BU only
if (await this.#runOnBU(methodName, cred, bu, selectedType, keys)) {
counter_credBu++;
} else {
counter_failed++;
}
resultObj[cred + '/' + bu] = await this.#runOnBU(
methodName,
cred,
bu,
selectedType,
keys
);
Util.logger.info(`:: Done`);
}
}
if (counter_credBu > 1) {
Util.logger.info(`:: ${lang_past} ${selectedType} on ${counter_credBu} BUs`);
}
return counter_failed === 0 ? true : false;
return resultObj;
}
/**
* helper for {@link Mcdev.#runMethod}
Expand All @@ -908,11 +914,11 @@ class Mcdev {
* @param {string} bu name of BU
* @param {TYPE.SupportedMetadataTypes} [type] limit execution to given metadata type
* @param {string[]} keyArr customerkey of the metadata
* @returns {Promise.<boolean>} true if all items were executed, false otherwise
* @returns {Promise.<string[]>} list of keys that were affected
*/
static async #runOnBU(methodName, cred, bu, type, keyArr) {
const properties = await config.getProperties();
let counter_failed = 0;
const resultArr = [];
const buObject = await Cli.getCredentialObject(
properties,
cred === null ? null : cred + '/' + bu,
Expand Down Expand Up @@ -941,14 +947,12 @@ class Mcdev {
}

// result will be undefined (false) if methodName is not supported for the type
if (!(await MetadataTypeInfo[type][methodName](keyArr))) {
counter_failed++;
}
resultArr.push(...(await MetadataTypeInfo[type][methodName](keyArr)));
} catch (ex) {
Util.logger.errorStack(ex, 'mcdev.' + methodName + ' failed');
}

return counter_failed === 0 ? true : false;
return resultArr;
}

/**
Expand Down
36 changes: 19 additions & 17 deletions lib/metadataTypes/Automation.js
Original file line number Diff line number Diff line change
Expand Up @@ -459,7 +459,7 @@ class Automation extends MetadataType {
* a function to start query execution via API
*
* @param {string[]} keyArr customerkey of the metadata
* @returns {Promise.<boolean>} Returns true if all items were executed successfully, otherwise false
* @returns {Promise.<string[]>} Returns list of keys that were executed
*/
static async execute(keyArr) {
const metadataMap = {};
Expand Down Expand Up @@ -510,18 +510,19 @@ class Automation extends MetadataType {
}
}
const results = await Promise.all(promiseResults);
const successCounter = results
const executedKeyArr = results
.filter(Boolean)
.filter((r) => r.OverallStatus === 'OK').length;
Util.logger.info(`Executed ${successCounter} of ${keyArr.length} items`);
return successCounter === keyArr.length;
.filter((r) => r.response.OverallStatus === 'OK')
.map((r) => r.key);
Util.logger.info(`Executed ${executedKeyArr.length} of ${keyArr.length} items`);
return executedKeyArr;
}
/**
* helper for {@link Automation.execute}
*
* @param {TYPE.AutomationMap} metadataMap map of metadata
* @param {string} key key of the metadata
* @returns {Promise.<object>} Returns the result of the API call
* @returns {Promise.<{key:string, response:object}>} metadata key and API response
*/
static async #executeItem(metadataMap, key) {
if (Util.OPTIONS.schedule) {
Expand All @@ -537,7 +538,7 @@ class Automation extends MetadataType {
* helper for {@link Automation.execute}
*
* @param {TYPE.AutomationItem} metadataEntry metadata object
* @returns {Promise.<object>} Returns the result of the API call
* @returns {Promise.<{key:string, response:object}>} metadata key and API response
*/
static async #runOnce(metadataEntry) {
return super.executeSOAP(metadataEntry);
Expand Down Expand Up @@ -565,7 +566,7 @@ class Automation extends MetadataType {
* a function to start query execution via API
*
* @param {string[]} keyArr customerkey of the metadata
* @returns {Promise.<boolean>} Returns true if all items were executed successfully, otherwise false
* @returns {Promise.<string[]>} Returns list of keys that were paused
*/
static async pause(keyArr) {
const metadataMap = {};
Expand Down Expand Up @@ -605,19 +606,20 @@ class Automation extends MetadataType {
);
}
}
const successCounter = (await Promise.all(promiseResults))
const pausedKeyArr = (await Promise.all(promiseResults))
.filter(Boolean)
.filter((r) => r.OverallStatus === 'OK').length;
.filter((r) => r.response.OverallStatus === 'OK')
.map((r) => r.key);

Util.logger.info(`Paused ${successCounter} of ${keyArr.length} items`);
return successCounter === keyArr.length;
Util.logger.info(`Paused ${pausedKeyArr.length} of ${keyArr.length} items`);
return pausedKeyArr;
}

/**
* helper for {@link Automation.pause}
*
* @param {TYPE.AutomationItem} metadata automation metadata
* @returns {Promise.<object>} schedule reponse
* @returns {Promise.<{key:string, response:object}>} metadata key and API response
*/
static async #pauseItem(metadata) {
const schedule = {};
Expand All @@ -638,7 +640,7 @@ class Automation extends MetadataType {
metadata[this.definition.nameField]
}`
);
return response;
return { key: metadata[this.definition.keyField], response };
} catch (ex) {
this._handleSOAPErrors(ex, 'pausing', metadata, false);
return null;
Expand Down Expand Up @@ -960,7 +962,7 @@ class Automation extends MetadataType {
* @param {TYPE.AutomationMap} metadataMap metadata mapped by their keyField
* @param {TYPE.AutomationMap} originalMetadataMap metadata to be updated (contains additioanl fields)
* @param {string} key current customer key
* @returns {Promise.<object>} -
* @returns {Promise.<{key:string, response:object}>} metadata key and API response
*/
static async #scheduleAutomation(metadataMap, originalMetadataMap, key) {
let response = null;
Expand Down Expand Up @@ -990,7 +992,7 @@ class Automation extends MetadataType {
schedule,
{
Interaction: {
ObjectID: metadataMap[key].id,
ObjectID: metadataMap[key][this.definition.idField],
},
},
'start',
Expand Down Expand Up @@ -1033,7 +1035,7 @@ class Automation extends MetadataType {
metadataMap[key].schedule.typeId = metadataMap[key].schedule.scheduleTypeId;
delete metadataMap[key].schedule.scheduleTypeId;
}
return response;
return { key, response };
}

/**
Expand Down
12 changes: 6 additions & 6 deletions lib/metadataTypes/MetadataType.js
Original file line number Diff line number Diff line change
Expand Up @@ -461,7 +461,7 @@ class MetadataType {
Util.logger.error(
` ☇ skipping ${this.definition.type}: execute is not supported yet for ${this.definition.type}`
);
return;
return [];
}
/**
* Abstract pause method that needs to be implemented in child metadata type
Expand All @@ -472,7 +472,7 @@ class MetadataType {
Util.logger.error(
` ☇ skipping ${this.definition.type}: pause is not supported yet for ${this.definition.type}`
);
return;
return [];
}

/**
Expand Down Expand Up @@ -1093,7 +1093,7 @@ class MetadataType {
*
* @param {string} uri REST endpoint where the POST request should be sent
* @param {string} key item key
* @returns {Promise.<string>} 'OK' if started execution successfully, otherwise - 'Error'
* @returns {Promise.<{key:string, response:string}>} metadata key and API response (OK or error)
*/
static async executeREST(uri, key) {
try {
Expand All @@ -1103,7 +1103,7 @@ class MetadataType {
} else {
throw new Error(response);
}
return response;
return { key, response };
} catch (ex) {
Util.logger.error(`Failed to execute ${this.definition.type} ${key}: ${ex.message}`);
}
Expand All @@ -1113,7 +1113,7 @@ class MetadataType {
* Used to execute a query/automation etc.
*
* @param {TYPE.MetadataTypeItem} [metadataEntry] single metadata entry
* @returns {Promise.<object>} api response
* @returns {Promise.<{key:string, response:object}>} metadata key and API response
*/
static async executeSOAP(metadataEntry) {
const soapType = this.definition.soapType || this.definition.type;
Expand All @@ -1134,7 +1134,7 @@ class MetadataType {
} else {
throw new Error(response?.OverallStatus);
}
return response;
return { key: metadataEntry[this.definition.keyField], response };
} catch (ex) {
this._handleSOAPErrors(ex, 'executing', metadataEntry);
return null;
Expand Down
10 changes: 6 additions & 4 deletions lib/metadataTypes/Query.js
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ class Query extends MetadataType {
* a function to start query execution via API
*
* @param {string[]} keyArr customerkey of the metadata
* @returns {Promise.<boolean>} Returns true if all items were executed successfully, otherwise false
* @returns {Promise.<string[]>} Returns list of keys that were executed successfully
*/
static async execute(keyArr) {
const results = [];
Expand All @@ -72,9 +72,11 @@ class Query extends MetadataType {
super.executeREST(`/automation/v1/queries/${objectId}/actions/start/`, key)
);
}
const successCounter = (await Promise.all(results)).filter((r) => r === 'OK').length;
Util.logger.info(`Executed ${successCounter} of ${keyArr.length} items`);
return successCounter === keyArr.length;
const executedKeyArr = (await Promise.all(results))
.filter((r) => r.response === 'OK')
.map((r) => r.key);
Util.logger.info(`Executed ${executedKeyArr.length} of ${keyArr.length} items`);
return executedKeyArr;
}
/**
* helper to allow us to select single metadata entries via REST
Expand Down
Loading
Loading