- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
‎11-28-2023 10:02 AM
Hello everyone, I'm running into an issue with a script I've whipped up and was needing some help. We are trying to automate a system that will take duplicate users, check which user has less incidents/tasks, trigger a workflow to move those incidents/tasks, then archive the old user, and refresh the ldap twice to pull in the users new data from AD.
The issue I'm running into here is, I want to trigger this workflow for every user that needs it ran on at once, however it seems to run one workflow per user pair at a time, this workflow can take 5 minutes to complete and we've got thousands of users that will need to be hit. Any ideas on how I can get this workflow to trigger on all users that need it then wait and check to see if those workflows completed then move on like I have wrote in the script below? I've cut out most of the functions, as the workflow functions are the only ones we are interested in but you can see the step to step process in the main function.
function triggerWorkflow(fromUser, toUser) {
var workflowSysID = '8ecc9eb6db2f49d8498f7914b9961969'; // Provided sys_id for the workflow
var workflow = new Workflow();
var context = workflow.startFlow(workflowSysID, null, 'update', {
from_user: fromUser.sys_id,
to_user: toUser.sys_id
});
gs.info('Workflow triggered to migrate tasks and approvals from ' + fromUser.user_name + ' to ' + toUser.user_name);
return {context: context, pair: {user1: fromUser, user2: toUser, preferredUser: toUser}};
}
function waitForAllWorkflows(workflowContexts) {
var maxAttempts = 10; // Max wait time 15 minutes
var attempts = 0;
while (attempts < maxAttempts) {
var allComplete = true;
workflowContexts.forEach(function(contextInfo) {
var contextGR = new GlideRecord('wf_context');
if (contextGR.get(contextInfo.context) && contextGR.state != 'finished') {
allComplete = false;
}
});
if (allComplete) {
gs.info('All workflows finished for migrating tasks and approvals');
break;
}
attempts++;
gs.sleep(90000); // Sleep for 90 seconds
}
if (!allComplete) {
gs.error('Not all workflows completed within ' + maxAttempts + ' attempts');
}
}
// Main script
function main() {
gs.info('Starting AD migration script');
var duplicates = findDuplicateUsers();
var workflowContexts = [];
var toUsers = [];
var fromUsers = [];
// First, compare tasks and roles for each pair to determine which user to keep
duplicates.forEach(function(pair) {
var preferredUser = compareTasksAndRoles(pair.user1, pair.user2);
if (preferredUser) {
var fromUser = (preferredUser.sys_id === pair.user1.sys_id) ? pair.user2 : pair.user1;
var toUser = preferredUser;
// Queue up the workflow for each user pair
var context = triggerWorkflow(fromUser, toUser);
workflowContexts.push(context);
// Collect toUser and fromUser for LDAP load
if (toUser.ldap_server == 'FID') {
toUsers.push(toUser);
fromUsers.push(fromUser);
}
} else {
gs.info('No preferred user determined for pair: ' + pair.user1.user_name + ' and ' + pair.user2.user_name);
}
});
// Wait for all queued workflows to complete
waitForAllWorkflows(workflowContexts);
// LDAP load for all toUsers
toUsers.forEach(function(user) {
ldapLoadForUser(user);
});
// Wait for 60 seconds before loading fromUsers
gs.sleep(60000);
// LDAP load for all fromUsers
fromUsers.forEach(function(user) {
ldapLoadForUser(user);
});
// Proceed with archiving users
fromUsers.forEach(function(user) {
archiveUser(user);
});
gs.info('AD migration script completed');
}
// Run the main script
main();
Solved! Go to Solution.

- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
‎11-29-2023 09:40 AM
If you want to run it faster, I would put the scripts inside the foreach loop in a script action.
Create an event and then call script action using that event from your script include. That way the calls become asynchronously and wont wait for one job to finish.
Please mark this response as correct or helpful if it assisted you with your question.

- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
‎11-28-2023 10:24 AM
I think you are already running it in a loop in below script. As I understand the findDuplicateUsers() should return an array of users and you are running a loop to compareTaskRoles for each one by one. If forEach not working for you well, you can try a for loop. Also make sure findDuplicateUsers() returns all the duplicate users.
Please mark this response as correct or helpful if it assisted you with your question.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
‎11-29-2023 06:14 AM
Hi Sanjiv!
You are correct, I have it coded for a loop, the findDuplicateUsers() does return an array of users. The forEach does seem to work as it does run the workflow on each pair of users in the array. However, the issue I'm running into is it is running the workflow one at a time.
It will run the workflow on one user, then it waits for that workflow to complete before it runs the workflow on the next user. This will take over an hour with 10 pairs of users to run this one.
I was hoping that it would run the workflow on all 10 pairs of users at once, taking much much less time but could be instance intense if running on a thousand pairs. Is it not possible to trigger the workflow simultaneously?
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
‎11-29-2023 09:38 AM

- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
‎11-29-2023 09:40 AM
If you want to run it faster, I would put the scripts inside the foreach loop in a script action.
Create an event and then call script action using that event from your script include. That way the calls become asynchronously and wont wait for one job to finish.
Please mark this response as correct or helpful if it assisted you with your question.