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 Oh that's a pretty good idea, this in particular is a fix script. So would it be better to potentially make a script include that calls that workflow? Then in my fix script have it call that script include? So essentially it'll call the script include multiple times while passing the parameters over? 

So if this is a fix script, you can make a call to script action from the fix script by triggering an event.

You can google how to use script action, if you haven't used it yet. Script action is different from script include. Below link should help you.

https://servicenowspectaculars.com/what-is-servicenow-script-action/

https://docs.servicenow.com/bundle/vancouver-build-workflows/page/administer/platform-events/referen...

 

 


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

I will be testing this by tomorrow, I won't forget to accept your solution if it works tomorrow 🙂 Thank you for your help so far! Greatly appreciated!