Files

124 lines
6.2 KiB
PHP

<?php
/** admin2/api/caching.php — Caching service status + follows + reset actions. */
require_once __DIR__ . '/../lib/helpers.php';
$pdo = db();
// --- POST actions: reset backfill (all or per-user) ---
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$input = json_decode(file_get_contents('php://input'), true) ?: [];
$action = $input['action'] ?? '';
$pubkey = $input['pubkey'] ?? '';
if ($action === 'reset_all') {
// Reset backfill progress for ALL followed authors, then bump config
// generation so the running caching service hot-reloads and re-drains.
try {
$pdo->beginTransaction();
$pdo->exec("UPDATE caching_followed_pubkeys
SET until_cursor = 0, backfill_complete = FALSE,
events_fetched = 0,
updated_at = EXTRACT(EPOCH FROM NOW())::BIGINT");
// Also reset per-relay progress rows
$pdo->exec("UPDATE caching_backfill_relay_progress
SET complete = FALSE, events_fetched = 0,
until_cursor = 0, last_status = 'reset',
consecutive_errors = 0,
updated_at = EXTRACT(EPOCH FROM NOW())::BIGINT");
// Bump config generation to trigger hot-reload
$pdo->exec("UPDATE config SET value = (COALESCE(value::int, 0) + 1)::text
WHERE key = 'caching_config_generation'");
$pdo->commit();
json_response(['ok' => true, 'message' => 'All backfill progress reset. Caching service will re-drain.']);
} catch (PDOException $e) {
$pdo->rollBack();
json_response(['ok' => false, 'error' => $e->getMessage()], 500);
}
} elseif ($action === 'reset_user' && $pubkey) {
// Reset backfill progress for a single followed author.
try {
$pdo->beginTransaction();
$stmt = $pdo->prepare("UPDATE caching_followed_pubkeys
SET until_cursor = 0, backfill_complete = FALSE,
events_fetched = 0,
updated_at = EXTRACT(EPOCH FROM NOW())::BIGINT
WHERE pubkey = ?");
$stmt->execute([$pubkey]);
// Also reset per-relay progress for this author
$stmt2 = $pdo->prepare("UPDATE caching_backfill_relay_progress
SET complete = FALSE, events_fetched = 0,
until_cursor = 0, last_status = 'reset',
consecutive_errors = 0,
updated_at = EXTRACT(EPOCH FROM NOW())::BIGINT
WHERE author_pubkey = ?");
$stmt2->execute([$pubkey]);
// Bump config generation to trigger hot-reload
$pdo->exec("UPDATE config SET value = (COALESCE(value::int, 0) + 1)::text
WHERE key = 'caching_config_generation'");
$pdo->commit();
json_response(['ok' => true, 'message' => "Backfill reset for pubkey. Caching service will re-fetch."]);
} catch (PDOException $e) {
$pdo->rollBack();
json_response(['ok' => false, 'error' => $e->getMessage()], 500);
}
} else {
json_response(['ok' => false, 'error' => 'Unknown action'], 400);
}
exit;
}
// Caching config values (for toggle controls)
$config = [];
try {
$cfg_rows = $pdo->query("SELECT key, value FROM config WHERE key IN ('caching_enabled','caching_inbox_enabled','caching_live_enabled','caching_backfill_enabled')")->fetchAll();
foreach ($cfg_rows as $r) { $config[$r['key']] = $r['value']; }
} catch (PDOException $e) {}
// Service state
$state = [];
try { $state = $pdo->query("SELECT * FROM caching_service_state WHERE id = 1")->fetch() ?: []; } catch (PDOException $e) {}
// Active target
$active = ['pubkey' => '', 'relay' => ''];
try { $active = $pdo->query("SELECT active_pubkey AS pubkey, active_relay AS relay FROM caching_backfill_active WHERE id = 1")->fetch() ?: $active; } catch (PDOException $e) {}
// Inbox
$inbox = ['pending' => 0, 'live' => 0, 'backfill' => 0];
try {
$inbox = $pdo->query("SELECT COUNT(*) AS pending, COUNT(*) FILTER (WHERE source_class='live') AS live, COUNT(*) FILTER (WHERE source_class='backfill') AS backfill FROM caching_event_inbox")->fetch() ?: $inbox;
} catch (PDOException $e) {}
// Follows (paginated, with names from profiles cache + per-relay progress)
$follows = [];
try {
$follows = $pdo->query("
SELECT fp.pubkey, fp.is_root, fp.backfill_complete, fp.events_fetched,
fp.last_event_at,
p.name, p.display_name,
(SELECT count(*) FROM events WHERE pubkey = fp.pubkey) AS total_events,
(SELECT count(*) FROM caching_backfill_relay_progress WHERE author_pubkey = fp.pubkey) AS relay_count,
(SELECT count(*) FROM caching_backfill_relay_progress WHERE author_pubkey = fp.pubkey AND complete = false) AS relay_incomplete
FROM caching_followed_pubkeys fp
LEFT JOIN profiles p ON p.pubkey = fp.pubkey
ORDER BY fp.is_root DESC, fp.events_fetched DESC LIMIT 1000
")->fetchAll();
// Fetch per-relay progress for all followed pubkeys in one query
$relayProgress = [];
try {
$rpRows = $pdo->query("
SELECT author_pubkey, relay_url, complete, events_fetched, until_cursor, last_status, updated_at
FROM caching_backfill_relay_progress
ORDER BY author_pubkey, events_fetched DESC
")->fetchAll();
foreach ($rpRows as $rp) {
$relayProgress[$rp['author_pubkey']][] = $rp;
}
} catch (PDOException $e) {}
foreach ($follows as &$f) {
$f['name'] = profile_display_name($f);
$f['npub'] = function_exists('hex_to_npub') ? hex_to_npub($f['pubkey']) : substr($f['pubkey'], 0, 20);
$f['relays'] = $relayProgress[$f['pubkey']] ?? [];
}
} catch (PDOException $e) {}
json_response(['state' => $state, 'active' => $active, 'inbox' => $inbox, 'follows' => $follows, 'config' => $config]);