Laravel Queue generating `illuminate:queue:restart` continuously - laravel

Ive Laravel queue running but on Database connection, here is the config:
'database' => [
'driver' => 'database',
'connection' => 'mysql',
'table' => 'jobs',
'queue' => 'default',
'retry_after' => 190,
'block_for' => 0,
]
This is how I run it:
php artisan queue:work --queue=xyz_queue > storage/logs/queue.log
On the redis CLI, this is what is happening every second:

It is normal and expected behavior. According to the documentation
Since queue workers are long-lived processes, they will not pick up changes to your code without being restarted. So, the simplest way to deploy an application using queue workers is to restart the workers during your deployment process. You may gracefully restart all of the workers by issuing the queue:restart command: php artisan queue:restart
This command will instruct all queue workers to gracefully "die" after they finish processing their current job so that no existing jobs are lost.
What queue:restart does is that setting current timestamp to the value of illuminate:queue:restart key.
When the queues are about to be consumed by the processes (php artisan queue:work) it gets that timestamp value from illuminate:queue:restart key and after the job is about to be completed it gets the value again from the same key.
It compares whether the the value before the job is processed is same as the after the job is processed.
If it is different, then it will stop long-lived process.
It is an efficient way(since Redis is super fast for this kind of scenarios) to detect whether the code is changed and should the jobs should be updated for this code change.
The reason it saves the value into the Redis, "most probably" your cache driver is Redis. If you change it to file then it will be saving in the file instead and making the get request to that file.
Here are the related methods;
protected function stopIfNecessary(WorkerOptions $options, $lastRestart, $job = null)
{
if ($this->shouldQuit) {
$this->stop();
} elseif ($this->memoryExceeded($options->memory)) {
$this->stop(12);
} elseif ($this->queueShouldRestart($lastRestart)) {
$this->stop();
} elseif ($options->stopWhenEmpty && is_null($job)) {
$this->stop();
}
}
protected function queueShouldRestart($lastRestart)
{
return $this->getTimestampOfLastQueueRestart() != $lastRestart;
}
protected function getTimestampOfLastQueueRestart()
{
if ($this->cache) {
return $this->cache->get('illuminate:queue:restart');
}
}

Related

How to Fix Client Error: file_get_contents(): in Cpanel with Laravel Project inside

