Fetch assets in parallel

parallel-fetching
gravel 12 months ago
parent 2abb3a6cd5
commit 147ade1b57
Signed by: gravel
GPG Key ID: C0538F3C906B308F

@ -272,7 +272,7 @@
* Launches all coroutines in parallel.
* @return int CURLM_* status.
*/
public function fetch_all(): int {
public function run_all(): int {
do {
$curlm_status = curl_multi_exec($this->transfers, $curlm_active_transfer);
if ($curlm_active_transfer) {

@ -31,22 +31,15 @@
}
/**
* Fetch the icon of the given room and return its relative path.
* @param \CommunityRoom $room
* @param string $size Image dimensions.
* @return string Relative path or null if icon is absent.
* @return \Generator<int,CurlHandle,CurlHandle|false,void>
*/
function room_icon(\CommunityRoom $room, string $size): ?string {
list($width, $height) = explode("x", $size);
$width = intval($width);
$height = intval($height);
assert(!empty($width) && !empty($height));
function fetch_room_icon_coroutine(\CommunityRoom $room): Generator {
if (room_icon_safety($room) < 0) {
return null;
return;
}
$room_id = $room->get_room_identifier();
$icon_cached = room_icon_path($room_id);
$icon_resized = room_icon_path_resized($room_id, $size);
$icon_expired = file_exists($icon_cached) && filemtime($icon_cached) < strtotime("-1 day");
// Re-fetch icons periodically.
@ -56,7 +49,8 @@
return null;
}
log_debug("Fetching icon for $room_id.");
$icon = file_get_contents($icon_url);
$icon_response = yield from FetchingCoroutine::from_url($icon_url)->run();
$icon = $icon_response ? curl_multi_getcontent($icon_response) : null;
if (empty($icon)) {
log_info("$room_id returned an empty icon.");
}
@ -65,6 +59,33 @@
file_put_contents($icon_cached, $icon);
}
}
}
/**
* Fetch the icon of the given room and return its relative path.
* @param \CommunityRoom $room
* @param string $size Image dimensions.
* @return string Relative path or null if icon is absent.
*/
function room_icon(\CommunityRoom $room, string $size): ?string {
list($width, $height) = explode("x", $size);
$width = intval($width);
$height = intval($height);
assert(!empty($width) && !empty($height));
if (room_icon_safety($room) < 0) {
return null;
}
$room_id = $room->get_room_identifier();
$icon_cached = room_icon_path($room_id);
$icon_resized = room_icon_path_resized($room_id, $size);
$icon_expired = file_exists($icon_cached) && filemtime($icon_cached) < strtotime("-1 day");
if (!file_exists($icon_cached)) {
log_debug("Missing icon asset for $room_id");
return "";
}
if (!file_exists($icon_resized) || $icon_expired) {
$icon_cached_contents = file_get_contents($icon_cached);
if (empty($icon_cached_contents)) {

@ -19,11 +19,9 @@
/**
* Fetch QR invite of the given room and return its relative path.
* @param \CommunityRoom $room
* @return string
* @return \Generator<int,CurlHandle,CurlHandle|false,void>
*/
function room_qr_code($room): string {
function fetch_qr_code_coroutine(\CommunityRoom $room): Generator {
$room_id = $room->get_room_identifier();
$png_cached = room_qr_code_path($room_id);
$image_expired = file_exists($png_cached) &&
@ -32,7 +30,8 @@
return room_qr_code_path_relative($room_id);
}
log_debug("Fetching QR code for $room_id.");
$png = file_get_contents($room->get_invite_url());
$png_response = yield from FetchingCoroutine::from_url($room->get_invite_url())->run();
$png = $png_response ? curl_multi_getcontent($png_response) : null;
if (empty($png)) {
log_warning("$room_id returned an empty QR code.");
}
@ -40,6 +39,19 @@
if (!(file_exists($png_cached) && filesize($png_cached) > 0 && empty($png))) {
file_put_contents($png_cached, $png);
}
}
/**
* Fetch QR invite of the given room and return its relative path.
* @param \CommunityRoom $room
* @return string
*/
function room_qr_code(\CommunityRoom $room): string {
$room_id = $room->get_room_identifier();
if (!file_exists(room_qr_code_path($room_id))) {
log_warning("Missing QR code asset for $room_id.");
return "";
}
return room_qr_code_path_relative($room_id);
}

@ -1,9 +1,11 @@
<?php
include_once "$PROJECT_ROOT/languages/language_flags.php";
require_once "$PROJECT_ROOT/languages/language_flags.php";
include_once "$PROJECT_ROOT/php/servers/known-servers.php";
include_once 'tags.php';
include_once 'fetching-coroutines.php';
require_once "$PROJECT_ROOT/php/servers/known-servers.php";
require_once 'tags.php';
require_once 'fetching-coroutines.php';
require_once 'room-icons.php';
require_once 'room-invites.php';
$MINUTE_SECONDS = 60;
$HOUR_SECONDS = 60 * $MINUTE_SECONDS;
@ -735,7 +737,7 @@
$runner = new FetchingCoroutineRunner($coroutines);
$runner->fetch_all();
$runner->run_all();
return $reachable_servers;
}
@ -918,8 +920,9 @@
foreach ($this->room_hints as $token) {
log_debug("Testing room /$token at $base_url.");
// FIXME: This fetches room hints sequentially per each server
// Note: This fetches room hints sequentially per each server
// Would need to allow yielding handle arrays
// More than good enough for now
$room_api_response = yield from FetchingCoroutine
::from_url($this->get_room_api_url($token))
@ -1082,6 +1085,23 @@
return true;
}
/**
* @param \CommunityServer $servers
*/
public static function fetch_assets(array $servers) {
// Sequential in each server, see note in fetch_room_hints_coroutine()
$coroutines = [];
foreach (CommunityServer::enumerate_rooms($servers) as $room) {
$coroutines[] = new FetchingCoroutine((function() use ($room) {
yield from fetch_qr_code_coroutine($room);
yield from fetch_room_icon_coroutine($room);
})());
}
(new FetchingCoroutineRunner($coroutines))->run_all();
}
/**
* Checks whether this server belongs to Session / OPTF.
*/

@ -1,5 +1,5 @@
<?php
include "$PROJECT_ROOT/php/utils/room-icons.php";
include_once "$PROJECT_ROOT/php/utils/room-icons.php";
/**
* @var \CommunityRoom[] $rooms

@ -13,6 +13,9 @@
// Re-build server instances from cached server data.
$servers = CommunityServer::from_details_array($server_data);
// Fetch all server assets ahead of time.
CommunityServer::fetch_assets($servers);
// List all rooms from the cached servers.
$rooms = CommunityServer::enumerate_rooms($servers);

Loading…
Cancel
Save