FlowScripting SDK - archSession.endWithLogout Function returns 404

I'm trying to create a Rest API to add a flow using flowscripting SDK. Since it's an API I have to set archSession.endTerminatesProcess = false; ( otherwise API will stop as soon as the flow creation is completed) and end the archSession using endWithLogout function after my API returns the result.

When I call endWithLogout function the following error message is shown in the log
ERROR! logout failure. Error: Request Error (404): HTTP 404 Not Found (not found)

If I use the same ArchSession without ending it I'm getting the following error while publishing the flow for the second time.
Current user does not have permissions to delete this flow. ( First time it deletes the survey with same name without any issue while publishing)

Can someone suggest me the best way to make FlowScripting SDK work in a Rest API Setup?

Thanks in advance

Hi @athuldilip,

With regards to your 2nd question, you'll want to make sure that the logged in user has the architect:flow:delete permission. If your script is creating a flow and then attempting to publish it, if Architect Scripting sees a flow with the same name and type, it will attempt to delete the exiting flow so it can publish the one that your script has created in memory and it looks like that is the error you're encountering.

And then for your first question, what happens if you configure the archSession object like this inside of the function specified to ArchSession::startWithClientIdAndSecret / ArchSession::startWithAuthToken:

var enums     = scripting.enums.archEnums;
var languages = scripting.languages.archLanguages;
var logger    = scripting.services.archLogging;
var session   = scripting.environment.archSession;

// Enable verbose logging :)
logger.logNotesVerbose = true;

function scriptMain(scriptSession)  {

   // ***********************************************************
   // Configure the session to log out the current user
   // ***********************************************************
   scriptSession.endMode = enums.SESSION_END_MODES.endWithLogout;  <-- this

   // ***********************************************************
   // This is just some example / pseudo code , but gives the
   // idea of creating a flow and publishing it.
   // ***********************************************************
   return flowFactory.createFlowInboundCallAsync(flowName, flowDescription, languages.englishUnitedStates, function(archInboundCallFlow) {

     // configure the inbound call flow here

     // validate it - in this example we won't publish if there are errors or warnings
     return archInboundCallFlow.validateAsync()
    .then(function (validationResults) {

        // Does the flow have any errors or warnings?
        if (validationResults.hasErrors) {
            logger.logError('There is at least one validation error in the created flow.  Not publishing.');
        }
        else if (validationResults.hasWarnings) {
            logger.logWarning('There is at least one validation warning in the created flow.  Not publishing.');
        }
        else {
            // ok, no errors or warnings.  Lets publish it.  :) 
            return archInboundCallFlow.publishAsync();
        }

    });
   }
}

session.startWithClientIdAndSecret(<location>, scriptMain, <clientId>, <clientSecret>);

and then let scripting end the session for you instead. Scripting will wait for any outstanding promises to resolve by doing this. Calling ArchSession::endWithLogout directly will tell the session to call any session ending callback you might have registered, logout and then exit the process immediately which I'm guessing isn't what you want.

Hope this helps!

Jim

Hi Jim

Thanks a lot for the answer. I was able to solve that issue and made it work with a node.js API and right now I'm able to add any number of flows one after the other.

But however there is another issue now. When I make multiple calls to this API at the same time ( ie. I call the endpoint from a different tab before the first call completes) only the first call to the endpoint works and the rest of them doesn't work. The error that is shown in the log is

is invalid. Reason: ERROR! 'startWithAuthToken' called when the session status is in the status of 'running' which is not allowed.

In my application users should be able to add flows concurrently. So how do I achieve that?

Thanks in advance

Hi @athuldilip,

The Architect Scripting session is a singleton instance in Scripting and when code calls startWithClientIdAndSecret or startWithAuthToken, it will set the session state to running and, as you can see, we don't allow subsequent calls to either of the start methods on that session while the state is running:

if (session.status === enums.SESSION_STATUSES.running) {
  // session is busy, calls to startWithClientIdAndSecret 
  // or startWithAuthToken will fail
}

First thing is if you're looking to call one of the start methods again is you'd set up the session like this:

// ***********************************************************
// Configure the session to end but not log out
// *if* you're re-using the same auth token on
// Scripting session start calls.  Maybe?
// ***********************************************************
scriptSession.endMode = enums.SESSION_END_MODES.end;

// ***********************************************************
// We'll also tell the Scripting session singleton
// not to call process exit by setting the 
// endTerminatesProcess property to false
// ***********************************************************
scriptSession.endTerminatesProcess = false;

It sounds like Scripting is running in a web service. I'm not sure of the exact setup but I'd recommend some way in your web service to synchronize calls to the startWithAuthToken method so you don't run in to the case of multiple threads all trying to call the start methods on the singleton session at the same time and running in to the problem you're seeing.

For example, you could create a queue where inbound requests to your web service queue up a job instead of calling one the session start methods directly. Now the queue will effectively enforce one at a time calls to the start methods. Or if you have some kind of locking available on incoming request threads, you could gate calls to the start methods by threads obtaining a lock and that lock will get released once the session's state is ended.

With either approach, how can you know when a session is ending? The ArchSession::startWithAuthToken and ArchSession::startWithClientIdAndSecret calls accept a callback function you can specify as the last parameter. This is called when a session's state is ending. :slight_smile: Since you no longer have the session configured to be endWithLogout and not terminate the process, it is this callback where Scripting is letting you perform any additional cleanup you want to perform, check the session's exit code or whatever. When you specify a callback function there, execution will look like this:

> Scripting logs a note of
    setting session status to 'ended'

> Scripting logs a verbose note of 
    'calling session end callback function'

> Next Scripting invokes your callback function.

> When the callback function ends and execution returns to Scripting, 
    it will log another verbose note of:
    session end callback function execution complete.

> Then it will log a note:
    ending with exit code: <blah>

> Now is when you'd want to start up the next job that was queued
    up, release the lock to let someone else do work, etc. etc.

Since Scripting is going to write a couple more traces after invoking your callback, I would not recommend invoking calls to the startWithAuthToken or startWithClientIdAndSecret inside of the callback method itself. Technically you'll see that the state of the session is ended at that point there but with the subsequent traces it's nice to let those happen IMO. For example, you could set some kind of small timer in that method that when it expires you then either release the lock that prevented other threads from executing and/or look at the queued jobs and start up the next job or whatever but after the callback function completes.

Obviously it's up to you how you'd want to synchronize calls to the start calls on the ArchSession instance. Hope the ending callback along with the other ArchSession endMode / endTerminatesProcess property settings help.

Jim

1 Like

Thanks a lot jim for the detailed answer. Now I have a clear idea about this :grinning:

Good luck! :slight_smile:

Jim

1 Like

This topic was automatically closed 31 days after the last reply. New replies are no longer allowed.