How to trigger workflow multiple times within Fix Script for multiple records

Jorogumo4
Tera Expert

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();

 

1 ACCEPTED SOLUTION

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.

View solution in original post

7 REPLIES 7

SanjivMeher
Kilo Patron
Kilo Patron

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.

 

SanjivMeher_0-1701195772525.png

 


Please mark this response as correct or helpful if it assisted you with your question.

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? 

@SanjivMeher , here's a screenshot to example the behavior mentioned in my previous comment

Jorogumo4_1-1701279500697.png

 

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.