i have problem when do seed in my laravel project in cpanel.
this is the errors
Client Error: file_get_contents(): https:// wrapper is disabled in the server configuration by allow_url_fopen=0
at vendor/kavist/rajaongkir/src/HttpClients/BasicClient.php:74
70▕
71▕ private function executeRequest(string $url): array
72▕ {
73▕ set_error_handler(function ($severity, $message) {
➜ 74▕ throw new BasicHttpClientException('Client Error: '.$message, $severity);
75▕ });
76▕
77▕ $rawResponse = file_get_contents($url, false, $this->context);
Please Someone help me
this is my LocationsTableSeeder.php
public function run()
{
$daftarProvinsi = RajaOngkir::provinsi()->all();
foreach ($daftarProvinsi as $provinceRow) {
Province::create([
'province_id' => $provinceRow['province_id'],
'nama' => $provinceRow['province'],
]);
$daftarKota = RajaOngkir::kota()->dariProvinsi($provinceRow['province_id'])->get();
foreach ($daftarKota as $cityRow) {
Kabupaten::create([
'province_id' => $provinceRow['province_id'],
'city_id' => $cityRow['city_id'],
'nama' => $cityRow['city_name'],
'type' => $cityRow['type'],
'postal_code' => $cityRow['postal_code'],
]);
}
}
}
It's a good practice to disable file_get_contents ability to open remote URLs (like the ones starting HTTP) on shared servers (that frequently use Cpanel) to avoid the download/injection of malicious scripts in your server.
Go to Cpanel PHP options and enable allow_url_fopen, as pointed by apokryfos, usually it's at Switch To PHP Options menu. Some providers will not allow this change via Cpanel and you might need to open a support ticket.
Usually, this option cannot be changed by ini_set or via the PHP script itself in any other way.

How to fix laravel no command 'Redis::throttle'?

I just use doc example,but get the error
exception 'Predis\ClientException' with message 'Command 'THROTTLE' is not a registered Redis command.
I havce search a lot about redis command,but nothing about throttle.
public function handle()
{
// Allow only 2 emails every 1 second
Redis::throttle('my-mailtrap')->allow(2)->every(1)->then(function () {
$recipient = 'steven#example.com';
Mail::to($recipient)->send(new OrderShipped($this->order));
Log::info('Emailed order ' . $this->order->id);
}, function () {
// Could not obtain lock; this job will be re-queued
return $this->release(2);
});
}
What should I do?Any help,Thanks!
throttle method is defined in Illuminate/Redis/Connections/PredisConnection.
The Redis facade allows for you to get the connection using
Redis::connection()
->throttle('my-mailtrap')
//...
http://laravel.com/docs/5.8/redis

Laravel forge Redis setup Undefined index: queue on RedisConnector

I am running Laravel 5.7 on Forge. Things are working well. I have two simple jobs that run. One when a user logs in and one when users want to download a large file.
In my local they both work great. Once deployed on forge they both fail with the same exception:
ErrorException: Undefined index: queue in /home/forge/SITE/vendor/laravel/framework/src/Illuminate/Queue/Connectors/RedisConnector.php:46
The stack trace points right back to the two lines where I call dispatch();
My setup is default for Redis. I have not changed my env or anything else related to a normal redis setup.
Both my local and my prod forge site have:
REDIS_HOST=127.0.0.1
REDIS_PASSWORD=null
REDIS_PORT=6379
I have no idea why this would happen only in my Forge setup. TIA
--
After continueing to look into this, when I run it locally I have run php artisan queue:work
I tested running this after ssh'ing into my forge server and got this:
ErrorException : Undefined index: queue
at /home/forge/members.spaceangels.com/vendor/laravel/framework/src/Illuminate/Queue/Connectors/RedisConnector.php:46
42| */
43| public function connect(array $config)
44| {
45| return new RedisQueue(
46| $this->redis, $config['queue'],
47| $config['connection'] ?? $this->connection,
48| $config['retry_after'] ?? 60,
49| $config['block_for'] ?? null
50| );
Exception trace:
1 Illuminate\Foundation\Bootstrap\HandleExceptions::handleError("Undefined index: queue", "/home/forge/members.spaceangels.com/vendor/laravel/framework/src/Illuminate/Queue/Connectors/RedisConnector.php", [])
/home/forge/members.spaceangels.com/vendor/laravel/framework/src/Illuminate/Queue/Connectors/RedisConnector.php:46
2 Illuminate\Queue\Connectors\RedisConnector::connect(["redis"])
/home/forge/members.spaceangels.com/vendor/laravel/framework/src/Illuminate/Queue/QueueManager.php:157
Please use the argument -v to see more details.
my config/queue.php setting:
'redis' => [
'driver' => 'redis',
'connection' => 'default',
'queue' => 'default',
'retry_after' => 90,
'block_for' => null,
],
I feel like this is something missing between my config and how forge enables Redis
Well, it seems like your .env file is missing:
CACHE_DRIVER=redis

CakePHP 3.x ORM doesn't use cache data when key exists

CakePHP 3.5.13 with Redis configured as the cache engine:
// config/app.php
'Cache' => [
'default' => [
'className' => 'Redis',
'duration' => '+1 hours',
'prefix' => 'cake_redis_',
'host' => '127.0.0.1',
'port' => 6379,
],
];
I have a table with ~260,000 rows in it and a corresponding Table class called SubstancesTable.php. I'm attempting to get the first 5000 rows and then cache the results, so that on subsequent queries, the cached results are used rather than executing the same query:
// Controller method
public function test()
{
$this->autoRender = false;
$Substances = TableRegistry::get('Substances');
// Get 5000 rows from table
$query = $Substances->find('list')->limit(5000);
// Write to cache
$query->cache('test_cache_key');
// Output the results
debug($query->toArray());
}
When I login to Redis (running redis-cli through ssh on my webserver), I can see a key has been generated with the name "test_cache_key":
127.0.0.1:6379> KEYS *
1) "cake_redis_test_cache_key"
I can also see the serialized data in there using GET cake_redis_test_cache_key.
When I execute the above in a browser, there is virtually no difference in the time taken between the cache not existing, and after the cache has been created. I have deleted the cached key in Redis using DEL cake_redis_test_cache_key and confirmed it has gone by listing the keys in Redis (KEYS *)
Clearly Cake isn't reading from the cache in this situation, even though it's writing to it without problems. Why is this happening?
The documentation (https://book.cakephp.org/3.0/en/orm/query-builder.html#caching-query-results) is not clear. Do I need to do something else to get it to read the results from the cache? I've also read CakePHP 3: find() with cache but can't see what's being done differently to what I'm doing above.

What happens with the QueueWorker when TTR ran out?

This relates to laravel 5.3, beanstalk, ttr and timeout working with Queue's and QueueWorkers. TTR: https://github.com/kr/beanstalkd/wiki/faq
If I understand correctly a job from the Queue gets the state reserved when a QueueWorker is picking it. This job state will be changed back to ready when the ttr runs out. But what happens with the QueueWorker?
Let's say the QueueWorker has a timeout set to 600 by the following command:
php artisan queue:work --tries=1 --timeout=600 --sleep=0
ttr is, as default, set to 60 seconds.
During the job a request is done to another site and it takes 120 seconds till response. After 60 seconds the job is set back to the ready state because the TTR. Will the QueueWorker keep working on the job till response has been received, maximum of 600 seconds? Or will the QueueWorker stop working on the job when TTR has been reached?
Actually, the QueueWorker will run till the job is completed. When you run queue worker without the daemon flag, it will run the code below:
return $this->worker->pop(
$connection, $queue, $delay,
$this->option('sleep'), $this->option('tries')
);
Reference:
https://github.com/laravel/framework/blob/5.2/src/Illuminate/Queue/Console/WorkCommand.php#L123
What this code does is pop its job from the queue and fire that job as a command:
public function process($connection, Job $job, $maxTries = 0, $delay = 0)
{
if ($maxTries > 0 && $job->attempts() > $maxTries) {
return $this->logFailedJob($connection, $job);
}
try {
$job->fire();
$this->raiseAfterJobEvent($connection, $job);
return ['job' => $job, 'failed' => false];
} catch (Exception $e) {
if (! $job->isDeleted()) {
$job->release($delay);
}
throw $e;
} catch (Throwable $e) {
if (! $job->isDeleted()) {
$job->release($delay);
}
throw $e;
}
}
Reference:
https://github.com/laravel/framework/blob/5.2/src/Illuminate/Queue/Worker.php#L213
Digging in the source for more information:
https://github.com/laravel/framework/tree/5.2/src/Illuminate/Queue

Resources