Laravel schedule command to run for all tenants - scheduled-tasks

I have setup multitenancy in my laravel project. I use laravel 7.x.
Now, I want to make task scheduler for some commands and that commands need to run for all tenants.
I have two schedule command called in app\Console\Kernel.php.
<?php
namespace App\Console;
use Illuminate\Console\Scheduling\Schedule;
use Illuminate\Foundation\Console\Kernel as ConsoleKernel;
class Kernel extends ConsoleKernel
{
/**
* The Artisan commands provided by your application.
*
* #var array
*/
protected $commands = [
Commands\FingerPrintAttendance::class,
Commands\AttendanceLateEarlyDeduction::class,
];
/**
* Define the application's command schedule.
*
* #param \Illuminate\Console\Scheduling\Schedule $schedule
* #return void
*/
protected function schedule(Schedule $schedule)
{
$schedule->command('cmd:fingerprint')->runInBackground()->everyFiveMinutes()->appendOutputTo(storage_path().'/logs/cron_result.log');
$schedule->command('cmd:late_early_deduction')->runInBackground()->everyFiveMinutes()->appendOutputTo(storage_path().'/logs/cron_result.log');
}
/**
* Register the commands for the application.
*
* #return void
*/
protected function commands()
{
$this->load(__DIR__ . '/Commands');
require base_path('routes/console.php');
}
}
Following is the command file of cmd:fingerprint.
<?php
namespace App\Console\Commands;
use App\Models\Tenant;
use Illuminate\Console\Command;
use App\Cron\FingerPrintAttendance;
use Carbon\Carbon;
class FingerPrintAttendance extends Command
{
/**
* The name and signature of the console command.
*
* #var string
*/
protected $signature = 'cmd:fingerprint {tenant?}';
/**
* The console command description.
*
* #var string
*/
protected $description = 'Fingerprint Attendance';
/**
* Create a new command instance.
*
* #return void
*/
public function __construct()
{
parent::__construct();
}
/**
* Execute the console command.
*
* #return int
*/
public function handle()
{
if ($this->argument('tenant')) {
$this->addFingerPrintDataIntoTables(
Tenant::find($this->argument('tenant'))
);
} else {
Tenant::all()->each(
function($tenant){
return $this->addFingerPrintDataIntoTables($tenant);
}
);
}
}
public function addFingerPrintDataIntoTables($tenant)
{
$tenant->configure()->use();
$this->line('==================');
$this->line("Running Tenant #{$tenant->id} ({$tenant->customer_name}) cmd:fingerprint at " . Carbon::now());
$fingerPrintAttendance = new FingerPrintAttendance;
$fingerPrintAttendance->create($tenant);
$this->line("Ending Tenant #{$tenant->id} ({$tenant->customer_name}) cmd:fingerprint at " . Carbon::now());
}
}
Here is cmd:late_early_deduction command file.
<?php
namespace App\Console\Commands;
use App\Models\Tenant;
use Illuminate\Console\Command;
use App\Cron\AttendLateEarlyDeduction;
use Carbon\Carbon;
class AttendanceLateEarlyDeduction extends Command
{
/**
* The name and signature of the console command.
*
* #var string
*/
protected $signature = 'cmd:late_early_deduction {tenant?}';
/**
* The console command description.
*
* #var string
*/
protected $description = 'Attend Late Early Deduction';
/**
* Create a new command instance.
*
* #return void
*/
public function __construct()
{
parent::__construct();
}
/**
* Execute the console command.
*
* #return int
*/
public function handle()
{
if ($this->argument('tenant')) {
$this->lateEarlyDeduction(
Tenant::find($this->argument('tenant'))
);
} else {
Tenant::all()->each(
function($tenant){
return $this->lateEarlyDeduction($tenant);
}
);
}
}
public function lateEarlyDeduction($tenant)
{
$tenant->configure()->use();
$this->line('==================');
$this->line("Running Tenant #{$tenant->id} ({$tenant->customer_name}) cmd:late_early_deduction at " . Carbon::now());
$AutoRenewLeave = new AttendLateEarlyDeduction;
$AutoRenewLeave->create($tenant);
$this->line("Ending Tenant #{$tenant->id} ({$tenant->customer_name}) cmd:late_early_deduction at " . Carbon::now());
}
}
Then I set task scheduler on my windows 10. My development environment is windows10.
When the task is trigger, it is only run first command and the second command never run. Following is the log result.
==================
Running Tenant #1 (Test A Company) cmd:fingerprint at 2021-12-06 15:50:01
Ending Tenant #1 (Test A Company) cmd:fingerprint at 2021-12-06 15:50:01
==================
Running Tenant #2 (Test B Company) cmd:fingerprint at 2021-12-06 15:50:01
Ending Tenant #2 (Test B Company) cmd:fingerprint at 2021-12-06 15:50:01
==================
Running Tenant #3 (Test C Company) cmd:fingerprint at 2021-12-06 15:50:01
Ending Tenant #3 (Test C Company) cmd:fingerprint at 2021-12-06 15:50:01
==================
Running Tenant #1 (Test A Company) cmd:fingerprint at 2021-12-06 15:55:01
Ending Tenant #1 (Test A Company) cmd:fingerprint at 2021-12-06 15:55:01
==================
Running Tenant #2 (Test B Company) cmd:fingerprint at 2021-12-06 15:55:01
Ending Tenant #2 (Test B Company) cmd:fingerprint at 2021-12-06 15:55:01
==================
Running Tenant #3 (Test C Company) cmd:fingerprint at 2021-12-06 15:55:01
Ending Tenant #3 (Test C Company) cmd:fingerprint at 2021-12-06 15:55:01
But, when I remove runInBackground() from both command, it is run both command. In the laravel doc, it is said, when I use runInBackground(), all commands will run simultaneously. But, it is not working in my code.
The reason I want to run all commands simultaneously because, I have a lot of tenants and I don't want to wait command for each tenants.
My question is, I don't clearly understand why runInBackground() in my code doesn't work ? Is there any alternative way to run all commands without waiting for each tenants.

