How to delay without stop - php

<?php
namespace Test;
class A {
public function T(){
sleep(1000);
//Code not possible for thread to perform
}
}
?>
But, When call method T, Program Stucking occured.
how can i delay without stucking?
i can use thread but, the code that I wrote with using API doesn't accept Thread.
sorry for bad English, and thanks

You have to create a new \pocketmine\Thread object for long running task, as mentioned in the documentation of the AsyncTask class:
[...]
* An AsyncTask does not have its own thread. It is queued into an AsyncPool and executed if there is an async worker
* with no AsyncTask running. Therefore, an AsyncTask SHOULD NOT execute for more than a few seconds. For tasks that
* run for a long time or infinitely, start another {#link \pocketmine\Thread} instead.
[...]
So it looks like the API support threads, so use them.

I have made a library that explicitly allows you to use a sleep-alike syntax based on tasks, using PHP generators: https://github.com/SOF3/pmutil/blob/master/src/sofe/pmutil/SleepyTask.php
Example use: https://gist.github.com/SOF3/36813c09f086de7307dd9dab908f4aa4
Note that the code targets a really old API (3.0.0-ALPHA10), so you have to update it before using.

Related

How can you handle class name changes in laravel queues?

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?

Multithreading in PHP?

I am coming from java background which has rich threading framework. In the past , I kept hearing that PHP does not support threading.
But below code from this site creates the thread in PHP in almost same way as java does.
So what's the difference ?
<?php
class ChildThread extends Thread {
public $data;
public function run() {
/* Do some work */
$this->data = 'result';
}
}
$thread = new ChildThread();
Also I read below statements on google
Avoid the idea of running paralell tasks (threads or processes) in
PHP. It has some modules for this purpose, but they are not available
on every platform and are not part of the PHP core, so the chances for
you to be able to use them are very low.
This way wil not will work in every single environment
So My question above way of creating thread thread does not work on every platform(which platform for example) ? Does it mean there is no true
way of creating thread that works on all environment ?

PHP -- Will the instance get created if the constructor has a long running job?

I got a class constructor which kicks off a curl_multi and goes about downloading certain number of files and takes a few seconds to complete. Will the object instance be created only after the constructor is done with the downloads?
class Downloader {
public function __construct($download_links_array,...) {
$handle = new curl_multi_init();
...
}
}
$downloader = new Downloader( array($download_links) );
$downloader->get_item(10); // Will this be too early to call?
So the question is will the instance get created before invoking get_item() or it will the control only be returned after the instance (ie, all the downloads are completed) is created?
Thanks!
It depends. How do you download your files? synchronously or not? If you do it synchronously, then your call of the function which executes the download will not return until the files are downloaded. Otherwise, the function will return immediately and your files will be downloaded in the background (usually you need to supply a callback function that handles the event of finishing the downloads while working asynchronously).
Moreover, an object is not considered ready as long as the constructor has not finished its work. That means, that the new call won't return until the object is ready, i.e. the constructor is finished.
Combining the two sections above teaches us that if the downloading is done synchronously, the object will be ready only after downloads are finished, thus the call of get_item will be executed only after all of the downloads are finished. However, if you download your files asynchronously, then the object will be ready regardless of when your downloads are finished, and the call for get_item may be executed even before your downloads are finished.
You can read this answer which might bring you better understanding on the difference between the two (as they discuss a very simple example of executing a query which might take a long time instead of downloading files).
Note: Constructors really do not need to perform such tasks.

Function Structure vs Unit Testing Private Function

I have a function, which someone else wrote, that creates a cURL wrapper object inside the function. Simplified version below
public function getCodes()
{
//do some stufff
$communicator = new Communicator();
$result = $communicator->call($this->API_KEY);
//do some stuff with $result
}
I was tasked with learning PHPUnit and writing tests for this type of code. In doing so I found that it's really hard to test a function like this when the object is created inside of the function and also that tests shouldn't require any outside communication to work.
We wanted to push our tests to git as many projects do but we didn't want to accidentally or intentionally push our API credentials to git.
So my solution was to keep getCodes() public but make it a wrapper for a private function that accepts a Communicator object as a parameter. Then I could test the private method with a mock Communicator object.
But this would mean that getCodes is never tested (my boss wants 100% code coverage) and I also read that you shouldn't be writing tests for private functions in most circumstances.
So my question is basically, how do I write a test for a function like this with an API call.
I would really suggest rewriting the code to inject the Communicator object via constructor.
If you already see there is a big issue with writing tests for something it is a very strong signal to re-thing the current implementation.
Another thing is that you shouldn't test your privates. Sebastian Bergmann wrote a post on his blog about this some time ago and the conclusion is - it is possible just not good (https://sebastian-bergmann.de/archives/881-Testing-Your-Privates.html).
Completely different thing is that I think your tests shouldn't go outside of the boundaries of your system. That is - mock everything that connects to outside systems. Such tests may fail for various of reasons non of witch are valid from the sole perspective of running tests.
You also mentioned coverage. Unfortunately this is something where, I hope, everyone will agree - you cannot have it the moment you start using native PHP resources (with some small exception like FS). You have to understand that things like curl, ssh, ftp and so on cannot be unit tested.

What is the proper way to setup and use php-resque?

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/

Categories