- Added caching_relays unified table with live_enabled/backfill_enabled columns - Separated --reset-backfill from --start-caching as independent flags - Removed redundant caching_enabled master setting; daemon derives from live/backfill - Set caching_inbox_enabled=true by default; removed Inbox toggle from Backfill page - Set caching_live_strategy=cache_all by default - Fixed outbox relay discovery to store ALL discovered relays, not just covering set - Added store_kind_0_information config (default: true) to gate profile sync trigger - Regenerated pg_schema.h from pg_schema.sql to include caching_relays table - Fixed process toggle button styling to match monochrome aesthetic - Fixed radio button styling to match black/white/red theme - Simplified Backfill page: removed Service Status and Inbox Status sections - Backfill status now respects config setting, not just daemon state - Admin config API now bumps caching_config_generation for caching-related changes - make_and_restart_relay.sh now resets PostgreSQL schema on fresh restart
151 lines
7.0 KiB
PHP
151 lines
7.0 KiB
PHP
<?php
|
|
/** admin2/api/live_subscription.php — Live subscription config API. */
|
|
require_once __DIR__ . '/../lib/helpers.php';
|
|
$pdo = db();
|
|
|
|
// --- POST actions: update live subscription config ---
|
|
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
|
|
$input = json_decode(file_get_contents('php://input'), true) ?: [];
|
|
$action = $input['action'] ?? '';
|
|
|
|
if ($action === 'toggle_enabled') {
|
|
// Toggle caching_live_enabled. The relay's config-change listener
|
|
// starts/stops caching_relay based on live OR backfill settings.
|
|
try {
|
|
$current = $pdo->query("SELECT value FROM config WHERE key = 'caching_live_enabled'")->fetchColumn();
|
|
$newVal = ($current === 'true') ? 'false' : 'true';
|
|
$dataType = 'boolean';
|
|
$stmt = $pdo->prepare("INSERT INTO config (key, value, data_type) VALUES ('caching_live_enabled', ?, ?)
|
|
ON CONFLICT (key) DO UPDATE SET value = EXCLUDED.value, updated_at = EXTRACT(EPOCH FROM NOW())::BIGINT");
|
|
$stmt->execute([$newVal, $dataType]);
|
|
// Bump config generation to trigger hot-reload
|
|
$pdo->exec("UPDATE config SET value = (COALESCE(value::int, 0) + 1)::text, updated_at = EXTRACT(EPOCH FROM NOW())::BIGINT
|
|
WHERE key = 'caching_config_generation'");
|
|
json_response(['ok' => true, 'enabled' => $newVal === 'true']);
|
|
} catch (PDOException $e) {
|
|
json_response(['ok' => false, 'error' => $e->getMessage()], 500);
|
|
}
|
|
} elseif ($action === 'save_config') {
|
|
$strategy = $input['strategy'] ?? '';
|
|
$kinds = $input['kinds'] ?? '';
|
|
$since = $input['since_seconds'] ?? '';
|
|
$limit = $input['limit'] ?? '';
|
|
|
|
try {
|
|
$pdo->beginTransaction();
|
|
if ($strategy === 'whitelist' || $strategy === 'cache_all') {
|
|
$stmt = $pdo->prepare("INSERT INTO config (key, value, data_type) VALUES ('caching_live_strategy', ?, 'string')
|
|
ON CONFLICT (key) DO UPDATE SET value = EXCLUDED.value, updated_at = EXTRACT(EPOCH FROM NOW())::BIGINT");
|
|
$stmt->execute([$strategy]);
|
|
}
|
|
if ($kinds !== '') {
|
|
$stmt = $pdo->prepare("INSERT INTO config (key, value, data_type) VALUES ('caching_live_kinds', ?, 'string')
|
|
ON CONFLICT (key) DO UPDATE SET value = EXCLUDED.value, updated_at = EXTRACT(EPOCH FROM NOW())::BIGINT");
|
|
$stmt->execute([$kinds]);
|
|
}
|
|
if ($since !== '') {
|
|
$stmt = $pdo->prepare("INSERT INTO config (key, value, data_type) VALUES ('caching_live_since_seconds', ?, 'integer')
|
|
ON CONFLICT (key) DO UPDATE SET value = EXCLUDED.value, updated_at = EXTRACT(EPOCH FROM NOW())::BIGINT");
|
|
$stmt->execute([(string)(int)$since]);
|
|
}
|
|
if ($limit !== '') {
|
|
$stmt = $pdo->prepare("INSERT INTO config (key, value, data_type) VALUES ('caching_live_limit', ?, 'integer')
|
|
ON CONFLICT (key) DO UPDATE SET value = EXCLUDED.value, updated_at = EXTRACT(EPOCH FROM NOW())::BIGINT");
|
|
$stmt->execute([(string)(int)$limit]);
|
|
}
|
|
// Bump config generation to trigger hot-reload
|
|
$pdo->exec("UPDATE config SET value = (COALESCE(value::int, 0) + 1)::text, updated_at = EXTRACT(EPOCH FROM NOW())::BIGINT
|
|
WHERE key = 'caching_config_generation'");
|
|
$pdo->commit();
|
|
json_response(['ok' => true, 'message' => 'Live subscription config saved.']);
|
|
} catch (PDOException $e) {
|
|
$pdo->rollBack();
|
|
json_response(['ok' => false, 'error' => $e->getMessage()], 500);
|
|
}
|
|
} elseif ($action === 'toggle_relay') {
|
|
// Toggle live_enabled or backfill_enabled for a relay in caching_relays
|
|
$relay_url = $input['relay_url'] ?? '';
|
|
$column = $input['column'] ?? '';
|
|
if ($relay_url === '' || !in_array($column, ['live_enabled', 'backfill_enabled'])) {
|
|
json_response(['ok' => false, 'error' => 'Invalid relay_url or column'], 400);
|
|
exit;
|
|
}
|
|
try {
|
|
$stmt = $pdo->prepare("UPDATE caching_relays SET $column = NOT $column, updated_at = EXTRACT(EPOCH FROM NOW())::BIGINT WHERE relay_url = ?");
|
|
$stmt->execute([$relay_url]);
|
|
// Bump config generation to trigger hot-reload
|
|
$pdo->exec("UPDATE config SET value = (COALESCE(value::int, 0) + 1)::text, updated_at = EXTRACT(EPOCH FROM NOW())::BIGINT
|
|
WHERE key = 'caching_config_generation'");
|
|
json_response(['ok' => true, 'message' => 'Relay toggled.']);
|
|
} catch (PDOException $e) {
|
|
json_response(['ok' => false, 'error' => $e->getMessage()], 500);
|
|
}
|
|
} else {
|
|
json_response(['ok' => false, 'error' => 'Unknown action'], 400);
|
|
}
|
|
exit;
|
|
}
|
|
|
|
// --- GET: return current live subscription config + status ---
|
|
$config = [];
|
|
try {
|
|
$cfg_rows = $pdo->query("SELECT key, value FROM config WHERE key IN (
|
|
'caching_live_strategy','caching_live_kinds','caching_live_since_seconds',
|
|
'caching_live_limit','caching_live_enabled',
|
|
'caching_kinds','caching_bootstrap_relays'
|
|
)")->fetchAll();
|
|
foreach ($cfg_rows as $r) { $config[$r['key']] = $r['value']; }
|
|
} catch (PDOException $e) {}
|
|
|
|
// Live subscription status from caching_service_state
|
|
$state = [];
|
|
try { $state = $pdo->query("SELECT * FROM caching_service_state WHERE id = 1")->fetch() ?: []; } catch (PDOException $e) {}
|
|
|
|
// Unified relay list from caching_relays table
|
|
$relays = [];
|
|
try {
|
|
$relays = $pdo->query("
|
|
SELECT relay_url, live_enabled, backfill_enabled, status_code, status_text, follow_count, is_bootstrap
|
|
FROM caching_relays
|
|
ORDER BY follow_count DESC, relay_url
|
|
")->fetchAll();
|
|
} catch (PDOException $e) {}
|
|
|
|
// If caching_relays table is empty (migration not yet run), fall back to old sources
|
|
if (empty($relays)) {
|
|
// Upstream relay status (old table)
|
|
$upstreamRelays = [];
|
|
try {
|
|
$upstreamRelays = $pdo->query("
|
|
SELECT relay_url, status_code, status_text, updated_at
|
|
FROM caching_upstream_relays
|
|
ORDER BY relay_url
|
|
")->fetchAll();
|
|
} catch (PDOException $e) {}
|
|
|
|
// Discovered relays with follow counts (from backfill progress)
|
|
$discoveredRelays = [];
|
|
try {
|
|
$discoveredRelays = $pdo->query("
|
|
SELECT relay_url, COUNT(DISTINCT author_pubkey) AS follow_count
|
|
FROM caching_backfill_relay_progress
|
|
GROUP BY relay_url
|
|
ORDER BY follow_count DESC, relay_url
|
|
")->fetchAll();
|
|
} catch (PDOException $e) {}
|
|
|
|
json_response([
|
|
'config' => $config,
|
|
'state' => $state,
|
|
'upstreamRelays' => $upstreamRelays,
|
|
'discoveredRelays' => $discoveredRelays,
|
|
'relays' => [],
|
|
]);
|
|
} else {
|
|
json_response([
|
|
'config' => $config,
|
|
'state' => $state,
|
|
'relays' => $relays,
|
|
]);
|
|
}
|