Related

Laravel queue throws FatalThrowableError when trying to send mails

i am trying to send a mail on a named queue (registration.user) as soon as a new user registers in my laravel (5.7) application.
i have created a mailable and a job, the job is dispatched and is working fine util the queue starts running. the job is throwing an error and the stacktrace is pushed in the failed jobs table.
the job is as following:
<?php
namespace App\Jobs;
use App\Mail\testMail;
use App\User;
use Illuminate\Bus\Queueable;
use Illuminate\Queue\SerializesModels;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;
use Illuminate\Support\Facades\Mail;
class SendRegistrationMailJob implements ShouldQueue
{
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
/**
* #var User
*/
private $user;
/**
* Create a new job instance.
*
* #param User $user
*/
public function __construct(User $user)
{
$this->user = $user;
}
/**
* Execute the job.
*
* #return void
*/
public function handle()
{
Mail::to($this->user->getAttribute('email'))->send(new testMail());
}
}
stacktrace (pastebin) (~ is where the project is)
it turned out to be a mistake I made while defining the queues, I just used the wrong syntax

laravel : get Job id after retriving

how may i get access to a job id in laravel 5.2?
regarding to this link i have tried getJobId() , but doesn't work.
ofcourse when i get a log using dd() thers is an id but probably its protected.so i cant access it.
#job: {#459
+"id": 233
+"queue": "offers"
+"payload": "{"job":"Illuminate\\Queue\\CallQueuedHandler#call","data":....}"
+"attempts": 50
+"reserved": 0
+"reserved_at": null
+"available_at": 1464615540
+"created_at": 1464615540
}
In the L5.3 you can get Job Id this way
inside your job class
<?php
namespace App\Jobs;
use App\Models\User;
use Illuminate\Bus\Queueable;
use Illuminate\Queue\SerializesModels;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Contracts\Queue\ShouldQueue;
class ParseUniversityData implements ShouldQueue
{
use InteractsWithQueue, Queueable, SerializesModels;
protected $user;
/**
* Create a new job instance.
*
* #param $userId
*/
public function __construct(User $user)
{
$this->user = $user;
}
/**
* Execute the job.
*
* #throws \Exception
* #return void
*/
public function handle()
{
$jobId = $this->job->getJobId(); // this how you can get job id
}
}
the method where you dispatch your job (in this example I'm using action method in my controller)
public function someExampleAction(Request $request)
{
$requestData = $request->all();
$job = (new someExampleJob(
$requestData['property'], $user
));
$jobId = dispatch($job); // this is variable job id
}
public function handle()
{
$jobid=$this->job->getJobId();
}
you can get the job id by this method

Unable to override Sonata User Bundle registration form

I keep getting an error while trying to override sonata registration template.
I extended Sonata User Bundle with EasyExtendsBundle, so I now have src/Application/Sonata/UserBundle.
EDIT: Symfony 2.7, Sonata Admin 2.3, Sonata User dev-master
I added a field in my User Entity
UserEntity.php
<?php
/**
* This file is part of the <name> project.
*
* (c) <yourname> <youremail>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Application\Sonata\UserBundle\Entity;
use Sonata\UserBundle\Entity\BaseUser as BaseUser;
/**
* This file has been generated by the Sonata EasyExtends bundle ( http://sonata-project.org/bundles/easy-extends )
*
* References :
* working with object : http://www.doctrine-project.org/projects/orm/2.0/docs/reference/working-with-objects/en
*
* #author <yourname> <youremail>
*/
class User extends BaseUser
{
/**
* #var integer $id
*/
protected $id;
/*
* #ORM\Column(type="string", length=255)
*
* #Assert\NotBlank(message="Please enter your name.", groups={"Registration", "Profile"})
*/
protected $age;
/**
* Get id
*
* #return integer $id
*/
public function getId()
{
return $this->id;
}
public function getAge()
{
return $this->age;
}
public function setAge($age)
{
$this->age = $age;
}
}
I then created a new RegisterForm
Application/Sonata/UserBundle/Form/Type/RegisterType.php
<?php
namespace Application\Sonata\UserBundle\Form\Type;
use FOS\UserBundle\Form\Type\RegistrationFormType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolverInterface;
class RegisterType extends RegistrationFormType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
parent::buildForm($builder, $options);
$builder
->add('age');
}
public function setDefaultOption(OptionsResolverInterface $resolver)
{
$resolver->setDefaults(array(
'validation_groups' => array('Default', 'Register')
));
}
public function getName()
{
return 'front_user_registration';
}
}
I tell sonata_user to use my form
config.yml
sonata_user:
profile:
register:
form:
type: front_user_registration
handler: sonata.user.profile.form.handler.default
name: front_user_registration_form
fos_user:
db_driver: orm # can be orm or odm
firewall_name: main
# if you change the class configuration, please also alter the sonata_user.yml file
user_class: Application\Sonata\UserBundle\Entity\User
group:
group_class: Application\Sonata\UserBundle\Entity\Group
group_manager: sonata.user.orm.group_manager
service:
user_manager: sonata.user.orm.user_manager
registration:
form:
type: front_user_registration
profile:
form:
type: fos_user_profile
handler: fos_user.profile.form.handler.default
name: fos_user_profile_form
validation_groups: [Authentication]
which I declare as a service
services.yml
user.form.register.type:
class: Application\Sonata\UserBundle\Form\Type\RegisterType
parent: fos_user.registration.form.type
tags:
- { name: form.type, alias: front_user_registration }
When I try to display the form, I get the following error :
Catchable Fatal Error: Argument 1 passed to
Sonata\UserBundle\Form\Handler\ProfileFormHandler::process() must
implement interface FOS\UserBundle\Model\UserInterface, boolean given,
called in
/Users/sylv/Sites/generajobs/vendor/sonata-project/user-bundle/Controller/RegistrationFOSUser1Controller.php
on line 49 and defined
Same goes if I add
arguments: [%fos_user.model.user.class%]
into my services.yml configuration.
Am i missing something here ?
That was a pretty stupid mistake, I had to change my "handler" line in config.yml to
handler: sonata.user.registration.form.handler.default
instead of sonata.user.profile.form.handler.default as I saw on several examples on S.O.
The two handlers process() function do not except the same parameters.

