130 lines
3.4 KiB
PHP
130 lines
3.4 KiB
PHP
<?php
|
|
namespace nur\sery\file\app;
|
|
|
|
use nur\sery\cl;
|
|
use nur\sery\file\SharedFile;
|
|
use nur\sery\os\path;
|
|
use nur\sery\php\time\DateTime;
|
|
use nur\sery\str;
|
|
|
|
/**
|
|
* Class RunFile: une classe permettant de suivre le fonctionnement d'une
|
|
* application qui tourne en tâche de fond
|
|
*/
|
|
class RunFile {
|
|
const RUN_EXT = ".run";
|
|
const LOCK_EXT = ".lock";
|
|
|
|
const NAME = null;
|
|
|
|
function __construct(string $file, ?string $name=null) {
|
|
$file = path::ensure_ext($file, self::RUN_EXT);
|
|
$this->file = new SharedFile($file);
|
|
$this->name = $name ?? static::NAME;
|
|
}
|
|
|
|
/** @var SharedFile */
|
|
protected $file;
|
|
|
|
/** @var ?string */
|
|
protected $name;
|
|
|
|
protected static function merge(array $data, array $merge): array {
|
|
return cl::merge($data, [
|
|
"serial" => $data["serial"] + 1,
|
|
], $merge);
|
|
}
|
|
|
|
protected function initData(bool $withDateStart=true): array {
|
|
$dateStart = $withDateStart? new DateTime(): null;
|
|
return [
|
|
"name" => $this->name,
|
|
"serial" => 0,
|
|
"date_start" => $dateStart,
|
|
"date_stop" => null,
|
|
"action" => null,
|
|
"action_date_start" => null,
|
|
"action_max_step" => null,
|
|
"action_current_step" => null,
|
|
"action_date_step" => null,
|
|
];
|
|
}
|
|
|
|
function read(): array {
|
|
$data = $this->file->unserialize();
|
|
if (!is_array($data)) $data = $this->initData(false);
|
|
return $data;
|
|
}
|
|
|
|
/** tester si l'application est démarrée */
|
|
function isStarted(): bool {
|
|
$data = $this->read();
|
|
return $data["date_start"] !== null;
|
|
}
|
|
|
|
/** tester si l'application est arrêtée */
|
|
function isStopped(): bool {
|
|
$data = $this->read();
|
|
return $data["date_stop"] !== null;
|
|
}
|
|
|
|
function haveWorked(int $serial, ?int &$currentSerial=null): bool {
|
|
$data = $this->read();
|
|
return $serial !== $data["serial"];
|
|
}
|
|
|
|
protected function willWrite(): array {
|
|
$file = $this->file;
|
|
$file->lockWrite();
|
|
$data = $file->unserialize(null, false, true);
|
|
if (!is_array($data)) {
|
|
$data = $this->initData();
|
|
$file->ftruncate();
|
|
$file->serialize($data, false, true);
|
|
}
|
|
$file->ftruncate();
|
|
return [$file, $data];
|
|
}
|
|
|
|
/** indiquer que l'application démarre */
|
|
function start(): void {
|
|
$this->file->serialize($this->initData());
|
|
}
|
|
|
|
/** indiquer le début d'une action */
|
|
function action(?string $title, ?int $maxSteps=null): void {
|
|
[$file, $data] = $this->willWrite();
|
|
$file->serialize(self::merge($data, [
|
|
"action" => $title,
|
|
"action_date_start" => new DateTime(),
|
|
"action_max_step" => $maxSteps,
|
|
"action_current_step" => 0,
|
|
]));
|
|
}
|
|
|
|
/** indiquer qu'une étape est franchie dans l'action en cours */
|
|
function step(int $nbSteps=1): void {
|
|
[$file, $data] = $this->willWrite();
|
|
$file->serialize(self::merge($data, [
|
|
"action_date_step" => new DateTime(),
|
|
"action_current_step" => $data["action_current_step"] + $nbSteps,
|
|
]));
|
|
}
|
|
|
|
/** indiquer que l'application s'arrête */
|
|
function stop(): void {
|
|
[$file, $data] = $this->willWrite();
|
|
$file->serialize(self::merge($data, [
|
|
"date_stop" => new DateTime(),
|
|
]));
|
|
}
|
|
|
|
function getLockFile(?string $name=null, ?string $title=null): LockFile {
|
|
$ext = self::LOCK_EXT;
|
|
if ($name !== null) $ext = ".$name$ext";
|
|
$file = path::ensure_ext($this->file->getFile(), $ext, self::RUN_EXT);
|
|
$name = str::join("/", [$this->name, $name]);
|
|
return new LockFile($file, $name, $title);
|
|
}
|
|
}
|