Loopback 4: Scheduled cron example using Loopback 4 - loopbackjs

As I am very new with loopback 4 and Typescript, knowing that we have to use custom booter to implement schedule tasks like Cron.
I require a code snippet which does that, i.e A custom booter class that implements Booter phases of configure, discover and load to Run a Cron

I am not sure this is the way to do it, but this is working for me.
https://loopback.io/doc/en/lb4/Booting-an-Application.html#bootcomponent
Start with creating a component inside the project folder. I created src\components\cron.component.ts
import { Component } from "#loopback/core";
import { CronJob, CronCommand } from "cron"
export class CronJobsComponent implements Component {
private cj: CronJob;
constructor(){
this.start()
}
async start(){
this.cj = new CronJob('* * * * * *', this.showMessage)
this.cj.start();
}
showMessage:CronCommand = async () => {
console.log("inside cron jobs")
}
}
Next import our component in the application.ts file
import { CronJobsComponent } from './components'
and register our new component inside the constructor
this.component(CronJobsComponent);
The corn job starts on application boot.
I used https://www.npmjs.com/package/cron and https://www.npmjs.com/package/#types/cron
Hope this helps you.

You can always create a cron endpoint.
http://localhost:3000/cron
You could then add a curl command to your crontab.
curl http://localhost:3000/cron
This method is a great way to handle seperation of concerns. If your api is a microservice running on kubernetes, you could call the cron endpoint using the Cron resource.
Just make sure that the endpoint is secure if your application is public.

Related

Select the service you wish to carry out a Google Task Handler

I am relatively new to Google Cloud Platform, and I am able to create app services, and manage databases. I am attempting to create a handler within Google Cloud Tasks (similar to the NodeJS sample found in this documentation.
However, the documentation fails to clearly address how to connect the deployed service with what is requesting. Necessity requires that I have more than one service in my project (one in Node for managing rest, and another in Python for managing geospatial data as asynchronous tasks).
My question: When running multiple services, how does Google Cloud Tasks know which service to direct the task towards?
Screenshot below as proof that I am able to request tasks to a queue.
When using App Engine routing for your tasks it will route it to the "default" service. However, you can overwrite this by defining AppEngineRouting, select your service, instance and version, the AppEngineHttpRequest field.
The sample shows a task routed to the default service's /log_payload endpoint.
const task = {
appEngineHttpRequest: {
httpMethod: 'POST',
relativeUri: '/log_payload',
},
};
You can update this to:
const task = {
appEngineHttpRequest: {
httpMethod: 'POST',
relativeUri: '/log_payload',
appEngineRouting: {
service: 'non-default-service'
}
},
};
Learn more about configuring routes.
I wonder which "services" you are talking about, because it always is the current service. These HTTP requests are basically being dispatched by HTTP headers HTTP_X_APPENGINE_QUEUENAME and HTTP_X_APPENGINE_TASKNAME... as you have them in the screenshot with sample-tasks and some random numbers. If you want to task other services, these will have to have their own task queue(s).

VS2017 Azure WebJob Extensions - How do I deploy a TimerTrigger WebJob?

I have the following WebJob project where I'm trying to deploy a TimerTrigger WebJob function, however I cannot get it to run on a scheduled basis when deploying it via "Publish As Azure WebJob..." in Visual Studio 2017.
Program.cs
class Program
{
static void Main()
{
var config = new JobHostConfiguration();
if (config.IsDevelopment)
{
config.UseDevelopmentSettings();
}
config.UseTimers();
var host = new JobHost(config);
host.RunAndBlock();
}
}
Functions.cs
public class Functions
{
public static async Task ProcessAsync([TimerTrigger("0 */3 * * * *")] TimerInfo timerInfo, TextWriter log)
{
...
}
}
webjob-publish-settings.json
{
"$schema": "http://schemastore.org/schemas/json/webjob-publish-settings.json",
"webJobName": "TestWebJob",
"runMode": "OnDemand"
}
Settings.job
{ "schedule": "0 */3 * * * *" }
The documentation for this is pretty non-existent, and it's baffling to why Azure supports Scheduled CRON TimerTrigger's but doesn't actually include them as an option when deploying.
Is this possible?
If you have created a schedule webjob manually, I think you probably have found it will generate a settings.job to set the schedule.Then the SCHEDULE in the portal read the schedule and show it. And if you deploy a TimerTrigger webjob with VS2017, it won't generate this file because you have define the TimerTrigger function.
Then I did some tests to show it.Firstly I create a webjob with TimerTrigger and deploy it, it will show same result just like yours with n/a SCHEDULE. Then I kill the webjob process and upload a settings.job then refresh(not the refresh in in the portal) the page, then the SCHEDULE change to CRON expression. And if you delete the file, it will change back.
As for the log, in my opinion it's also caused by the settings.job, if you have this file it will trigger this webjob every x minutes, and if you don't have it will trigger the function every x minutes in a webjob.
If you still have questions, please let me know.
It seems that the above code is working. However, it runs completely differently to how you would imagine if you're familiar with running "Scheduled" WebJobs manually.
If you were to run them manually, you would usually see the Schedule at the top level, along with the Status updating every x minutes, etc:
and you would also see the logs update at parent level, like so:
However, when deploying it using the above method via Visual Studio 2017, you only ever get the WebJob running once for the duration of it's lifetime. As a result you would only ever get one parent log in the logs list too.
Though if you click into this, you will see individual logs for each scheduled function log:
Hopefully this will make sense for other people who are looking into setting up WebJobs :)