TYPO3 extbase: how to use ObjectStorage?

I'm trying to use a m:n relation, the same way as FrontEndUser is related to FrontEndUserGroup, e.g. without intermediate mm table. In my controller, I build my object, then I call $barRepository->update($barObject); to update the values of my object. However, it fails on the update function with the error:
Fatal error: Call to undefined method Cbrunet\Up\Domain\Model\Foo::getPosition() in /home/cbrunet/websites/typo3_src-6.1.1/typo3/sysext/extbase/Classes/Persistence/Generic/Backend.php on line 486
where Foo is the type of the object contained in the ObjectStorage of Bar. My understanding is that getPosition should be called on the ObjectStorage, not on the object contained into that ObjectStorage. However, I cannot figure out why this is not working in my case.
This is in TYPO3 6.1.5. Any hint would be appreciated.
The model of Bar which has a m:n relation to Foo looks like:
namespace Cbrunet\Up\Domain\Model;
class Bar extends \TYPO3\CMS\Extbase\DomainObject\AbstractEntity {
/**
* #var \TYPO3\CMS\Extbase\Persistence\ObjectStorage<\Cbrunet\Up\Domain\Model\Foo>
*/
protected $myprop;
public function __construct() {
$this->myprop = new \TYPO3\CMS\Extbase\Persistence\ObjectStorage();
}
/**
* #param \TYPO3\CMS\Extbase\Persistence\ObjectStorage $myprop
* #return void
*/
public function setMyprop(\TYPO3\CMS\Extbase\Persistence\ObjectStorage $myprop) {
$this->myprop = $myprop;
}
/**
* #param \Cbrunet\Up\Domain\Model\Foo $myprop
* #return void
*/
public function addMyprop(\Cbrunet\Up\Domain\Model\Foo $myprop) {
$this->myprop->attach($myprop);
}
/**
* #param \Cbrunet\Up\Domain\Model\Foo $myprop
* #return void
*/
public function removeMyprop(\Cbrunet\Up\Domain\Model\Foo $myprop) {
$this->myprop->detach($myprop);
}
/**
* #return \TYPO3\CMS\Extbase\Persistence\ObjectStorage
*/
public function getMyprop() {
return $this->myprop;
}
}
The relevant code in my controller looks like:
/**
* action update
*
* #return void
*/
public function updateAction() {
$args = $this->request->getArgument('myargs');
foreach ($args as $k=>$val) {
$pp = $this->barRepository->findOneByAprop($k); // another prop of Bar, not illustrated in the code above.
$listepour = new \TYPO3\CMS\Extbase\Persistence\ObjectStorage();
foreach ($val as $p) {
$ap = $this->fooRepository->findOneByUid(intval($p));
$listepour->attach($ap);
}
$pp->setMyprop($listepour);
$this->barRepository->update($pp); // error occurs here
}
$this->redirect('list');
}
Do you also have configured your TCA?
do you have an initStorageObjects-function in your domain model?
Also you can try to build these case with the extension-manager and compare the code.

