Removed all unused files
This commit is contained in:
parent
2b39a9df9e
commit
44b554d08c
6 changed files with 0 additions and 452 deletions
|
@ -1,66 +0,0 @@
|
||||||
== GLOBAL ==
|
|
||||||
Both the client and the worker have access to the following functions:
|
|
||||||
|
|
||||||
initialize($mode, $server_config): void - Initializes TamerLib in the given mode, if no server_config is provided then
|
|
||||||
Tamer will initialize it's own server and use its own configuration. When initializing as a worker, the
|
|
||||||
$server_config is ignored as the configuration is provided by the parent process.
|
|
||||||
|
|
||||||
shutdown(): void - Shuts down the TamerLib by resetting the global variables and releasing any resources it may have
|
|
||||||
allocated.
|
|
||||||
|
|
||||||
|
|
||||||
== CLIENT ==
|
|
||||||
The client is the master process of TamerLib that is used to push tasks to the worker processes, optionally a client may
|
|
||||||
also be responsible for supervising workers and or managing its own server process.
|
|
||||||
|
|
||||||
createWorker($count, $path): void - Creates workers and starts them, the count parameter specifies how many workers to create
|
|
||||||
and the path parameter being optional, if provided, specifies the path to the worker executable. If the path
|
|
||||||
parameter is not provided, TamerLib will use it's own subprocess to create the workers which can only handle closures
|
|
||||||
|
|
||||||
do($callable, $channel=0): string - Pushes a task to the worker pool and returns the job id, this adds the job to its own watchlist
|
|
||||||
so that it can be monitored by Tamer.
|
|
||||||
|
|
||||||
call($function, $args, $channel=0): string - Pushes a function call to the worker pool and returns the job id, this adds the job to its own watchlist
|
|
||||||
so that it can be monitored by Tamer.
|
|
||||||
|
|
||||||
dof($callable, $channel=0): void - Pushes a task to the worker pool and forgets about it, this does not add the job to the watchlist
|
|
||||||
|
|
||||||
callf($function, $args, $channel=0): void - Pushes a function call to the worker pool and forgets about it,
|
|
||||||
this does not add the job to the watchlist
|
|
||||||
|
|
||||||
wait($callback($job_id, $return)): void - Waits for all jobs dispatched with do() to complete, the callback is called
|
|
||||||
for each job that completes with the job id and the return value of the job. If one or more jobs fail, the function
|
|
||||||
will throw an replicated exception.
|
|
||||||
|
|
||||||
waitFor($job_id): mixed - Waits for a specific job to complete and returns the return value of the job, if the job
|
|
||||||
fails, the function will throw an replicated exception.
|
|
||||||
|
|
||||||
clear(): void - Clears the watchlist of all jobs.
|
|
||||||
|
|
||||||
NOTE: wait & waitFor will execute supervisory tasks while waiting for jobs to complete if the client is configured to
|
|
||||||
supervise workers.
|
|
||||||
|
|
||||||
== WORKER ==
|
|
||||||
The worker is the slave process of TamerLib that is used to execute tasks pushed to it by the client process.
|
|
||||||
|
|
||||||
setFunction($function, $callable): void - Sets the function that will be called when the worker receives a task with
|
|
||||||
the given function name.
|
|
||||||
|
|
||||||
removeFunction($function): void - Removes the function that will be called when the worker receives a task with
|
|
||||||
the given function name.
|
|
||||||
|
|
||||||
getFunctions(): array - Returns an array of all the functions that the worker has registered.
|
|
||||||
|
|
||||||
run($channels, $timeout=0): void - Runs the worker process, this function will block until the worker is shutdown or
|
|
||||||
until the timeout is reached. If the timeout is reached, the worker will shutdown. The channels parameter is an
|
|
||||||
int or an array of ints that specifies which channels the worker will listen on. If the channels parameter is 0
|
|
||||||
then the worker will listen only on channel 0.
|
|
||||||
|
|
||||||
return($job_id, $return): void - Returns the return value of the job to the client process, this function is called
|
|
||||||
automatically when the worker completes a job.
|
|
||||||
|
|
||||||
throw($job_id, $exception): void - Throws an exception to the client process, this function is called automatically
|
|
||||||
when the worker completes a job and the job throws an exception.
|
|
||||||
|
|
||||||
reject($job_id, $exception): void - Rejects a job, this silently rejects the job and pushes it back onto the queue
|
|
||||||
for another worker to pick up.
|
|
261
old
261
old
|
@ -1,261 +0,0 @@
|
||||||
/**
|
|
||||||
* Configures the Redis server.
|
|
||||||
*
|
|
||||||
* @param string $cmd
|
|
||||||
* @param string $host
|
|
||||||
* @param int|null $port
|
|
||||||
* @return void
|
|
||||||
* @throws NoAvailablePortException
|
|
||||||
*/
|
|
||||||
public static function configureRedisServer(string $cmd='redis-server', string $host='127.0.0.1', ?int $port=null): void
|
|
||||||
{
|
|
||||||
if(self::$redis_server instanceof RedisServer)
|
|
||||||
{
|
|
||||||
throw new RuntimeException('Redis server already configured.');
|
|
||||||
}
|
|
||||||
|
|
||||||
self::$redis_server = new RedisServer($cmd, $host, $port);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the Redis server
|
|
||||||
*
|
|
||||||
* @return RedisServer|null
|
|
||||||
*/
|
|
||||||
private static function getRedisServer(): ?RedisServer
|
|
||||||
{
|
|
||||||
if(is_null(self::$redis_server))
|
|
||||||
{
|
|
||||||
self::$redis_server = new RedisServer();
|
|
||||||
}
|
|
||||||
|
|
||||||
return self::$redis_server;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Adds the job ID to the watch list.
|
|
||||||
*
|
|
||||||
* @param int $job_id
|
|
||||||
* @return void
|
|
||||||
*/
|
|
||||||
private static function addToWatch(int $job_id): void
|
|
||||||
{
|
|
||||||
self::$watching_jobs[] = $job_id;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Cleans up the watch list by removing jobs that no longer exist.
|
|
||||||
*
|
|
||||||
* @return void
|
|
||||||
*/
|
|
||||||
public static function cleanWatchList(): void
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
foreach(self::$watching_jobs as $job_id)
|
|
||||||
{
|
|
||||||
if(!self::getRedisClient()->exists($job_id))
|
|
||||||
{
|
|
||||||
unset(self::$watching_jobs[$job_id]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch(Exception $e)
|
|
||||||
{
|
|
||||||
throw new RuntimeException('Failed to clean watch list.', 0, $e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the Redis client.
|
|
||||||
*
|
|
||||||
* @return Redis
|
|
||||||
* @throws RedisException
|
|
||||||
*/
|
|
||||||
private static function getRedisClient(): Redis
|
|
||||||
{
|
|
||||||
if(is_null(self::$redis_server))
|
|
||||||
{
|
|
||||||
self::$redis_server = new RedisServer();
|
|
||||||
}
|
|
||||||
|
|
||||||
if(!self::$redis_server->isRunning())
|
|
||||||
{
|
|
||||||
self::$redis_server->start();
|
|
||||||
}
|
|
||||||
|
|
||||||
if(is_null(self::$redis_client))
|
|
||||||
{
|
|
||||||
self::$redis_client = new Redis();
|
|
||||||
/** @noinspection NullPointerExceptionInspection */
|
|
||||||
var_dump(self::getRedisServer()->getHost(), self::getRedisServer()->getPort());
|
|
||||||
self::$redis_client->connect(self::getRedisServer()->getHost(), self::getRedisServer()->getPort());
|
|
||||||
}
|
|
||||||
|
|
||||||
return self::$redis_client;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the worker supervisor.
|
|
||||||
*
|
|
||||||
* @return WorkerSupervisor
|
|
||||||
*/
|
|
||||||
private static function getSupervisor(): WorkerSupervisor
|
|
||||||
{
|
|
||||||
if(is_null(self::$supervisor))
|
|
||||||
{
|
|
||||||
self::$supervisor = new WorkerSupervisor();
|
|
||||||
}
|
|
||||||
|
|
||||||
return self::$supervisor;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Spawns a closure worker.
|
|
||||||
*
|
|
||||||
* @param int $count
|
|
||||||
* @return void
|
|
||||||
*/
|
|
||||||
public static function spawnClosure(int $count=8): void
|
|
||||||
{
|
|
||||||
self::getSupervisor()->spawnClosure(self::getRedisServer(), $count);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Spawns a worker of a specific php file.
|
|
||||||
*
|
|
||||||
* @param array $cmd
|
|
||||||
* @param int $count
|
|
||||||
* @return void
|
|
||||||
*/
|
|
||||||
public static function spawn(array $cmd, int $count=8): void
|
|
||||||
{
|
|
||||||
self::getSupervisor()->spawnWorker($cmd, self::getRedisServer(), $count);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sends a closure to be executed by a worker, returns the job ID for the closure.
|
|
||||||
*
|
|
||||||
* @param callable $closure
|
|
||||||
* @return string
|
|
||||||
*/
|
|
||||||
public static function do(callable $closure): string
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
$closure = serialize(new SerializableClosure($closure));
|
|
||||||
}
|
|
||||||
catch(Exception $e)
|
|
||||||
{
|
|
||||||
throw new RuntimeException('Failed to serialize closure.', 2000, $e);
|
|
||||||
}
|
|
||||||
|
|
||||||
$job_packet = new JobPacket();
|
|
||||||
$job_packet->setJobType(JobType::CLOSURE);
|
|
||||||
$job_packet->setEncodingType(EncodingType::SERIALIZED);
|
|
||||||
$job_packet->setPayload($closure);
|
|
||||||
|
|
||||||
// Push as hash using toArray()
|
|
||||||
try
|
|
||||||
{
|
|
||||||
self::getRedisClient()->hMSet($job_packet->getId(), $job_packet->toArray());
|
|
||||||
self::getRedisClient()->expire($job_packet->getId(), 60);
|
|
||||||
self::getRedisClient()->rPush(sprintf('ch%s', $job_packet->getChannel()), $job_packet->getId());
|
|
||||||
}
|
|
||||||
catch(Exception $e)
|
|
||||||
{
|
|
||||||
throw new RuntimeException('Failed to push job to Redis.', 2000, $e);
|
|
||||||
}
|
|
||||||
|
|
||||||
self::addToWatch($job_packet->getId());
|
|
||||||
return $job_packet->getId();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Waits for all jobs to complete.
|
|
||||||
*
|
|
||||||
* @param callable|null $callback
|
|
||||||
* @return void
|
|
||||||
* @throws RedisException
|
|
||||||
*/
|
|
||||||
public static function waitAll(?callable $callback=null): void
|
|
||||||
{
|
|
||||||
while(count(self::$watching_jobs) > 0)
|
|
||||||
{
|
|
||||||
foreach(self::$watching_jobs as $job_id)
|
|
||||||
{
|
|
||||||
if(!self::getRedisClient()->exists($job_id))
|
|
||||||
{
|
|
||||||
unset(self::$watching_jobs[$job_id]);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(!in_array(self::getRedisClient()->hGet($job_id, 'status'), JobStatus::PROCESSING_STATES))
|
|
||||||
{
|
|
||||||
if(!is_null($callback))
|
|
||||||
{
|
|
||||||
$callback(self::getRedisClient()->hGet($job_id, 'return_value'));
|
|
||||||
}
|
|
||||||
|
|
||||||
self::getRedisClient()->del($job_id);
|
|
||||||
unset(self::$watching_jobs[$job_id]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Waits for a job to complete, returns the result.
|
|
||||||
*
|
|
||||||
* @param string $job_id
|
|
||||||
* @param int $timeout
|
|
||||||
* @return mixed
|
|
||||||
* @throws RedisException
|
|
||||||
*/
|
|
||||||
public function waitFor(string $job_id, int $timeout=0)
|
|
||||||
{
|
|
||||||
$timeout_count = time();
|
|
||||||
while(in_array(self::getRedisClient()->hGet($job_id, 'status'), JobStatus::PROCESSING_STATES, true))
|
|
||||||
{
|
|
||||||
if($timeout > 0 && time() - $timeout_count > $timeout)
|
|
||||||
{
|
|
||||||
throw new RuntimeException(sprintf('waitFor %s timed out.', $job_id));
|
|
||||||
}
|
|
||||||
|
|
||||||
usleep(100);
|
|
||||||
}
|
|
||||||
|
|
||||||
$return = self::getRedisClient()->hGet($job_id, 'result');
|
|
||||||
self::getRedisClient()->del($job_id);
|
|
||||||
|
|
||||||
return $return;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets a key from the shared memory.
|
|
||||||
*
|
|
||||||
* @param string $key
|
|
||||||
* @param null $default
|
|
||||||
* @return mixed
|
|
||||||
*/
|
|
||||||
public static function getKey(string $key, $default=null): mixed
|
|
||||||
{
|
|
||||||
if(isset(self::$shared_memory[$key]))
|
|
||||||
{
|
|
||||||
return self::$shared_memory[$key];
|
|
||||||
}
|
|
||||||
|
|
||||||
return $default;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets a key in the shared memory.
|
|
||||||
*
|
|
||||||
* @param string $key
|
|
||||||
* @param mixed $value
|
|
||||||
* @return void
|
|
||||||
*/
|
|
||||||
public static function setKey(string $key, mixed $value): void
|
|
||||||
{
|
|
||||||
self::$shared_memory[$key] = $value;
|
|
||||||
}
|
|
|
@ -1,77 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
/** @noinspection PhpMissingFieldTypeInspection */
|
|
||||||
|
|
||||||
namespace TamerLib\Classes;
|
|
||||||
|
|
||||||
class AdaptiveSleep
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* @var int int
|
|
||||||
*/
|
|
||||||
private $max_sleep_time;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @var array
|
|
||||||
*/
|
|
||||||
private $busy_buffer;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @var int
|
|
||||||
*/
|
|
||||||
private $buffer_size;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @var int
|
|
||||||
*/
|
|
||||||
private $buffer_index;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* AdaptiveSleep constructor.
|
|
||||||
*
|
|
||||||
* @param int $max_sleep_time
|
|
||||||
* @param int $buffer_size
|
|
||||||
*/
|
|
||||||
public function __construct(int $max_sleep_time=500, int $buffer_size=30)
|
|
||||||
{
|
|
||||||
$this->max_sleep_time = $max_sleep_time;
|
|
||||||
$this->busy_buffer = array_fill(0, $buffer_size, false); // Fill the buffer with false values (not busy
|
|
||||||
$this->buffer_size = $buffer_size;
|
|
||||||
$this->buffer_index = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Preforms an adaptive sleep.
|
|
||||||
*
|
|
||||||
* @param bool $busy
|
|
||||||
* @return int
|
|
||||||
*/
|
|
||||||
public function sleep(bool $busy): int
|
|
||||||
{
|
|
||||||
// Add the busy state to the buffer
|
|
||||||
$this->busy_buffer[$this->buffer_index] = $busy;
|
|
||||||
$this->buffer_index = ($this->buffer_index + 1) % $this->buffer_size; // Circular buffer
|
|
||||||
|
|
||||||
// Calculate the average busy state
|
|
||||||
$busy_count = 0;
|
|
||||||
foreach($this->busy_buffer as $busy_state)
|
|
||||||
{
|
|
||||||
if($busy_state)
|
|
||||||
{
|
|
||||||
$busy_count++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
$busy_average = $busy_count / $this->buffer_size;
|
|
||||||
|
|
||||||
// Calculate the sleep time
|
|
||||||
$sleep_time = $this->max_sleep_time * (1 - $busy_average);
|
|
||||||
|
|
||||||
// Sleep
|
|
||||||
if($sleep_time > 0)
|
|
||||||
{
|
|
||||||
usleep($sleep_time);
|
|
||||||
}
|
|
||||||
|
|
||||||
return $sleep_time;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,10 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
namespace TamerLib\Enums;
|
|
||||||
|
|
||||||
final class JobType
|
|
||||||
{
|
|
||||||
public const CLOSURE = 100;
|
|
||||||
|
|
||||||
public const FUNCTION = 200;
|
|
||||||
}
|
|
|
@ -1,9 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
namespace TamerLib\Enums;
|
|
||||||
|
|
||||||
final class WorkerType
|
|
||||||
{
|
|
||||||
public const SCRIPT = 10;
|
|
||||||
public const CLOSURE = 20;
|
|
||||||
}
|
|
|
@ -1,29 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
use TamerLib\Classes\AdaptiveSleep;
|
|
||||||
|
|
||||||
require 'ncc';
|
|
||||||
import('net.nosial.tamerlib');
|
|
||||||
|
|
||||||
$adaptive_sleep = new AdaptiveSleep(10);
|
|
||||||
|
|
||||||
$time = time();
|
|
||||||
while(true)
|
|
||||||
{
|
|
||||||
if(time() - $time > 3)
|
|
||||||
{
|
|
||||||
// Simulate traffic every 3 seconds
|
|
||||||
$sleep = $adaptive_sleep->sleep(random_int(0, 100) < 90);
|
|
||||||
|
|
||||||
if(time() - $time > 5)
|
|
||||||
{
|
|
||||||
// Stop the simulation after 5 seconds
|
|
||||||
$time = time();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// No traffic
|
|
||||||
$sleep = $adaptive_sleep->sleep(false);
|
|
||||||
}
|
|
||||||
}
|
|
Loading…
Add table
Reference in a new issue