xaizek / rocketgit (License: AGPLv3+) (since 2018-12-09)
Light and fast Git hosting solution suitable to serve both as a hub or as a personal code storage with its tickets, pull requests, API and much more.
<root> / scripts / events.php (1b1fa110b6c5d2d77cc3958e04986a9026050c57) (5,557B) (mode 100644) [raw]
<?php
// This is called by cron, and is persistent.
// It takes care of any background job received.
// It will receive signals using a UNIX socket.
// TODO: This will obsolete q.php
error_reporting(E_ALL);
ini_set("track_errors", "On");
set_time_limit(0);

$_s = microtime(TRUE);

require_once("/etc/rocketgit/config.php");

$INC = dirname(__FILE__) . "/../inc";
require_once($INC . "/init.inc.php");
require_once($INC . "/log.inc.php");
require_once($INC . "/sql.inc.php");
require_once($INC . "/struct.inc.php");
require_once($INC . "/events.inc.php");
require_once($INC . "/repo.inc.php");
require_once($INC . "/prof.inc.php");
require_once($INC . "/mr.inc.php");
require_once($INC . "/keys.inc.php");
require_once($INC . "/user.inc.php");
require_once($INC . "/bug.inc.php");
require_once($INC . "/fixes.inc.php");
require_once($INC . "/plan.inc.php");
require_once($INC . "/apikeys.inc.php");
require_once($INC . "/admin.inc.php");
require_once($INC . "/ver.php");

function rg_destroy($key)
{
	global $conn_table;

	if (isset($conn_table['r'][$key]))
		unset($conn_table['r'][$key]);
	if (isset($conn_table['w'][$key]))
		unset($conn_table['w'][$key]);
	if (isset($conn_table['conns'][$key]['socket']))
		if (is_resource($conn_table['conns'][$key]['socket']))
			socket_close($conn_table['conns'][$key]['socket']);
	unset($conn_table['conns'][$key]);
}

function rg_event_send($key, $buf)
{
	global $conn_table;

	$s = &$conn_table['conns'][$key];
	$s['send'] .= $buf;
	$conn_table['w'][$key] = $s['socket'];
}

rg_prof_start("MAIN");

rg_log_set_file($rg_log_dir . "/events.log");
rg_log_set_sid("000000"); // to spread the logs
// We must disable cache, else, we will not receive the updates because
// of the core cache. Do not forget that we are a long live process.
$rg_cache_core_enable = FALSE;

rg_log("Start (ver=$rocketgit_version)...");

rg_sql_app("rg-events");
$db = rg_sql_open($rg_sql);
if ($db === FALSE) {
	rg_internal_error("Cannot connect to database!");
	exit(1);
}

if (rg_struct_ok($db) === FALSE)
	exit(0);

// Remove the socket, else we will get error
if (file_exists($rg_event_socket))
	unlink($rg_event_socket);

// Prepare socket for signaling
$socket = @socket_create(AF_UNIX, SOCK_STREAM, 0);
if ($socket === FALSE) {
	rg_internal_error("Cannot create events socket!");
	exit(1);
}

$r = @socket_bind($socket, $rg_event_socket);
if ($r === FALSE) {
	rg_internal_error("Cannot bind socket!");
	exit(1);
}

$r = @socket_listen($socket, 128);
if ($r === FALSE) {
	rg_internal_error("Cannot set queue length on socket!");
	exit(1);
}

socket_set_nonblock($socket);

$r = chmod($rg_event_socket, 0600);
if ($r === FALSE) {
	rg_internal_error("Cannot set rights on event socket!");
	exit(1);
}

$conn_table = array('r' => array(), 'w' => array(), 'conns' => array());
$conn_table['r']['master'] = $socket;

$original_mtime = @filemtime(__FILE__);
$notify_list = array();
do {
	// Check our mtime so we can upgrade the software and this script
	// will restart.
	clearstatcache();
	$mtime = @filemtime(__FILE__);
	if ($mtime != $original_mtime) {
		rg_log("mtime=$mtime, original_mtime=$original_mtime");
		rg_log("File changed. Exiting...");
		break;
	}

	$r = 0;
	do {
		// check machine load - if too big we will delay
		$load = rg_load();
		if ($load > 200) {
			rg_log("Load too big! Skip queue processing.");
			break;
		}

		$r = rg_event_process_queue($db, $notify_list);
		if ($r === FALSE)
			break;
	} while ($r > 0);
	if ($r === FALSE)
		break;

	// Wait for signal
	rg_log("Waiting for signal...");
	$r2 = $conn_table['r'];
	$w2 = $conn_table['w'];
	$e2 = array();
	$r = @socket_select($r2, $w2, $e2, 10);
	if ($r === FALSE)
		rg_fatal('Cannot select: '
			. socket_strerror(socket_last_error()));
	if ($r == 0)
		continue;

	//rg_log_ml('conn_table: ' . print_r($conn_table, TRUE));
	foreach ($r2 as $key => $sock) {
		if (strcmp($key, "master") == 0) {
			$client = @socket_accept($sock);
			if ($client === FALSE) {
				rg_log("Connection seems broken!");
				continue;
			}

			socket_set_nonblock($client);
			$key = intval($client);
			$conn_table['conns'][$key] = array(
				'socket' => $client,
				'send' => '',
				'recv' => '');
			$conn_table['r'][$key] = $client;
			continue;
		}

		$r = @socket_recv($sock, $buf, 1024, 0);
		if ($r === FALSE) {
			rg_log($key . ': Error in recv: '
				. socket_strerror(socket_last_error()));
			rg_destroy($key);
			continue;
		}
		if ($r === 0) { // remote close the connection
			rg_log($key . ": Remote closed the connection (received 0).");
			rg_destroy($key);
			continue;
		}

		$s = &$conn_table['conns'][$key];
		$s['recv'] .= $buf;
		if (!strstr($buf, "\n"))
			continue;
		rg_log($key . ': RECEIVED: ' . $s['recv']);
		if (strncmp($s['recv'], 'NOTIFY ', 7) == 0) {
			$ev_id = trim(substr($s['recv'], 7));
			$notify_list[$ev_id][] = array(
				'priv' => $key,
				'func' => 'rg_event_send');
		}
		$s['recv'] = '';
	}

	foreach ($w2 as $key => $sock) {
		if (!isset($conn_table['conns'][$key]))
			continue;

		$s = &$conn_table['conns'][$key];
		$ret = @socket_send($s['socket'], $s['send'], strlen($s['send']), 0);
		if ($ret === FALSE) {
			rg_log($key . ": Cannot send: " . socket_strerror(socket_last_error()));
			rg_destroy($key);
			continue;
		}

		$s['send'] = substr($s['send'], $ret);
		if (empty($s['send']))
			unset($conn_table['w'][$key]);
	}

	//rg_log_ml("e2: " . print_r($e2, TRUE));
	foreach ($e2 as $key => $sock)
		rg_destroy($key);
} while (1);

@socket_close($socket);

rg_log("Exiting...");

rg_prof_end("MAIN");
rg_prof_log();
Hints

Before first commit, do not forget to setup your git environment:
git config --global user.name "your_name_here"
git config --global user.email "your@email_here"

Clone this repository using HTTP(S):
git clone https://code.reversed.top/user/xaizek/rocketgit

Clone this repository using ssh (do not forget to upload a key first):
git clone ssh://rocketgit@code.reversed.top/user/xaizek/rocketgit

You are allowed to anonymously push to this repository.
This means that your pushed commits will automatically be transformed into a pull request:
... clone the repository ...
... make some changes and some commits ...
git push origin master