Blog

How to Use Low Priority Tasks in JS and Java CodeRunners

by on April 25, 2019

Low Priority Tasks in JS and Java CodeRunner

Today we are going to talk about a very valuable feature available for Managed Backendless and Backendless Pro users called Low Priority Tasks. In this article, we’ll look at how it works and what is it best used for.

Backendless custom business logic (Cloud Code custom event handlers and custom API services) tasks are put into a single queue and executed by a dedicated service called CodeRunner. In Backendless Cloud, these tasks do not have any kind of priority and are executed according to the task’s position in the queue. But there are cases when the CodeRunner queue is spammed with “heavy” requests which take 10 or even 20 seconds to execute, i.e. getting hundreds or even thousands of records with multiple relations, utility requests to delete thousands of outdated records in a table, etc.

In such a scenario, all subsequent requests with higher priority such as the application’s core logic will be left hanging until all tasks in the queue finish. To resolve these problems, we will introduce you to Low Priority Tasks.

The main purpose of this feature is to keep a particular percentage of available “workers” inactive so tasks with higher priority can be executed while other “workers” are working on low priority tasks. Whenever tasks with higher priority appear in the queue, they are executed right away. Low priority tasks are executed only in the event that there are no tasks in the “main” queue left.

How it works

Configuration

Please keep in mind that this feature works only in the Managed and Pro versions of Backendless. To get started, we’ll need to do the following:

Add the following line to coderunner.json config if you are using JavaScript cloud code:

"workers": {
    "cache": {
      "limit": 20
    },
    "concurrent": 20,
    "heartbeat": {
      "interval": 5,
      "timeout": 10
    },
    "lowPriorityThreshold": 0.8
  },

Here, “limit” and “concurrent”: <VALUE> indicate the number of “workers”; in other words, the number of tasks CodeRunner can simultaneously work on. “lowPriorityThreshold” = 0.8 means that low priority executions can take only 80% of the worker pool. The rest will be reserved ONLY for the main queue. Note that if the queue of tasks includes only high priority ones, 100% of the worker pool can be used.

Add the following line to runner.properties config if you are using Java cloud code:

low_priority_queue.workers_threshold = 0.8
system.pool.core = 20

If you have your CodeRunner running already, you’ll need to restart it after changing the config file (runner.properties or coderunner.json).

That is all we need to do to enable support of low priority tasks on the server-side. Now I’m going to show how CodeRunner differentiates low priority tasks and tasks for the main queue. In order to request a low priority invocation, we need to specify this in a client-side request to a custom service and/or handler.

Invocation with Priority “LOW”

Here are examples of how it can be done for a custom event handler called ‘myCustomEvent’ :

REST

POST http://<YOUR DOMAIN>/<APP ID>/<REST API Key>/servercode/events/myCustomEvent

HTTP header:
   bl-execution-type: async-low-priority

BODY:
{"yourArgument":"value"}

Android

HashMap args = new HashMap();
args.put( "weather", "sunny" );
Backendless.Events.dispatch( "myCustomEvent", args, ExecutionType.ASYNC_LOW_PRIORITY );

JS

Backendless.Events.dispatch( "myCustomEvent", args, Backendless.BL.ExecutionTypes.ASYNC_LOW_PRIORITY );

ExecutionType  is an enumeration consisting of ASYNC , SYNC  and ASYNC_LOW_PRIORITYASYNC  schedules invocation to the main queue and ASYNC_LOW_PRIORITY  will schedule the task to low priority queue. The same will hold true for any service’s method.

Here are examples of how to invoke a method called testMethod  in service called testService  in low-priority mode:

REST

POST http://<YOUR DOMAIN>/<APP ID>/<REST API Key>/services/testService/testMethod

HTTP header:
   bl-execution-type: async-low-priority

BODY:
{"yourArgument":"value"}

Android

HashMap args = new HashMap();
args.put( "weather", "sunny" );
Backendless.CustomService.invoke( "testService", "testMethod", args, ExecutionType.ASYNC_LOW_PRIORITY);

JS

Backendless.CustomServices.invoke('testService','testMethod', Backendless.BL.ExecutionTypes.ASYNC_LOW_PRIORITY)

Keeping all these signatures in mind is not necessary because the client code required for invocation of your service can be auto-generated by Backendless for Android (Java), JS, Obj-C, and Swift:

Low Priority Tasks in JS and Java CodeRunner

All you’ll need to do is to add an additional argument – ExecutionType.ASYNC or ExecutionType.ASYNC_LOW_PRIORITY to the method’s signature.

Example

Let’s see how this works on an example of a custom event handler. What you’ll need to do is:

  1. We’ll need to Create and deploy custom JS handler with the following code:
Backendless.ServerCode.customEvent('myCustomEvent', async function(req) {
  console.log('my custom event handler')

  return new Promise(resolve => setTimeout(resolve, 1000))
});

As you can see it’s very straightforward  – just waiting for 1 second before printing a log. This timeout is required to generate a live queue of tasks, so we could demonstrate the difference between how the CodeRunner service approaches low priority tasks and basic ASYNC tasks.

  1. I prepared a JS script that monitors the queue of low priority tasks, the queue of main tasks, and the current state of available workers.
    First, I’ll call myCustomEvent handler in low priority mode 300 times. As a result, 16 (80% of 20) workers will be working on that task’s execution. Second, I’ll call the same handler but for the main queue (ExecutionType.ASYNC). When these tasks get to queue, the low priority tasks stop execution until there are no ASYNC tasks left in the queue. Here is a visual demonstration of how it works:

Low priority tasks executing with CodeRunner

We hope this feature will speed up your application and make you forget about timeouts in business logic! If you have further questions, don’t hesitate to reach out to us on the support forum or our Slack channel.

Useful links:
Cloud Code for Java – https://backendless.com/docs/bl-java/index.html

Cloud Code for JS – https://backendless.com/docs/bl-js/index.html

JS script demonstrating how low priority tasks are handled (don’t forget to replace HOST, AppID and API key with your credentials): https://drive.google.com/file/d/1pfYHUqHgPJXmZTjec6Fn1JcAUXNsar1t/view?usp=sharing