I am trying to use php-resque to queue and execute ffmpeg conversions on my server. I understand broadly how it should work, but I am having some trouble with the details and can not find any tutorials. Specifically, I don't understand where I should place my job classes, and how to give the classes to my workers and start my workers. The read me only says "Getting your application underway also includes telling the worker your job classes, by means of either an autoloader or including them."
Hopefully someone can outline the overall structure of using php-resque.
You can put your job classes where you want. It'll depend on your application structure.
How to create a job class
For example, let's suppose the class VideoConversion, used for the ffmpeg conversion.
class VideoConversion {
public function perform() {
// The code for video conversion here
}
}
In your main application, before using php-resque, let's say you have something like that
public function uploadVideo() {
// Upload and move the video to a temp folder
// Convert the video
}
And you want to enqueue the 'convert video' part. Let's just queue it to the convert queue:
public function uploadVideo() {
// Upload and move the video to a temp folder
// Let's suppose you need to convert a 'source video' to a 'destination video'
Resque::enqueue('convert', 'VideoConversion', array('origine-video.avi', 'destination-video.avi'));
}
When queuing the job, we passed the path to the source and destination video to the VideoConversion class. You can pass other argument, it'll depend on how your VideoConversion class is written.
A worker will then poll the convert queue, and execute the VideoConversion job. What the worker will do is to instantiate the VideoConversion class, and execute the perform() method.
The job arguments (array('origine-video.avi', 'destination-video.avi')), third argument when queueing the job with Resque::enqueue, will be available inside the perform() method via $this->args.
# VideoConversion.php
class VideoConversion
{
public function perform() {
// $this->args == array('origine-video.avi', 'destination-video.avi');
// Convert the video
}
Find your job classes
The VideoConversion class can be put anywhere, but you have to tell your workers where to find it.
There's multiple ways to do that
Put you jobs classes in the include_path
In your .htaccess or the apache config, add the directory containing all your job classes to the include path. Your workers will automatically find them.
Main issue with this method is that all your jobs classes must be in the same folder, and that all your job classes are available everywhere.
Tell each worker where to find your job classes
When starting the worker, use the APP_INCLUDE argument to point to the job classes 'autoloader'.
APP_INCLUDE=/path/to/autoloader.php QUEUE=convert php resque.php
The above command will start a new worker, polling the queue named convert.
We're also passing the file /path/to/autoloader.php to the worker. (see here to learn to start a worker)
Technically, the worker will include that file with include '/path/to/autoloader.php';.
You can then tell the workers how to find your job classes:
Use basic include
In the '/path/to/autoloader.php':
include /path/to/VideoConversion.php
include /path/to/anotherClass.php
...
Use an autoloader
Use php autoloader to load your job classes.
Use set_include_path()
set_include_path('path/to/job');
That way, your jobs are in the include_path just for this worker.
Closing thought
APP_INCLUDE is binded to the worker you're starting. If you're starting another worker, use APP_INCLUDE again. You can use a different file for each worker.
You can also design your job classes to execute more than one job. There's a tutorial explaining how to do that. It covers from the basic of a queue system to how to use and implement it.
If it's still not enough, take a look at resque documentation. php-resque API is exactly the same. Only difference is that Resque job classes are written in Ruby, whereas php-resque's one are in php.
Hi Please check out following tutorial on how to use resque with phalcon.
http://www.mehuldoshi.in/background-jobs-phalcon-resque/
Related
When I queue up a laravel mailable to execute 15 minutes later like so:
Mail::to($user)->later(now()->addMinutes(15), new EmailConfirm($user));
Laravel will store the EmailConfrim class in the payload column in the jobs table.
If I do a release which changes the class name EmailConfirm to ConfirmEmail I will get the following error when the code executes 15 minutes later:
prod.ERROR: Illuminate\Mail\SendQueuedMailable::handle(): The script
tried to execute a method or access a property of an incomplete object.
Please ensure that the class definition
"App\Mail\Mailables\EmailConfrim" of the object you are trying to
operate on was loaded _before_ unserialize() gets called or provide an
autoloader to load the class definition
This error is telling me that the class defined in the payload no longer exists.
A solution I've been toying with is to add an app_version_number to the laravel generated jobs table. I would then not let my laravel workers die until all the jobs are executed for that version before running:
php artisan queue:restart.
This will take me a bit of time to reliably code this as it will be specific to our prod environment. How could I go about managing this problem in a more eloquent way?
I'd temporarily leave both classes in the codebase, deploy that, and then 15 minutes (or whatever the maximum amount of time a job lingers around) later push the removal of the old one.
This answer is very similar to https://stackoverflow.com/a/54314953/2191572 BUT I would recommend maintaining the EmailConfirm via extension to avoid double-duty maintenance while your queue catches up:
class EmailConfirm extends ConfirmEmail
{
// This is just a shell/alias/wrapper/whatever for the real class
}
class ConfirmEmail
{
function __construct( $param )
{
// Maintain this class
}
}
15 minutes isn't so bad in terms of wait time but what if your queue doesn't catch up for several days and you need to change ConfirmEmail multiple times?
I'm building a website and are getting more and more classes to load. Currently I'm including every class in index.php and I also have a ajax handler where every class is included, so I basically include all my PHP files at ajax calls and on every page on the website.
Is this bad practice?
I've tried searching a bit around an have seen that there is a function called spl_autoload_register. By reading a little about it, my understanding is that it tries to include the files defined if a class is not found. But, how is that different from require_once or include_once.
Lets say I have the class underneath in a file and then use require_once('myclass.php');
class Myclass {
function myMethod {
//some code here
}
}
But, the class is not in use before I initialize it with $class = new Myclass; So what is now the difference from running
function my_autoloader($class) {
require_once('classes/' . $class . '.php');
}
spl_autoload_register('my_autoloader');
I would still have to initialize it with $class = new Myclass; when I want to use it. Are there some performance gains from either of them or is it more a preference thing?
And one more question. Should PHP be minifyed like its done with JS and CSS or is this pointless with PHP?
In 2018 the best way to work with autoloading is Composer - build for easy work and performance optimization.
4. Steps to Load Your Classes Fast and Clean
Download composer (for start even right to your project, it's up to you)
Create composer.json and tell him directories or files to load classes from:
{
"autoload": {
"classmap": "/src"
}
}
Using most open and friendly classmap option.
Rebuild cache by CLI command:
composer.phar dump
Include it in index.php
require_once __DIR__ . '/vendor/autoload.php';
And you're ready to go!
The code will technically run faster if you don't load every file on every page, but this will largely go away if you configure "OpCache", which loads all the compiled class definitions into shared memory. And at some point, you may end up with a page that needs 90% of your code loaded to do its job anyway. (This is also relevant to your question about minification - PHP is compiled on the server, so minification doesn't really help anyone.)
The other advantage with autoloading though is maintenance - when you define a new class, you don't have to add it to some master-list of includes, make sure it loads after its parent class but before its child classes, etc. Instead, you place the class definition in a meaningfully named file and directory (great for humans finding it too!) and the autoloader will find it when it's needed.
I did extensive measurements on TYPO3 (PHP) including hundreds of class files on a machine with SSD. I created a script including all available classes. Class reading was not a very expensive part compared to other issues.
I would focus on this optimisation, once all more important questions are addressed.
I've seen a lot of threads here and in other forums that asked this a lot of times, but I still see using the include function of PHP in the answers?
how can I use this function, not using totally the include function?
Thank you
how can I use this function, not using totally the include function
You cannot totally not use include and that is not the point of using autoloader as you usually need to at least include the autoloader ;). That autoloader is the regular PHP code that is being called by PHP when unknown class use is attempted in the code. It is expected to include right file to make the class known, and the code continues as you'd explicitely include right file by hand in your code. So the main benefit shows up when your code uses classed (OOP) - you do not need to care if you included the class you are about to instantiate the object of or not. You just do new Foo() or call Something::methodName() and if all is set up right it will work.
The function spl_autoload_register is used to register a callback into the autoloader queue.
The PHP autoloader is a functionality of the PHP interpreter that, when a class is not defined, calls the functions registered in the queue, one by one, asking them to load the class, until the class becomes available. It the class is still not available after all the functions were invoked, the interpreter triggers a fatal error.
The autoloader doesn't perform any magic. It is the entire responsibility of the registered functions to make the class available. Most of them use the name and namespace of the missing class to figure out the path of the file that contains the declaration of the class and include it.
That's how the thing works. There are not many ways to produce a class in PHP and, for a reusable autoloader callback, the list starts and ends with include1 (include_once, require or require_once can be used as well but they don't make any difference in this case.)
The autoloader callback itself stays in separate file (for reusability) and usually that file also contains its registration as autoloader callback (the call to spl_autoload_register). All your code have to do is to include this file once in every file that is an entry point of your application.
All things being equal, your application needs to use include at least once and once is also the maximum required number of usages for it. The autoloader callback also uses include (probably also only once) but you don't write autoloader callbacks every day. If you wrote one and you wrote it well you can reuse it. Most people never wrote an autoloader callback and they will never write one.
Using Composer is easy and if you follow the PSR-4 rules of naming the files of your project, Composer can generate an autoloader for your project that knows how to load your classes (behind the scene it uses include, of course). All you have to do is to run composer init in the root directory of your project, run composer install and write include 'vendor/autoload.php'; in the file that represents the entry-point of your application. No other uses of include are required.
1 An autoloader callback is not required to include another file to make the class available. It can generate the code of the class on the fly and eval()-uate it, but the use cases of such approach are very limited. It is used by the testing suites f.e., to generate mock classes.
I am trying to write unit tests for a file import export module.
One of my method checks that a filename passed exists.
How would this be mocked and a test written to check if the file exists or not?
Unit tests are supposed to prove that a unit of code functions correctly in complete isolation. If your test depends on the file system to function correctly in order to pass, your test is suboptimal and could be lying to you on any given test run.
Like any experiment, when you have more than one variable in play, you can't be sure of your results. For PHP code that interacts with the file system, it's best to mock the file system using a custom stream wrapper (usually vfsStream, but you can easily write your own stream wrapper if you really want to).
$noTest < $testWithFileSystemDependency < $testThatMocksFileSystem
Usually, this is accomplished by passing file paths into the methods that use them directly:
<?php
function myFunction($someFilePath) {
// do stuff
}
In this way, you can mock the file system and pass in a testable dummy path that will behave how you have mocked it to behave.
You write two tests. One creates the file and expects your method to succeed, the other ensures the file doesn't exist and expects your method to fail.
Personally I just create _files directory in the tests directory and create files there. Or in /tmp.
There is a way to mock the fs: http://www.phpunit.de/manual/current/en/test-doubles.html#test-doubles.mocking-the-filesystem but from my experience - I prefer real FS operations (in this case).
I am writing helper classes for a large project in PHP and I have written a class called Command. It is essentially an OOP wrapper around running system commands from PHP in a controlled way. It has methods like addOption() to add -a type options and addArgument() to add other arguments.
I will need to do a lot of scp'ing of files around so I will be using the Command class a lot. The calls to scp are very specific in that I need certain options used every time.
Does it make sense to extend this class and create a ScpCommand class? It seems to have an 'is a' relationship, but it is really just the same thing as the Command class with specific options every time. I don't really think I would need to override any methods with the exception of the constructor. I probably would add just class variables. It would really just be a convenience.
What makes the most sense here?
If it is just configuration, why not consider a factory which returns a Command after doing your boiler-plate configuration for you?
function getScpCommand($???)
{
$Command = new Command();
$Command->addOption(/* scp specific this */);
$Command->addArgument(/* scp specific that */);
/* etc */
$Command->addOption(/* handle your getScpCommand parameters here */)
return $Command;
}