Vala: D-BUS object implementing interface, error with properties

Is it possible to have a class annotated with [DBus (name = ...)] implement an interface?
Following the example at https://live.gnome.org/Vala/DBusServerSample, I am implementing a D-BUS client/server application.
One thing that I found peculiar about the example was that there was no separate interface definition. I would like to have the interface used by the client side in a separate file, and have the server class implement that interface. That way I can have the compiler tell me when I miss something.
This does not appear to work with properties though. The following definition is compatible with what I have:
/* interface.vala */
namespace org.test {
[DBus (name = "org.test.Items")]
public interface IItems : Object {
/**
* The object paths to the item instances.
*
* These objects are of type org.test.items.Item.
*/
public abstract ObjectPath[] items {
owned get;
}
/**
* The signal that is emitted when a new item is added.
*
* When this signal is emitted, the item will be available.
*
* #param id
* The object path to the item instance.
*/
public signal void item_added(ObjectPath id);
/**
* The signal that is emitted when an item is removed.
*
* When this signal is emitted, the item will be unavailable.
*
* #param id
* The object path to the item instance.
*/
public signal void item_removed(ObjectPath id);
/**
* Adds a new item.
*
* The URL will be parsed, and if it contains a valid item, it will be
* added.
*
* #param url
* The URL to the item. This should typically be the URL of the
* RSS feed.
* #return the ID of the item added, which can be used to query D-BUS
* for it
* #throws IOError if a D-BUS error occurs
*/
public abstract ObjectPath add_item(string url) throws IOError;
/**
* Removes an item.
*
* #param id
* The ID of the item to remove.
* #throws IOError if a D-BUS error occurs
*/
public abstract void remove_item(ObjectPath id) throws IOError;
}
}
/* server.vala */
using Gee;
namespace org.test {
[DBus (name = "org.test.Items")]
public class Items : DBUSObject, IItems {
private ArrayList<Item> _items;
[DBus (visible = false)]
protected override void dbus_register(DBusConnection conn,
ObjectPath path) throws IOError {
conn.register_object(path, this);
}
[DBus (visible = false)]
public Items() {
base("org.test.Items", "/org/test", "Items", true);
_items = new ArrayList<Item>();
}
[DBus (visible = false)]
~Items() {
unregister();
}
/**
* #see interface.vala::org.test.IItems.comics
*/
public ObjectPath[] items {
owned get {
ObjectPath[] result = {};
foreach (var item in _items) {
result += new ObjectPath(item.path);
}
return result;
}
}
/**
* #see interface.vala::org.test.IItems.add_comic
*/
public ObjectPath add_item(string url) throws IOError {
/* . . . */
}
/**
* #see interface.vala::org.test.IItems.remove_item
*/
public void remove_item(ObjectPath id) throws IOError {
/* . . . */
}
}
}
When I compile it, I get no error from valac, but when the generated C code is compiled, the linker complains: undefined reference to 'org_test_items_get_items'.
This function is referenced by _dbus_org_test_items_get_items, but it does not exist
It's obviously a bug. The right place to report bugs is http://bugzilla.gnome.org .