laravel scheduler in within loop - cron

I am confused in laravel queued jobs when I run the code below it processes user_id 1,2,3,4,5 but when it's running after the 1 minute mark it will try to run user_id 1,2,3,4,5 again and not continue with 6,7,8,9,10. I want to run this continuously until it finishes through all the users (meaning I don't know the timing when it will finish going through all the users). How do I go about this?
app/console/kernel
<?php
namespace App\Console;
use Illuminate\Console\Scheduling\Schedule;
use Illuminate\Foundation\Console\Kernel as ConsoleKernel;
use App\User;
use Illuminate\Support\Facades\File;
use App\Exceptions\Handler;
use App\Jobs\UserJob;
class Kernel extends ConsoleKernel
{
/**
* The Artisan commands provided by your application.
*
* #var array
*/
protected $commands = [
//
];
/**
* Define the application's command schedule.
*
* #param \Illuminate\Console\Scheduling\Schedule $schedule
* #return void
*/
protected function schedule(Schedule $schedule)
{
$users = User::where('is_status', 1)->get();
foreach( $users as $user ){
$schedule->job( new UserJob($user) )->everyMinute();
}
}
/**
* Register the commands for the application.
*
* #return void
*/
protected function commands()
{
$this->load(__DIR__.'/Commands');
require base_path('routes/console.php');
}
}
this is my cronjob which runs every minute
* * * * * cd /path-to-your-project && php artisan schedule:run >> /dev/null 2>&1

Have you tried giving it a name and add without lapping, perhaps its starting, before its finished. I was struggling with a similar problem.
->name('Process Whatever')
->withoutOverlapping()

Related

Node: Storing function names in a variable and then calling them

