Limit number of instances of Symfony Command - symfony

I have a command in my Symfony app launched by Cron. I want to be able to limit the number of instances executed at the same time on my server, let's say 4 instances. I don't have any clue on how to do this. I found how to lock the command to launch the command only one time and wait for it to finish, but I don't know how to launch more than one and limit the number of instances anyway.
Do you have an idea ?

What you are looking for is a semaphore.
There is a LockComponent currently scheduled for 3.4 (was pulled from 3.3). It is a major improvement over the LockHandler in the FilesystemComponent.
In a pinch, you can probably pool a fixed number of locks from the LockHandler. I don't recommend it, because it uses flock on the filesystem. This limits the lock to a single server. Additionally, flock may be limited to the process scope on some systems.
<?php
use Symfony\Component\Filesystem\LockHandler;
define('LOCK_ID', 'some-identifier');
define('LOCK_MAX', 5);
$lockPool = [];
for ($i = 0; $i <= LOCK_MAX;) {
$lockHandle = sprintf('%s-%s.lock', LOCK_ID, ++$i);
$lockPool[$i] = new LockHandler($lockHandle);
}
$activeLock = null;
$lockTimeout = 60 * 1000;
$lockWaitStart = microtime(true);
while(!$activeLock) {
foreach ($lockPool as $lockHandler) {
if ($lockHandler->lock()) {
$activeLock = $lockHandler;
break 2;
}
}
if ($lockTimeout && ($lockTimeout > microtime(true) - $lockWaitStart)) {
break;
}
// Randomly wait between 0.1ms and 10ms
usleep(mt_rand(100, 10000));
}
A much better and efficient solution would be to use the semaphore extension and work some magic with ftok, shm_* and sem_*.

i suggest you to use a process control system as supervisor. it's pretty simple to use and you can choose how many instance of your script you start.
http://supervisord.org/

You could use a shared counter file which holds a counter that gets increased when the Command starts running and decreases it before it's finished.
Another solution would be checking the process list with something like this:
$processCount = exec('ps aux | grep "some part of the console command you run" | grep -v "grep" | wc -l' );
if(!empty($processCount) && $processCount >= X) {
return false;
}

You can create a "launcher command" executed by your cron or supervisor.
This Symfony commad can launch your instances with the process component on your server. You can also check whatever you want to check and do everything you want to do like the exec php function.

Related

How to call a function again inside a function in powershell

I'm trying to implement pooling function for datamovement operation in dynamic 365.
I have a PowerShell script which is having a function called Test(pera1,pera2,pera3..) when we call this function it will take around 1hr+ time to complete the event. Now I have to call another task based on this Test() function result. If my condition is match then will call another task otherwise I have to put Start-Sleep -Seconds 3600 to complete the event.
function EnvOperationPooling($pera1, $pera2, $pera3)
{
// here API call code
// API result
if($apiResponse.DeploymentState-eq 'Inprogress')
{
Start-Sleep -Seconds 3600
EnvOperationPooling -proj1 $pera1 -proj2 $pera2 -proj2 $pera2
Write-Host "##vso[task.setvariable variable=DeploymentState;isOutput=true]$($apiResponse.DeploymentState)"
}
else
{
Write-Host "##vso[task.setvariable variable=DeploymentState;isOutput=true]$($apiResponse.DeploymentState)"
}
}
how i can make it recursive any suggetion to make above code better ..?
For recursive operation & time saving of your process you need use background jobs of PowerShell.
if you start a background job, the command prompt returns immediately, even if the job takes an extended time to complete. You can continue to work in the session without interruption while the job runs. Refer
Start-Job -ScriptBlock {Get-Process}
Refer for more here

Scheduling complication updates

