Asynchronous Threads in Lasso 8.5

Embed Size (px)

Citation preview

Blue Orange

Advanced Track:

Asynchronous Threads

Bil Corrylasso.pro

What Are Async Threads?

Code that executes in parallel to the currently processing page.

Why Use Async Threads?

Off-load tasksImprove response time to enduser by off-loading tasks that do not need to provide immediate feedback to the enduser

Recurring eventsLasso Scheduled Events, Email Queue, etc all are async threads.

Network-hooked serviceslp_site_restart sets up a TCP listener that receives commands to restart Lasso

Typical Lasso Request Model

Browser sends HTTP request to the web server

Web server determines the request is for Lasso and passes it to the Lasso connector

Lasso connector communicates with Lasso Server and sends the request

Lasso Server parses request, replies to Lasso connector

Lasso connector replies to web server

Web server replies to browser

Lasso Async Thread Model

Lasso page initiates new thread

Just like a normal page, the thread will run until:It terminates normally

It crashes

It is terminated for taking too long

Lasso site or server is shut down

When configured as such, some threads never terminate

Lasso Async Thread Model
(cont)

Because the request comes from Lasso itself, async threads do NOT have access to the web request info, such as client_headers, action_params, etc.

It will also not have access to the variables of the page that created it.

All file paths must be absolute from the hard disk root [include] does not work

Lasso Async Thread Model
(cont)

Output from the async thread is not available, so alternative methods must be used, such as logging to a file, a database, global variable or the Lasso console

An async thread will execute according to its priority and the load on Lasso

Basic Example

Async threads are surrounded by curly-braces and initiated using ->asasync:

[{'Hello World'}->asasync]

The above code doesn't show anything in the browser, but it does run asynchronously.

Sending Data to Async Thread

->asasync allows you to add params to pass into the async thread

[{ var('p1') = params->find('p1')->get(1)->value }->asasync(-params=array('p1'=1, 'p2'=2))]

Can also use globals (or other shared resources), but take care to correctly send the right message to the right thread and use [thread_atomic] to keep access to the global thread-safe

Template For Copying Vars To Async Thread

Creating Context

To create context within async threads, use variables to store the context of the current page (such as client_headers, file path, action_params) and use the template to pass the context into the async thread.

Two Important Settings

[Lasso_ExecutionTimeLimit]Specifies the maximum number of seconds to let this thread run. Setting it to zero will allow the thread to run continuously

[Thread_SetPriority]Can set to high or low, setting it to low (Thread_Priority_Low) gives more priority to enduser requests

Off-Loading Tasks

Improve the response time to the enduser by off-loading tasks on the page that meet the following criteria:Code for task is relatively self-contained

Task does not need to return data for the enduser to view

Task does not have to be finished by the time the concurrent page is served

Example of Off-Loading a Task

Page originally created related records and made the enduser wait:

[

loop(500);// create related recordinline(-sql=INSERT INTO mytable (id,this,that)\ VALUES (+integer($userid)+,+integer($this)+,+integer($that)+)); /loop;

'Thanks for waiting!';

]

Example of Off-Loading a Task
(cont)

Page now off-loads the related records creation and response much quicker to the enduser:

Creating a Recurring Event

Use [while(true)] to create a continuous thread

Use [Lasso_ExecutionTimeLimit(0)] to permit the thread to run continuously

Can use a global to use as a switch to shut down the thread [while(global('on'))] just be sure to use [thread_atomic] to make it thread-safe

Use [sleep] to pause the event between runsVery important! If the thread doesn't sleep, it will consume Lasso and the processor

Example of a Recurring Event

Creating a thread to watch a folder for new files to process:

[{Lasso_ExecutionTimeLimit(0); // run foreverThread_SetPriority(Thread_GetCurrentID, Thread_Priority_Low); // low prioritywhile(true);iterate(file_listdirectory('///path/from/disk/root/'),local('file'));// do something with #file/iterate;Sleep(1000*60*10); // sleep 10 minutes (in milliseconds)/while;}->asasync]

This would be placed in your LassoStartup folder.

Debugging

Async threads are tricky to debug because they do not directly output the browser. Test async code outside of ->asasync

Trap for errors

Send debug messages to an external source (file, database, etc.)

Test Outside of Async

Easiest testing method, comment out the ->asasync container and try running your code, does it work?

For recurring event threads, you'll have to limit the number of loop_counts and shorten the sleep:

[//{Lasso_ExecutionTimeLimit(0); // run foreverThread_SetPriority(Thread_GetCurrentID, Thread_Priority_Low); // low prioritywhile(true);loop_count > 10 ? loop_abort;iterate(file_listdirectory('///path/from/disk/root/'),local('file'));// do something with #file/iterate;Sleep(1000*60*2); // sleep 2 minutes (in milliseconds)/while;//}->asasync]

Trapping for Errors

Place async code within [protect] to log errors:

[{Lasso_ExecutionTimeLimit(0); // run foreverThread_SetPriority(Thread_GetCurrentID, Thread_Priority_Low); // low priority

protect;handle_error;log_critical('Folder watcher encounter an error: '+error_msg);/handle_error;

while(true);iterate(file_listdirectory('///path/from/disk/root/'),local('file'));// do something with #file/iterate;Sleep(1000*60*10); // sleep 10 minutes (in milliseconds)/while;/protect;}->asasync]

Send Debug Messages to External Source

File

Database

Lasso Errors

Lasso Console

Email

Global Var

Thank You!

Questions?