I am writing a node application that uses node-cron to schedule certain function to run at specific times. Currently the code for this is embedded in the main application. I want to move the configuration of scheduled tasks out to a config file, so want need to store the function names in a variable to achieve this, as the schedule tasks call out a number of functions in different modules etc.
For information the syntax to schedule a cron task is this:
cron.schedule('* * * * *', () => {functiontocall()});
The code block below shows how I am currently storing the tasks in an object and trying to schedule them with node-cron.
mycronobj = [
{scheduletime : "* * * * *", schedulefunction : 'testfunction1'},
{scheduletime : "*/5 * * * *", schedulefunction : 'testfunction2'},
{scheduletime : "*/10 * * * *", schedulefunction : 'testfunction3'},
]
for (item in mycronobj) {
cron.schedule(mycronobj[item].scheduletime, () => {mycronobj[item].schedulefunction()});
}
However this doesn't work, the scheduled functions don't run. I have tried storing the functions names as a string (as shown) or direct as
{scheduletime : "* * * * *", schedulefunction : testfunction1()}
When trying to add the scheduled function I have tried this with the following syntaxes:
mycronobj[item].schedulefunction()
mycronobj[item]schedulefunction
mycronobj[item].schedulefunction
None of which have worked for me. I have tried looking for an answer to this and I tried using eval(), but this also didn't work correctly, the outcome was that a task with first schedule ("* * * * *") was scheduled with the last function 'testfunction3' was applied, also I dont really want to use eval as I have read its not great practice and can be avoided if you know what your doing (clearly I don't).
Other options I have come across is to use Window which doesn't exist in Node or This, which I cannot get to work either.
Thanks in advance.
The reason your code isn't working is that mycronobj[item]schedulefunction is a string so is not invokable. You need to turn this string into a reference to the function with the same name.
The simplest solution to this is using eval, e.g:
for (item of mycronobj) {
cron.schedule(item.scheduletime, () =>
eval(`${item.schedulefunction}()`);
}
However this is a really bad idea, and allows for arbitrary code execution which is generally considered a very bad thing (tm).
Node gives you a slightly safer alternative to this using the vm module, which can create a limited sandbox in which your code can execute:
const vm = require("vm");
let context = vm.createContext({ foo });
for (item of mycronobj) {
cron.schedule(item.scheduletime, () =>
vm.runInContext(`${item.schedulefunction}()`, context);
}
This is only marginally better though since it can still allow arbitrary code execution, so by far the safest option is just to explicitly list exactly which functions are allowed to be called:
const commands = {
testfunction1: () => console.log("I am 1"),
testfunction2: () => console.log("I am 2"),
testfunction3 // Reference existing function
}
function testfunction3() { console.log("I am 3"); }
for (item of mycronobj) {
let func = commands[item.schedulefunction];
if (!func) { throw new Error(`Unknown command: "${item.schedulefunction}"`); }
cron.schedule(item.scheduletime, func);
}
This also has the benefit of determining during setup whether functions are valid rather than only when the cron job runs.

node-cron looping endlessly on vm

Im having a cron job set up on a gcloud compute instance.
It runs as expected on my local, but on the gcloud instance it waits until the first run and then starts to execute in an endless loop without a time gap.
async function runScript() {
...
}
cron.schedule("* */30 * * * *", () => {
runScript();
});
So I still dont know what the issue was, but I figured out a solution.
The cron-job needs to be setup in the following way:
cron.schedule("0 */30 * * * *", () => {
Now it also runs fine on the vm

SFTP Outbound Gateway Commands

I need to use more commands (cd, mkdir, rmdir) with SFTPOutboundGateway, but according to the official documentation, there is only a handful of commands available, none of the other ones I need being included. Is there a reason behind it ? Is there a(nother) way to use more commands such as cd, mkdir and rmdir ?
cd in a gateway makes no sense since it effectively would do nothing.
For commands not supported by the gateway, use the SftpRemoteFileGateway from your code in a service activator.
For commands not supported by the template, use
/**
* Execute the callback's doInSession method after obtaining a session.
* Reliably closes the session when the method exits.
*
* #param callback the SessionCallback.
* #param <T> The type returned by
* {#link SessionCallback#doInSession(org.springframework.integration.file.remote.session.Session)}.
* #return The result of the callback method.
*/
<T> T execute(SessionCallback<F, T> callback);
and
#FunctionalInterface
public interface SessionCallback {
/**
* Called within the context of a session.
* Perform some operation(s) on the session. The caller will take
* care of closing the session after this method exits.
*
* #param session The session.
* #return The result of type T.
* #throws IOException Any IOException.
*/
T doInSession(Session<F> session) throws IOException;
}
For commands not supported by Session, use
/**
* Get the underlying client library's client instance for this session.
* Returns an {#code Object} to avoid significant changes to -file, -ftp, -sftp
* modules, which would be required
* if we added another generic parameter. Implementations should narrow the
* return type.
* #return The client instance.
* #since 4.1
*/
Object getClientInstance();
#Override
public ChannelSftp getClientInstance() {
return this.channel;
}
and operate on the JSch client directly.

Which hook should be used to run a cron job in prestashop?

I am making a prestashop module in which I need to run cron job after every 20 minutes. I didn't find any hook for that. All I found is "Cron task manager" module but I don't want to use a module for that.
There is nothing like this in the Prestashop Core and module, but anyway, things can be simply done :
Call a function in module constructor, so it will be executed each time
$this->mySuperCron();
Then store a time and just check time before executing your request :
private function mySuperCron() {
$check_time = strtotime('now - 20 minutes');
if ( (int) Configuration::get('MYSUPERMODULETIMER') < (int) $check_time ) {
// Make your cron here by either calling functions here or do it with file_get_contents / curl or echo an ajax which will be executed in backoffice
Configuration::updateValue('MYSUPERMODULETIMER', (int) $check_time);
}
}
Matt's example is good, but it may not work beacause $check_time will always be higher than Configuration::get('MYSUPERMODULETIMER').
I fixed that like this:
$next = strtotime('now + 15 minutes');
if ( (int) Configuration::get('MYSUPERMODULETIMER') < (int) strtotime('now') ) {
// Make your cron here by either calling functions here or do it with file_get_contents / curl or echo an ajax which will be executed in backoffice
Configuration::updateValue('MYSUPERMODULETIMER', (int) $next);
}

How to set timeout in web-service call?

i am using
SimpleWebServiceOutboundGateway
simpleGateway.setSendTimeout(1000);
to call a web-service , but some time web-service takes more time to give response , and i want to set timeout so that it should terminate flow if response is delay.even after setSendTimeOut , it keeps on waiting . how can i achieve timeout ?
Quoting JavaDocs:
/**
* Set the timeout for sending reply Messages.
* #param sendTimeout The send timeout.
*/
public void setSendTimeout(long sendTimeout) {
this.messagingTemplate.setSendTimeout(sendTimeout);
}
as a part of the AbstractMessageProducingHandler and it is fully related to already a message to send to the output channel. That isn't a part of the SOAP protocol interaction.
You have to take a look to the options of your particular WebServiceMessageSender. For example HttpComponentsMessageSender has options like:
/**
* Sets the timeout until a connection is established. A value of 0 means <em>never</em> timeout.
*
* #param timeout the timeout value in milliseconds
* #see org.apache.http.params.HttpConnectionParams#setConnectionTimeout(org.apache.http.params.HttpParams, int)
*/
public void setConnectionTimeout(int timeout) {
if (timeout < 0) {
throw new IllegalArgumentException("timeout must be a non-negative value");
}
org.apache.http.params.HttpConnectionParams.setConnectionTimeout(getHttpClient().getParams(), timeout);
}
/**
* Set the socket read timeout for the underlying HttpClient. A value of 0 means <em>never</em> timeout.
*
* #param timeout the timeout value in milliseconds
* #see org.apache.http.params.HttpConnectionParams#setSoTimeout(org.apache.http.params.HttpParams, int)
*/
public void setReadTimeout(int timeout) {
by using configuration file,
<int-http:inbound-gateway request-channel="requestData" **reply-timeout="5000"**
supported-methods="GET" path="/{oft}/users/{userId}"
payload-expression="#pathVariables.userId" reply-channel="responseChannel" >
<int-http:header name="outputfile" expression="#pathVariables.oft"/>
</int-http:inbound-gateway>

Resources