Say my set_time_limit is set to 30 seconds and can't be changed. I have an email script in php that will run longer than 30 seconds on 1 cron job (I haven't reached that time mark yet.) What happens on timeout after 30 seconds? Will the script stop then continue?
If not, I would like to record the elapsed time from the beginning of my script's loop until it reaches 30 seconds and pause the process then continue.
What is a good way to do this?
Update: what I think might work
function email()
{
sleep(2); //delays script 2 seconds (time to break script on reset)
foreach ($emails as $email):
// send individual emails with different content
// takes longer than 30 seconds
enforeach;
// on 28 seconds
return email(); //restarts process
}
Suggested approach:
function microtime_float()
{
list($usec, $sec) = explode(" ", microtime());
return ((float)$usec + (float)$sec);
}
$time_start = microtime_float();
foreach ($emails as $email):
// send individual emails with different content
// takes longer than 30 seconds
$time_curr = microtime_float();
$time = $time_curr - $time_start;
if($time > 28){ //if time is bigger than 28 seconds (2 seconds less - just in case)
break;// we will continue processing the rest of the emails - next time cron will call the script
}
enforeach;
What you ask is not possible. When the script timeout is reached, it stops. You cannot pause it and continue it. You can only restart it. Let me tell you what I did to solve a similar problem.
Part One:
Queue all your emails into a simple database. (Just a few fields like to,
from, subject, message, and a flag to track if it is sent.)
Part Two.
1. Start script
2. Set a variable with the start time
3. Check the db for any mails that have not been sent yet
4. If you find any start a FOR loop
5. Check if more than 20 seconds have elapsed (adjust the window here, I like
to allow some spare time in case a mail call takes a few seconds longer.)
6. If too much time passed, exit the loop, go to step 10
7. Send an email
8. Mark this email as sent in the db
9. The FOR loop takes us back to step 4
10. Exit the script
Run this every 60 seconds. It sends what it can, then the rest gets sent next time.
Related
I have created two functions in a separate php file and want them to run over and over.
After function A completes, I want it to compare the current time, relative to the last time function B ran, and if more than 24hrs has elapsed (or whatever value I set it to), it runs function B, resets the next time for when it should be trigger to run, and continues to run function A. They need to run separately and not parallel since values altered in function A will affect function B and thus need to be separate. The ideal scenario is I have a config.php file where I set the time delay (in hours), but I can sort that out later!
I am stumped on how to get this while(true){} loop organized... any ideas?
Regardless of whether you end up doing it this way (because I think the comments about cron make some good points, and there are some other issues you may run into with a continuously running PHP script like this) here's a basic logic for executing the alternate function based on a defined delay.
// define the delay and initialize the timestamp
$delay = 86400; // 24 hours, for example
$last_time = time();
while (true) {
functionA();
// the next time functionB should execute is the timestamp for the last run + the delay
if (time() > $last_time + $delay) {
functionB();
$last_time = time(); // reset the timestamp
}
}
Would something of this nature be similar to what you're looking for?
while ($time > 13 && $time < 21)
You could have flags involved in each function as well. If a boolean flag is fired and is = 1, then continue on?
I'm using zend_mail from zend-framework2 in my project to send some amount of emails in a loop, but sometimes it takes more than usual to send an email.
After doing some research, i found that the delay occurs on the stream_socket_client function.
I tried to set this function's timeout to acceptable value, but it seems to ignore that setting.
Also tried to use STREAM_CLIENT_PERSISTENT to limit the number of opened sockets but with no luck.
Average stream_socket_client times are about 0.03 seconds and occasionally it takes from 5 seconds up to even 40 seconds. Every value above 0.5 seconds is unacceptable for me. I'm out of ideas what can cause that issue.
Current setup:
$start = microtime(true);
$this->socket = #stream_socket_client($remote, $errorNum, $errorStr, self::TIMEOUT_CONNECTION, STREAM_CLIENT_CONNECT|STREAM_CLIENT_PERSISTENT);
echo 'Stream socket: '.(microtime(true) - $start);
The question is simple, I would like to check a database to serve customised content to a site visitor, but failover and serve a generic page if this function takes more then 800ms to execute. (Target time for the server response is 1000ms).
I've seen the set_time_limit function, however this takes an integer in seconds as the argument.
My question: is there something similar that can be used with values of less than 1 second?
I'm looking for something like:
void set_time_limit_ms ( int $milliseconds )
set_time_limit_ms (800)
doesn't exist. you just could emulate it with a tick function:
declare(ticks=1); // or more if 1 takes too much time
$start = microtime(1);
register_tick_function(function () use ($start) {
(microtime(1) - $start < 0.8) or die();
});
You will not be able to use this function to prevent a query that is running longer than you expected. This only measures the actual script execution time. Here is an bit from the manual.
The set_time_limit() function and the configuration directive
max_execution_time only affect the execution time of the script
itself. Any time spent on activity that happens outside the execution
of the script such as system calls using system(), stream operations,
database queries, etc. is not included when determining the maximum
time that the script has been running. This is not true on Windows
where the measured time is real.
Yes there is, I often use microtime. see
http://php.net/manual/en/function.microtime.php
<?php
$time_start = microtime(true);
// Sleep for a while
usleep(100);
$time_end = microtime(true);
$time = $time_end - $time_start;
echo "Did nothing in $time seconds\n";
?>
I'm writing a a php script where i do a loop and inside the loop there is a particular function processing information, as illustrated here.
while (some condition){
// some code
processInformation();
// Some more code
}
Well it turns out that midway, inside processInformation(), I encountered the error Fatal error: Maximum execution time of 30 seconds exceeded. Using set_time_limit(0), would not help in my situation because processInformation() might take forever. I don't want an error to completely break my program, so is there anyway i can catch an exception or tell php to "continue" the loop if processInformation() takes too long?
You can increase the value of maximum execution time from 30 seconds to any value. For example: if you want to set the limit of maximum execution time of 3 minutes (instead of 30 seconds), then you can set as:
ini_set('max_execution_time', 180); //maximum execution time of 3 minutes
This way, you can set the time based on your need.
I dunno how to catch the exception but you could use a simple time calculation to escape after say 60 secs. ()
$x=time();
while (some condition){
processInformation();
if ($x + 60) < time()
break;
}
I want to put a php daemon to sleep (with System_Daemon::iterate())
so it runs max 20 times randomly spread over an hour. maybe a min distance would be smart so it doesn't run 20 times in the first half hour and 0 times in the second half.
i'm kinda stuck here and don't know how to start with this one, any help is very apreciated!
You may use cron jobs, to set the script to run ever so often.
http://net.tutsplus.com/tutorials/php/managing-cron-jobs-with-php-2/
... Crontab:
0 9 * * * /path/to/bashscript
and in /path/to/bashscript:
#!/bin/bash
maxdelay=$((1*60)) # every hour, converted to minutes
for ((i=1; i<=20; i++)); do
delay=$(($RANDOM%maxdelay)) # pick an independent random delay, 20 times
(sleep $((delay*60)); /path/to/phpscript.php) & # background a subshell, then run the php script
done
i came up with one possible solution, i didnt try it out yet, so it main contain syntax or logic errors. because it is running as a daemon there is a never ending loop around it.
// 3600 seconds or one hour
$timeframe=3600;
// run max 20 times in $timeframe
$runtimes=20;
// minimum delay between two executions
$mindelay=60;
// maxium delay between two executions
$maxdelay=240;
if ($cnt % $runtimes != 0) {
$delay = rand($mindelay,$maxdelay);
System_Daemon::iterate($delay);
$sum += $delay;
$cnt++;
} else {
//final delay till the $timeframe
if ($sum < $timeframe) {
System_Daemon::iterate($timeframe - $sum);
}
$sum=0;
}
its not perfect and u waste some time but i guess its going to fullfill the job.
any comments?