This topic is locked

Guide 47 – Control of a single running Process

1/18/2023 2:16:24 PM
PHPRunner Tips and Tricks
fhumanes author

It is common for applications to have "heavy" and therefore "slow" processes that we want users to not be able to run several times in a short period of time or that these processes run one by one, so as not to overload the system. server, and thus continue giving a good response time to the rest of the processes and users.

Also, the same problem can arise when we want a resource in our system to be accessed only by a single process, waiting to be released for the rest of the processes that require that resource.

Some examples that may require this unique process management are:

  • Reloading or copying information from another system (massive batch process).
  • Data backup or backup of previous backups
  • Preparation of heavy reports. System closure or reconfiguration processes.
  • Use of a server resource (file, serial port, USB, digital certificate, etc.)
  • Etc.

Objective

Have a logic, in the projects developed in PHPRunner , to control:

  • That a specific process is only running once and the rest of the requests that occur are rejected by the system.
  • That a specific process is only running once and that the rest of the concurrent requests are queued and released according to the order of arrival (FIFO queue).

DEMO: https://fhumanes.com/single_execution/

Technical Solution

Concurrency control can be performed at least with these 3 means.

  • Through a “semaphore” of the operating system
  • Through the blocking of a file.
  • Through a database manager table.

In this example, control has been used by locking a file (files, to have several controls).

This is the image of the application:

img alt

2 buttons have been implemented:

(1) – Button to execute the process and reject the requests that concur in the execution.

(2) – Button to execute the process and queue the requests until the previous one is finished

The process is very simple, delay the process 15 seconds:

<?php
// time initial
$time_initial = date('h:i:s');
// sleep 15 seg
sleep(15);
// Time final
$time_final = date('h:i:s');
?>

The function that performs the control of a process and the rest, its rejection, is:

<?php
function single_execution( $semaphore, $process ) {
$path_semaphore = __DIR__."/semaphores/".$semaphore.".lock";
$fp = fopen($path_semaphore, "r+");
if ($fp == false ) { // file not found
return array(false ,"The semaphore file does not exist!");
}
if (!flock($fp, LOCK_EX|LOCK_NB, $blocked)) {
if ($blocked) {
// another process holds the lock
return array(false, "Couldn't get the lock! Other script in run!");
}
else {
// couldn't lock for another reason, e.g. no such file
return array(false , "Error! Nothing done.");
}
}
else {
// lock obtained
ftruncate($fp, 0); // truncate file
// execute Proccess
include ($process);
fflush($fp); // flush output before releasing the lock
flock($fp, LOCK_UN); // release the lock
return array(true, "Process executed correctly");
}
}

The function performed by the FIFO queue is:

<?php

function fifo_execution( $semaphore, $process ) {
$path_semaphore = __DIR__."/semaphores/".$semaphore.".lock";
$fp = fopen($path_semaphore, "r+");
if ($fp == false ) { // file not found
return array(false ,"The semaphore file does not exist!");
}
if (flock($fp, LOCK_EX)) { // acquire an exclusive lock
ftruncate($fp, 0); // truncate file
// execute Proccess
include ($process);
fflush($fp); // flush output before releasing the lock
flock($fp, LOCK_UN); // release the lock
}
fclose($fp);
return array(true, "Process executed correctly");
}

The programming of the 3-state buttons is:

  • Previous (Javascript)

    $('a[id^="Process_unique"]').attr("disabled", true); // Deshabilitar botón
  • Server (PHP)


    include ("MyCode/semaphore_code.php");


$status = single_execution("semaphore_1", DIR."/MyCode/slow_processes/process_1.php");
$result['status'] = $status[0];
$result['message'] = $status[1];

* After (JavaScript)

$('a[id^="Process_unique"]').removeAttr("disabled") // Habilitar botón
var message = 'Status = '+ result["status"]+' '+result["message"];
ajax.setMessage(message);


[If you are interested in this topic and want to obtain the code, ](https://fhumanes.com/blog/guias-desarrollo/guia-47-control-de-un-unico-proceso-en-ejecucion/)click here to access the article
fhumanes author 1/18/2023

Sorry, the layout of the article has been fatal, but I don't know how I can correct it.

If you want to access all the information and code, please, access my portal.