I have a custom complication on Apple Watch that I am trying to get to update once an hour. Each hour it should ping an API endpoint and if the data has changed from the last check, the complication should be updated.
Here is what I currently have that only seems to work once in a blue moon. When it DOES work, it does indeed ping my server and update the complication. It appears WatchOS just isn't calling my scheduled tasked once per hour. Is there a better standard practice that I'm missing?
#implementation ExtensionDelegate
- (void)applicationDidFinishLaunching {
// Perform any final initialization of your application.
[SessionManager sharedManager];
[self scheduleHourlyUpdate];
}
- (void) scheduleHourlyUpdate {
NSDate *nextHour = [[NSDate date] dateByAddingTimeInterval:(60 * 60)];
NSDateComponents *dateComponents = [[NSCalendar currentCalendar]
components: NSCalendarUnitYear | NSCalendarUnitMonth | NSCalendarUnitDay | NSCalendarUnitHour | NSCalendarUnitMinute | NSCalendarUnitSecond fromDate:nextHour];
[[WKExtension sharedExtension] scheduleBackgroundRefreshWithPreferredDate:nextHour userInfo:nil scheduledCompletion:^(NSError * _Nullable error) {
// schedule another one in the next hour
if (error != nil)
NSLog(#"Error while scheduling background refresh task: %#", error.localizedDescription);
}];
}
- (void)handleBackgroundTasks:(NSSet<WKRefreshBackgroundTask *> *)backgroundTasks {
// Sent when the system needs to launch the application in the background to process tasks. Tasks arrive in a set, so loop through and process each one.
for (WKRefreshBackgroundTask * task in backgroundTasks) {
// Check the Class of each task to decide how to process it
if ([task isKindOfClass:[WKApplicationRefreshBackgroundTask class]]) {
// Be sure to complete the background task once you’re done.
WKApplicationRefreshBackgroundTask *backgroundTask = (WKApplicationRefreshBackgroundTask*)task;
[backgroundTask setTaskCompletedWithSnapshot:NO];
[self updateComplicationServer];
} else if ([task isKindOfClass:[WKSnapshotRefreshBackgroundTask class]]) {
// Snapshot tasks have a unique completion call, make sure to set your expiration date
WKSnapshotRefreshBackgroundTask *snapshotTask = (WKSnapshotRefreshBackgroundTask*)task;
[snapshotTask setTaskCompletedWithDefaultStateRestored:YES estimatedSnapshotExpiration:[NSDate distantFuture] userInfo:nil];
} else if ([task isKindOfClass:[WKWatchConnectivityRefreshBackgroundTask class]]) {
// Be sure to complete the background task once you’re done.
WKWatchConnectivityRefreshBackgroundTask *backgroundTask = (WKWatchConnectivityRefreshBackgroundTask*)task;
[backgroundTask setTaskCompletedWithSnapshot:NO];
} else if ([task isKindOfClass:[WKURLSessionRefreshBackgroundTask class]]) {
// Be sure to complete the background task once you’re done.
WKURLSessionRefreshBackgroundTask *backgroundTask = (WKURLSessionRefreshBackgroundTask*)task;
[backgroundTask setTaskCompletedWithSnapshot:NO];
} else if ([task isKindOfClass:[WKRelevantShortcutRefreshBackgroundTask class]]) {
// Be sure to complete the relevant-shortcut task once you’re done.
WKRelevantShortcutRefreshBackgroundTask *relevantShortcutTask = (WKRelevantShortcutRefreshBackgroundTask*)task;
[relevantShortcutTask setTaskCompletedWithSnapshot:NO];
} else if ([task isKindOfClass:[WKIntentDidRunRefreshBackgroundTask class]]) {
// Be sure to complete the intent-did-run task once you’re done.
WKIntentDidRunRefreshBackgroundTask *intentDidRunTask = (WKIntentDidRunRefreshBackgroundTask*)task;
[intentDidRunTask setTaskCompletedWithSnapshot:NO];
} else {
// make sure to complete unhandled task types
[task setTaskCompletedWithSnapshot:NO];
}
}
}
- (void)updateComplicationServer {
[self scheduleHourlyUpdate];
NSString *nsLogin = [NSUserDefaults.standardUserDefaults objectForKey:#"loginDTO"];
if (nsLogin != nil)
{
NSDateComponents *dateComponents = [[NSCalendar currentCalendar]
components: NSCalendarUnitYear | NSCalendarUnitMonth | NSCalendarUnitDay fromDate:[NSDate date]];
LoginDTO *login = new LoginDTO([nsLogin cStringUsingEncoding:NSUTF8StringEncoding]);
NSMutableURLRequest *req = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:#"https://www.myurl.com/Api/Watch/Complication"]];
[req setHTTPMethod:#"GET"];
// Set headers
[req addValue:[NSString stringWithUTF8String:login->GetApiKey()] forHTTPHeaderField:#"MySessionKey"];
[req addValue:[NSString stringWithFormat:#"%d,%d,%d", dateComponents.year, dateComponents.month, dateComponents.day] forHTTPHeaderField:#"FetchDate"];
[req addValue:#"application/json" forHTTPHeaderField:#"Content-Type"];
NSURLSession *session = [NSURLSession sharedSession];
NSURLSessionDataTask *task = [session dataTaskWithRequest:req completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error)
{
// Call is complete and data has been received
NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse*)response;
if (httpResponse.statusCode == 200)
{
NSString* nsJson = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
NSString *prevJson = [NSUserDefaults.standardUserDefaults objectForKey:#"previousComplicationJson"];
if (prevComplicationJson != nil)
{
if ([prevComplicationJson isEqualToString:nsJson])
return; // Nothing changed, so don't update the UI.
}
// Update the dictionary
[NSUserDefaults.standardUserDefaults setObject:nsJson forKey:#"previousComplicationJson"];
CLKComplicationServer *server = [CLKComplicationServer sharedInstance];
for (int i = 0; i < server.activeComplications.count; i++)
[server reloadTimelineForComplication:server.activeComplications[i]];
}
}];
[task resume];
delete login;
}
}
watchOS background tasks are extraordinarily cumbersome to implement and debug, but based on Apple’s documentation and implementations that others have discussed, here‘s what I believe to be the best practice. I see a couple of issues here.
First, from the WKRefreshBackgroundTask docs:
The system suspends the extension as soon as all background tasks are complete.
Calling setTaskCompletedWithSnapshot on the task indicates to the system that you’ve finished performing all the work you need to do, so it will suspend your app. Your updateComplicationServer method is probably never getting a chance to run because the system suspends your extension too early.
More importantly, to make URL requests during a background update, you’ll need to use a background URL session. The example process outlined in the WKRefreshBackgroundTask docs shows the best practice for setting this up. In short:
You schedule a background refresh using WKExtension’s scheduleBackgroundRefresh just like you’re doing.
The system will wake your extension sometime after your preferred date (at the system’s discretion) with a WKRefreshBackgroundTask.
In your extension delegate’s handle method, check for the WKApplicationRefreshBackgroundTask; instead of performing the request with a URLSessionDataTask here, you need to schedule a background URL session so that the system can suspend your extension and perform the request on your behalf. See the WKURLSessionRefreshBackgroundTask docs for details about how background sessions should be set up.
The system will perform your URL request in a separate process, and again wake your extension once it has finished. It will call your extension delegate’s handle method like before, this time with a WKURLSessionRefreshBackgroundTask. Here, you need to do two things:
Save the background task in an instance variable on your extension delegate. We don’t want to set it complete just yet, but we need to keep it around to set complete later when the URL request finishes.
Create another background URL session using the background task’s sessionIdentifier, and use your extension delegate as the session’s delegate (why it doesn’t work to use another object as the delegate, I can’t say, but it seems to be a crucial detail). Note that using the same identifier to create a second URL session allows the system to connect the session to the download that it performed for you in another process; the purpose of this second background URL session is solely to connect the delegate with the session.
In the session delegate, implement both the urlSession(_ downloadTask: didFinishDownloadingTo:) and urlSession(task: didCompleteWithError:) functions.
Unlike your block-based NSURLSessionDataTask, background URL requests are always performed as download tasks. The system performs the request and gives you a temporary file with the resulting data. In the urlSession(_ downloadTask: didFinishDownloadingTo:) function, the data in that file and process it as needed to update your UI.
Finally, in the delegate’s urlSession(task: didCompleteWithError:) function, call setTaskCompletedWithSnapshot to tell the system that you’ve finished your work. Phew.
As I mentioned, this is all really frustrating to debug, mostly because it’s all up to the system when these things actually take place, if they happen at all. Apple’s documentation has this to say about the budget allocated to background refreshes:
In general, the system performs approximately one task per hour for each app in the dock (including the most recently used app). This budget is shared among all apps on the dock. The system performs multiple tasks an hour for each app with a complication on the active watch face. This budget is shared among all complications on the watch face. After you exhaust the budget, the system delays your requests until more time becomes available.
One final note: legend has it that the watchOS simulator doesn’t handle background URL refresh tasks properly, but unfortunately, Apple’s docs have no official word on that. Best to test on Apple Watch hardware if you‘re able.

How to check if a Process is Running or Not

I am starting a process using the below code
QProcess* process = new QProcess();
process->start(Path);
The start method will start a third party application.
If the process is already running, I should not call process->start(Path) again.
The process pointer is private member of the class.
From the docs for QProcess ...
There are at least 3 ways to check if a QProcess instance is running.
QProcess.pid() : If its running, the pid will be > 0
QProcess.state() : Check it again the ProcessState enum to see if its QProcess::NotRunning
QProcess.atEnd() : Its not running if this is true
If any of these are not working as you would expect, then you will need to post a specific case of that example.
To complement the #jdi's answer with a real-life code example:
QString executable = "C:/Program Files/tool.exe";
QProcess *process = new QProcess(this);
process->start(executable, QStringList());
// some code
if ( process->state() == QProcess::NotRunning ) {
// do something
};
QProcess::ProcessState constants are:
Constant Value Description
QProcess::NotRunning 0 The process is not running.
QProcess::Starting 1 The process is starting, but the program has not yet been invoked.
QProcess::Running 2 The process is running and is ready for reading and writing.
Documentation is here.

PHPUnit Performance / Test Timeout

I am building a testing script which is checking the performance of a set of commands. The test script needs to let it run for a specific amount of time before failing the test.
I found the PerformanceTestCase in the PHPUnit documentation website, but when I tried to use it I realised that it's old functionality which hasn't been included within the new version. (That doc is PHPUnit 3.0, and my version is 3.5).
Is there an equivalent for this functionality within PHPUnit 3.5, and how do I use it?
Well, you could simply do something like
public function testFoo() {
$tStart = microtime( true );
// your time critical commands
$tDiff = microtime( true ) - $tStart;
$this->assertLessThan( $maxTime, $tDiff, 'Took too long' );
}
Of course this means that your commands will not be interrupted before being finished.
And IMO unittests are not meant for testing performance.
I ran into a smiliar issue today - I needed to test an external HTTP call was occuring within the allocated time.
Rather than build another loop or take $start and $end time readings - I exposed the timed_out param, detailed here http://www.php.net/manual/en/function.stream-get-meta-data.php
while (!feof($fp)) {
$info = stream_get_meta_data($fp);
if ($info['timed_out']) {
$this->timed_out = true;
fclose($fp);
throw new Exception("Request timed out");
}
else {
$response .= fgets($fp, 128);
}
}
fclose($fp);

is node.js' console.log asynchronous?

Are console.log/debug/warn/error in node.js asynchrounous? I mean will javascript code execution halt till the stuff is printed on screen or will it print at a later stage?
Also, I am interested in knowing if it is possible for a console.log to NOT display anything if the statement immediately after it crashes node.
Update: Starting with Node 0.6 this post is obsolete, since stdout is synchronous now.
Well let's see what console.log actually does.
First of all it's part of the console module:
exports.log = function() {
process.stdout.write(format.apply(this, arguments) + '\n');
};
So it simply does some formatting and writes to process.stdout, nothing asynchronous so far.
process.stdout is a getter defined on startup which is lazily initialized, I've added some comments to explain things:
.... code here...
process.__defineGetter__('stdout', function() {
if (stdout) return stdout; // only initialize it once
/// many requires here ...
if (binding.isatty(fd)) { // a terminal? great!
stdout = new tty.WriteStream(fd);
} else if (binding.isStdoutBlocking()) { // a file?
stdout = new fs.WriteStream(null, {fd: fd});
} else {
stdout = new net.Stream(fd); // a stream?
// For example: node foo.js > out.txt
stdout.readable = false;
}
return stdout;
});
In case of a TTY and UNIX we end up here, this thing inherits from socket. So all that node bascially does is to push the data on to the socket, then the terminal takes care of the rest.
Let's test it!
var data = '111111111111111111111111111111111111111111111111111';
for(var i = 0, l = 12; i < l; i++) {
data += data; // warning! gets very large, very quick
}
var start = Date.now();
console.log(data);
console.log('wrote %d bytes in %dms', data.length, Date.now() - start);
Result
....a lot of ones....1111111111111111
wrote 208896 bytes in 17ms
real 0m0.969s
user 0m0.068s
sys 0m0.012s
The terminal needs around 1 seconds to print out the sockets content, but node only needs 17 milliseconds to push the data to the terminal.
The same goes for the stream case, and also the file case gets handle asynchronous.
So yes Node.js holds true to its non-blocking promises.
console.warn() and console.error() are blocking. They do not return until the underlying system calls have succeeded.
Yes, it is possible for a program to exit before everything written to stdout has been flushed. process.exit() will terminate node immediately, even if there are still queued writes to stdout. You should use console.warn to avoid this behavior.
My Conclusion , after reading Node.js 10.* docs (Attached below). is that you can use console.log for logging , console.log is synchronous and implemented in low level c .
Although console.log is synchronic, it wont cause a performance issue only if you are not logging huge amount of data.
(The command line example below demonstrate, console.log async and console.error is sync)
Based on Node.js Doc's
The console functions are synchronous when the destination is a terminal or a file (to avoid lost messages in case of premature exit) and asynchronous when it's a pipe (to avoid blocking for long periods of time).
That is, in the following example, stdout is non-blocking while stderr is blocking:
$ node script.js 2> error.log | tee info.log
In daily use, the blocking/non-blocking dichotomy is not something you should worry about unless you > log huge amounts of data.
Hope it helps
Console.log is asynchronous in windows while it is synchronous in linux/mac. To make console.log synchronous in windows write this line at the start of your
code probably in index.js file. Any console.log after this statement will be considered as synchronous by interpreter.
if (process.stdout._handle) process.stdout._handle.setBlocking(true);
You can use this for synchrounous logging:
const fs = require('fs')
fs.writeSync(1, 'Sync logging\n')

Resources