Asynchronous server-side scripting
Sometimes, server-side scripts can take a long time for execution (e.g., crawling many files, writing many entities, communicating with external services) so that naively executing them, e.g., from the web interface may result in connection timeouts. In such cases, we might want to execute these processes asynchronously so that the script simply runs in the background for as long as it takes.
While LinkAhead doesn’t support asynchronous server-side scripts per se (yet), in this tutorial, we will use LinkAhead’s server-side scripting API to effectively achieve the same thing. It is meant for users who are already familiar with the server-side scripting infrastructure and know how to write and execute (Python) server-side scripts.
For simplicity, let’s consider the following: We have a very simple
script that takes a name
and a description
and inserts a new
RecordType if it doesn’t exist already. To emulate long execution
times, we may make the script sleep for a few seconds. In total, this
script may look like the following.
#!/usr/bin/env python3
from time import sleep
import linkahead as db
from caosadvancedtools.serverside import helper
def main():
parser = helper.get_argument_parser()
parser.add_argument("name", help="Name of the new RT")
parser.add_argument("description", help="Description of the new RT")
sleep(30)
args = parser.parse_args()
db.configure_connection(auth_token=args.auth_token)
num_rt = db.execute_query(f"COUNT RECORDTYPE WITH name='{args.name}'")
if num_rt > 0:
return
db.RecordType(name=args.name, description=args.description).insert()
if __name__ == "__main__":
main()
This script can, e.g., be called from the web interface as explained in the server-side scripting documentation, will run for at least 30 seconds, and then insert a new RecordType if we don’t have one with the same name already. Note that this is more of a sketch rather than production code, e.g., it is missing any kind of user feedback regarding successful execution or possible errors.
While 30 seconds execution time usually don’t cause any timeouts, it
is already a rather long time to wait in the browser without any
feedback, so we want to call this script in an asynchronous way and
then inform the user that it was called asynchronously and is running
in the background. To achieve this, we create a second Python script
that calls the above one. Assuming the above script was called
create_rt.py
, the calling script could look as follows.
#!/usr/bin/env python3
import os
import subprocess
import sys
from pathlib import Path
import linkahead as db
from caosadvancedtools.serverside import helper
def main():
parser = helper.get_argument_parser()
parser.add_argument("name", help="Name of the new RT")
parser.add_argument("description", help="Description of the new RT")
args = parser.parse_args()
# log-in with the provided credentials and save auth token for further log-in
db.configure_connection(auth_token=args.auth_token)
db.Info()
conn = db.get_connection()
auth_token = conn._authenticator.auth_token
# Provide the absolute path to the other script
exec_path = Path(__file__).parent / "create_rt.py"
cmds = [
str(exec_path),
"--auth-token",
auth_token,
args.filename,
args.name,
args.description
]
# We can use the environment of the SSS setup, but we need to reset the HOME
# so that the called script can find e.g., the pylinkahead.ini config file.
myenv = os.environ.copy()
myenv["HOME"] = str(Path(__file__).parent.parent / "home")
# We also need to provide a cwd, otherwise Popen will default to cwd=None
p = subprocess.Popen(cmds, start_new_session=True, env=myenv, cwd=str(exec_path.parent))
print(
f"Your job to create RT '{args.name}' asynchronously was started successfully "
"and is running in the background."
)
if __name__ == "__main__":
main()
There are a few things to mention about the calling script:
We use the authentication token provided by the server-side scripting environment to authenticate, then we copy the resulting login token and provide it to the called script which can then use this token to authenticate with the same permissions as the calling script.
We reproduce the general environment of the server-side scripting API, but we reset the
HOME
variable since the SSS API uses a temporary directory.We need to additionally specify a current working directory since
Popen
’s default toNone
will result in errors when importing LinkAhead.