How to set Continuous Webjob as Singleton?

I've seen some guidance around using settings.job for this but it's not working - in the console I see:
WebJob singleton setting is False
How can I go about preventing scale-outs from running multiple instances of my webjob?
As far as I know, to set a continuous job as singleton, we could create a file called settings.job with the content: { "is_singleton": true } and put it at the root of the WebJob directory.
And we could get continuous job settings to make sure whether it is singleton.
GET /api/continuouswebjobs/{job name}/settings
in the console I see:
WebJob singleton setting is False
Please use Kudu tool to check whether the settings.job is existing at the root of the WebJob directory and the actual value of “is_singleton” property.
If you can use the WebJobs SDK, I prefer to use the Singleton attribute.
https://learn.microsoft.com/en-us/azure/app-service/webjobs-sdk-how-to#singleton-attribute
[Singleton]
public static async Task ProcessImage([BlobTrigger("images")] Stream image)
{
// Process the image.
}
If you have something like a ServiceBus trigger you should use [Singleton(Mode = SingletonMode.Listener)] in combination with the other host settings.

Locking console batch process in Yii2

I'm developing a web application based on the Yii2 framework.
Every 12 hours the application needs to run a batch process to update some DB tables and it takes 5-10 seconds. In order to do that, I created a console command (say ./yii dummy/index) that is called by the windows task scheduler using a .bat script. However, while running the task, the application Web GUI is still running. Does Yii2 autonomously stops any web interaction while executing the task or should I lock manually the system to avoid any inconsistency issues? If is that so, how can I stop web interaction while executing the console process and restart them when it's completed?
Console and web apps are completely autonomous. Running a console command will in no way prevent the web app from running.
The easiest way to solve this problem would be to set some kind of mutex in your console command and check for it in your web application. For that, Yii2 offers a variety of mutex classes all derived from yii\mutex\Mutex.
You add a mutex to your console and web app configs:
'mutex' => [
'class' => 'yii\mutex\MysqlMutex',
],
In your console command you need to acquire the mutex (allow it to wait for a few seconds):
$mutexResult = Yii::$app->mutex->acquire('example-mutex', 10);
if ($mutexResult) {
echo 'Could not acquire lock'.PHP_EOL;
Yii::$app->end();
}
And when you're done, release it:
Yii::$app->mutex->release('example-mutex');
In your web application you then check if the mutex is available. I believe current application template will generate controllers that extend the yii\web\Controller class. You should create your own base controller class that extends yii\web\Controller and define its beforeAction method:
class BaseController extends \yii\web\Controller
{
public function beforeAction($action)
{
$mutexResult = Yii::$app->mutex->acquire('example-mutex', 20);
if ($mutexResult) {
Yii::$app->mutex->release('example-mutex');
} else {
echo 'Console app is running';
return false;
}
return parent::beforeAction($action);
}
}
Then extend all your web application's controllers from this BaseController class.
This way Yii will check for this flag before any action is executed.

SharePoint Farm Wide Custom Timer Job

I am trying to develop a custom timer job that is scoped at farm level rather than a web application level. Can someone provide me with some sample code. Also when I look at the constructor of SPJobDefinition I see the following constructor with the following parameters.
protected SPJobDefinition(string name, SPService service, SPServer server, SPJobLockType lockType);
I assume this is what I have to use to create a farm level job definition. What is the SPService used for?
You can pass any farm level service as parent, and locktype as None. while provisioning timer job. This will make your timer job to run on all servers where the service is running and your job will be run once per server.
Example
Job = new TestJob1("mytimerjob",
"Instance of service", null, SPJobLockType.None);
Instance of service can be : timer service, sharepoint foundation web application service"