The Lock

The mission of the Lock Core Library is to create and manage lock files. The lock files are used in order to report the status of a process during and after the application execution.

As example of lock file usage we can describe a case with a batch process. The batch process is using some resources when is running, and the same process want to avoid that new processes are launched at same time. In this case the lock file can be used as signal for the following processes, so the processes can read the lock files and stop the execution.

The lock files can also used in order to report the process "post-mortem" execution status, so for example a process that was finalized or halted in an unexpected way can report to the following processes the last execution status.

Drivers

The lock file has currently one single driver.

Lock_File

The Lock_File is the default Lock Core Library driver. This driver writes the process status into a file.

Instantiation example:

    Lock::instance()->attach(new Lock_File('/tmp/myprocess.lock'));

Instantiation & Driver attachment

In the previous section about the drivers we learned how to instantiate our Lock class using the Lock_File driver, however there is one aspect about the class instantiation and is that it is possible to create different Lock instances using singleton passing one unique identifier to the instance method. Example:

    Lock::instance('mysecondlockfile')->attach(new Lock_File('/tmp/mysecondlockfile'));

How to write into the Lock file

Lock files are written using the write method. Example:

    // Write the current process status
    Lock::instance()->write(serialize(['status' => 'Running', 'completed' => '20%']));

How to read from the Lock file

Lock files are read using the read method. Example:

    // Read from Lock file
    $status = Lock::instance()->read();

Dead message

A "dead message" or "dead letter" is a message that a process writes when their execution is unexpected halted due an error or system crash. The Lock Core Library can writes automatically "dead messages" when the application is unexpected halted or it is finished.

There are 3 different behaviours for the the "dead messages":

  1. Lock file is automatically deleted when the application finished even when the execution is unexpected halted, so the "dead message" is not written at all. This is the default behaviour, however this behaviour can be manually changed when the property dead_message is equals to "null" (null). Example:

    // Remove lock file when application finished
    Lock::instance()->dead_message = null;
    
    // Write current application status
    Lock::instance()->write(serialize(['status' => 'running', 'completed' => '0%']);
    
    // Finish the application execution
    Apprunner::terminate(Apprunner::EXIT_FAILURE);
  2. Lock file is not removed when application is finished and the last written message remains. It is possible to set this behaviour assigning the value "false" (bool) to the dead_message property. Example:

    // Keep Lock file when application finished
    Lock::instance()->dead_message = false;
    
    // Write current application status
    Lock::instance()->write(serialize(['status' => 'running', 'completed' => '0%']);  
    
    // Terminate application execution
    Apprunner::terminate(Apprunner::EXIT_FAILURE);       
  3. Lock file is not remove when application is finished, however the "dead message" is written. It is possible to set this behaviour assigning the "dead message to the dead_message property. Example:

    // Write default "dead message"
    Lock::instance()->dead_message = serialize(['status' => 'error', 'time' => time()]);
    
    // Write current application status
    Lock::instance()->write(serialize(['status' => 'running', 'completed' => '0%']);       
    
    // Simulate unexpected error (Or finish the application with Apprunner::terminate)
    throw new Exception('Application crash');

It is possible to revert this behaviour and the described in the point 2 assigning the value "null" (null) to the dead_letter property. Example:

    // Write default "dead message"
    Lock::instance()->dead_message = serialize(['status' => 'error', 'time' => time()]);

    // Write current application status
    Lock::instance()->write(serialize(['status' => 'finished', 'completed' => '100%']);     

    // Remove lock file because application was sucesfully executed
    Lock::instance()->dead_message = null;

    // Terminate application execution
    Apprunner::terminate(Apprunner::EXIT_SUCESS);