Files
c-relay-pg/admin/api/live_subscription.php
T
Laan Tungir ca7a4b6722 v2.1.36 - Unified relay table, caching/backfill separation, inbox defaults, profile gating, and UI fixes
- 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
2026-08-03 19:37:09 -04:00

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,
]);
}