v2.1.41 - Fix caching daemon reconnect: support max_reconnect_attempts<=0 as infinite, use infinite retries in caching_relay upstream and sink pools to prevent permanent relay abandonment in long-running daemons; add production admin systemd unit (port 7077) and wire into deploy_local.sh

This commit is contained in:
Laan Tungir
2026-08-20 10:54:30 -04:00
parent eeb22e3ed3
commit 5457fde653
8 changed files with 62067 additions and 250 deletions
+1 -1
View File
@@ -1 +1 @@
[{"kind":1,"count":38472,"pct":72.5},{"kind":6,"count":7126,"pct":13.4},{"kind":10002,"count":3427,"pct":6.5},{"kind":0,"count":1984,"pct":3.7},{"kind":4,"count":623,"pct":1.2},{"kind":3,"count":578,"pct":1.1},{"kind":30023,"count":251,"pct":0.5},{"kind":30078,"count":196,"pct":0.4},{"kind":5,"count":94,"pct":0.2},{"kind":10000,"count":80,"pct":0.2},{"kind":1311,"count":59,"pct":0.1},{"kind":36787,"count":24,"pct":0},{"kind":7,"count":24,"pct":0},{"kind":30267,"count":22,"pct":0},{"kind":7376,"count":20,"pct":0},{"kind":1059,"count":18,"pct":0},{"kind":7375,"count":16,"pct":0},{"kind":30004,"count":10,"pct":0},{"kind":9999,"count":8,"pct":0},{"kind":9321,"count":8,"pct":0}]
[{"kind":1,"count":1333690,"pct":78.1},{"kind":6,"count":220490,"pct":12.9},{"kind":10002,"count":59276,"pct":3.5},{"kind":0,"count":49519,"pct":2.9},{"kind":5,"count":30179,"pct":1.8},{"kind":3,"count":6272,"pct":0.4},{"kind":30023,"count":2965,"pct":0.2},{"kind":10000,"count":1246,"pct":0.1},{"kind":4,"count":1169,"pct":0.1},{"kind":7,"count":1078,"pct":0.1},{"kind":1311,"count":1021,"pct":0.1},{"kind":30078,"count":278,"pct":0},{"kind":7376,"count":238,"pct":0},{"kind":30211,"count":103,"pct":0},{"kind":7375,"count":76,"pct":0},{"kind":30004,"count":38,"pct":0},{"kind":1018,"count":24,"pct":0},{"kind":9321,"count":24,"pct":0},{"kind":36787,"count":24,"pct":0},{"kind":30267,"count":22,"pct":0}]
+1 -1
View File
@@ -1 +1 @@
[{"pubkey":"4c800257a588a82849d049817c2bdaad984b25a45ad9f6dad66e47d3b47e3b2f","name":"mleku","count":7936,"pct":15},{"pubkey":"82341f882b6eabcd2ba7f1ef90aad961cf074af15b9ef44a09f9d2a8fbfbe6a2","name":"jack","count":6486,"pct":12.2},{"pubkey":"460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c","name":"Vitor Pamplona","count":4604,"pct":8.7},{"pubkey":"1ec454734dcbf6fe54901ce25c0c7c6bca5edd89443416761fadc321d38df139","name":"Laan Tungir","count":3765,"pct":7.1},{"pubkey":"4d7842051782e0d3feb034d150adc2b6bae4ee3b49786793bffa468b6f5b96b3","name":"FLASH","count":2994,"pct":5.6},{"pubkey":"fa984bd7dbb282f07e16e7ae87b26a2a7b9b90b7246a44771f0cf5ae58018f52","name":"PABLOF7z","count":1938,"pct":3.7},{"pubkey":"8ff74724ed641b3c28e5a86d7c5cbc49c37638ace8c6c38935860e7a5eedde0e","name":"WSB","count":1440,"pct":2.7},{"pubkey":"d623a581b314ba983e1e78ef907adce0e58141ce4b69d63678b0bcc4f752cec2","name":"","count":274,"pct":0.5},{"pubkey":"a13d0cca4316d76227dcaabc59d22a0bd63ad73d723355c3645c66408dc9223a","name":"","count":221,"pct":0.4},{"pubkey":"40a7c2e18da5c6c1102d51516c44ac670c3d6f56eee8dfe5066c353f0f157e9e","name":"","count":195,"pct":0.4},{"pubkey":"08c6657385c506f242a0f4474b9fd4f0cbd488544972df116910b79d3e5b72b2","name":"\u957f\u6bdb\u8c61\u516c\u5171\u65f6\u95f4\u7ebf\u540c\u6b65","count":170,"pct":0.3},{"pubkey":"f61151f6e2777f003f6b2930476e69970ae8908fe5e696bbf241249ebe4fdf39","name":"","count":158,"pct":0.3},{"pubkey":"c239c0f994c471c9a1e0d22b14255d956923cfbc7ce7aac653aceb2bfa4a5015","name":"HODLR","count":147,"pct":0.3},{"pubkey":"2498d6911a1d61c2d4c801a48a3c1c541aadcd90f402d45822e16dc124394686","name":"","count":133,"pct":0.3},{"pubkey":"73e8a4874935df1ba0cbd3a359a1ae19915cdb17748e3998d26fd24cf6b9c779","name":"","count":126,"pct":0.2},{"pubkey":"07180924339a86e8cc9cfb98a4209c294980b65f0853041da3cef7a64d0f179a","name":"","count":120,"pct":0.2},{"pubkey":"5e42c5c7fc24daec53612602033ef3bc55055156e4d556811dbcb18a0634554f","name":"","count":117,"pct":0.2},{"pubkey":"4e833a634da2de63cf765f8c586308a708fb98785985e37d605547e166cdb92d","name":"","count":108,"pct":0.2},{"pubkey":"b3e43e8cc7e6dff23a33d9213a3e912d895b1c3e4250240e0c99dbefe3068b5f","name":"kojira","count":101,"pct":0.2},{"pubkey":"f7a13d555e526369377d27ec13515d4eb18227a3974ef75bad88690cd018f68a","name":"","count":100,"pct":0.2}]
[{"pubkey":"77cc1725d92c109c31a62a9e6199b86fbee1ff678e40e4251eaaaadb13949d1f","name":"","count":37930,"pct":2.2},{"pubkey":"1ec454734dcbf6fe54901ce25c0c7c6bca5edd89443416761fadc321d38df139","name":"Laan Tungir","count":34867,"pct":2},{"pubkey":"460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c","name":"Vitor Pamplona","count":26606,"pct":1.6},{"pubkey":"f8e6c64342f1e052480630e27e1016dce35fc3a614e60434fef4aa2503328ca9","name":"corndalorian","count":19536,"pct":1.1},{"pubkey":"18905d0a5d623ab81a98ba98c582bd5f57f2506c6b808905fc599d5a0b229b08","name":"node","count":16211,"pct":0.9},{"pubkey":"d3d74124ddfb5bdc61b8f18d17c3335bbb4f8c71182a35ee27314a49a4eb7b1d","name":"average_gary","count":15968,"pct":0.9},{"pubkey":"44dc1c2db9c3fbd7bee9257eceb52be3cf8c40baf7b63f46e56b58a131c74f0b","name":"Enki","count":14508,"pct":0.8},{"pubkey":"adc14fa3ad590856dd8b80815d367f7c1e6735ad00fd98a86d002fbe9fb535e1","name":"Contra","count":13767,"pct":0.8},{"pubkey":"296842eaaed9be5ae0668da09fe48aac0521c4af859ad547d93145e5ac34c17e","name":"franny","count":12858,"pct":0.8},{"pubkey":"7cc328a08ddb2afdf9f9be77beff4c83489ff979721827d628a542f32a247c0e","name":"cloud fodder","count":11721,"pct":0.7},{"pubkey":"32e1827635450ebb3c5a7d12c1f8e7b2b514439ac10a67eef3d9fd9c5c68e245","name":"jb55","count":11547,"pct":0.7},{"pubkey":"2efaa715bbb46dd5be6b7da8d7700266d11674b913b8178addb5c2e63d987331","name":"vinney...axkl","count":11526,"pct":0.7},{"pubkey":"1e67de3754171071d3cf9b44b6e546bd94fd0a2ca3fb4dbbb1b054685c9116e4","name":"Renaud Lifchitz","count":11126,"pct":0.7},{"pubkey":"b2d670de53b27691c0c3400225b65c35a26d06093bcc41f48ffc71e0907f9d4a","name":"0xtr","count":10848,"pct":0.6},{"pubkey":"c6f7077f1699d50cf92a9652bfebffac05fc6842b9ee391089d959b8ad5d48fd","name":"iefan \ud83d\udd4a\ufe0f","count":10573,"pct":0.6},{"pubkey":"604e96e099936a104883958b040b47672e0f048c98ac793f37ffe4c720279eb2","name":"NotBiebs and 69 others","count":10292,"pct":0.6},{"pubkey":"9989500413fb756d8437912cc32be0730dbe1bfc6b5d2eef759e1456c239f905","name":"nostr.build","count":10252,"pct":0.6},{"pubkey":"4eb88310d6b4ed95c6d66a395b3d3cf559b85faec8f7691dafd405a92e055d6d","name":"Ava","count":10145,"pct":0.6},{"pubkey":"a44dbc9aaa357176a7d4f5c3106846ea096b66de0b50ee39aff54baab6c4bf4b","name":"Ben Justman\ud83c\udf77","count":10138,"pct":0.6},{"pubkey":"ee6ea13ab9fe5c4a68eaf9b1a34fe014a66b40117c50ee2a614f4cda959b6e74","name":"Dr. The Daniel \ud83d\udd96","count":9795,"pct":0.6}]
+61963 -238
View File
File diff suppressed because it is too large Load Diff
+11 -2
View File
@@ -258,8 +258,17 @@ int main(int argc, char **argv) {
cr_pubkey_set_t followed;
cr_pubkey_set_init(&followed);
/* Upstream pool. */
nostr_relay_pool_t *upstream = nostr_relay_pool_create(nostr_pool_reconnect_config_default());
/* Upstream pool.
* Use infinite reconnect attempts (max_reconnect_attempts = 0) so that
* a relay which goes down and fails to reconnect is retried forever at
* the capped backoff interval (30s). Without this, the default
* max_reconnect_attempts=10 permanently abandons a relay after ~3
* minutes of failures, which is fatal for a long-running daemon —
* the live subscription silently stops receiving events and the
* only fix is a process restart. */
nostr_pool_reconnect_config_t upstream_reconnect_cfg = *nostr_pool_reconnect_config_default();
upstream_reconnect_cfg.max_reconnect_attempts = 0; /* 0 = infinite */
nostr_relay_pool_t *upstream = nostr_relay_pool_create(&upstream_reconnect_cfg);
if (!upstream) {
DEBUG_ERROR("failed to create upstream pool");
return 1;
+5 -1
View File
@@ -41,7 +41,11 @@ int cr_sink_init(cr_sink_t *sink, const char *local_relay_url, cr_seen_ring_t *s
sink->source_class = CR_SINK_CLASS_LIVE;
strncpy(sink->url, local_relay_url, sizeof(sink->url) - 1);
sink->pool = nostr_relay_pool_create(nostr_pool_reconnect_config_default());
/* Use infinite reconnect attempts so the sink (local relay connection)
* never permanently gives up if the local relay restarts. */
nostr_pool_reconnect_config_t sink_reconnect_cfg = *nostr_pool_reconnect_config_default();
sink_reconnect_cfg.max_reconnect_attempts = 0; /* 0 = infinite */
sink->pool = nostr_relay_pool_create(&sink_reconnect_cfg);
if (!sink->pool) {
DEBUG_ERROR("sink: failed to create pool");
return -1;
+32 -5
View File
@@ -36,6 +36,9 @@ INSTALLED_SERVICE_PATH="/etc/systemd/system/${SERVICE_NAME}.service"
LOCAL_ADMIN_DIR="admin"
PROD_ADMIN_DIR="admin_prod"
PROD_ADMIN_PORT=7077
ADMIN_SERVICE_NAME="c-relay-pg-admin-prod"
ADMIN_SERVICE_FILE="systemd/c-relay-pg-admin-prod.service"
INSTALLED_ADMIN_SERVICE_PATH="/etc/systemd/system/${ADMIN_SERVICE_NAME}.service"
# Database config (must match the service file ExecStart)
DB_HOST="127.0.0.1"
@@ -188,14 +191,38 @@ if [ -f "${PROD_ADMIN_DIR}/lib/config.php.prod" ]; then
fi
success "Admin dashboard synced"
# --- Restart production admin PHP server ---
info "Restarting production admin PHP server on port ${PROD_ADMIN_PORT}..."
# --- Install/update the production admin systemd unit ---
# The admin dashboard runs as a system systemd service (c-relay-pg-admin-prod)
# so it persists across reboots and is managed alongside the relay.
ADMIN_SERVICE_NEEDS_INSTALL=0
if [ "$ACTION" = "install" ]; then
ADMIN_SERVICE_NEEDS_INSTALL=1
elif [ ! -f "$INSTALLED_ADMIN_SERVICE_PATH" ]; then
warn "Admin service file not installed at $INSTALLED_ADMIN_SERVICE_PATH"
ADMIN_SERVICE_NEEDS_INSTALL=1
elif ! diff -q "$ADMIN_SERVICE_FILE" "$INSTALLED_ADMIN_SERVICE_PATH" >/dev/null 2>&1; then
warn "Admin service file has changed, updating $INSTALLED_ADMIN_SERVICE_PATH"
ADMIN_SERVICE_NEEDS_INSTALL=1
fi
if [ "$ADMIN_SERVICE_NEEDS_INSTALL" -eq 1 ]; then
info "Installing admin service file to $INSTALLED_ADMIN_SERVICE_PATH"
sudo cp "$ADMIN_SERVICE_FILE" "$INSTALLED_ADMIN_SERVICE_PATH"
sudo chown root:root "$INSTALLED_ADMIN_SERVICE_PATH"
sudo chmod 644 "$INSTALLED_ADMIN_SERVICE_PATH"
sudo systemctl daemon-reload
success "Admin service file installed and daemon reloaded"
fi
# --- Restart production admin PHP server (via systemd) ---
info "Restarting production admin service ${ADMIN_SERVICE_NAME} on port ${PROD_ADMIN_PORT}..."
# Kill any stray non-systemd PHP server on the admin port (e.g. from admin/serve.sh)
pkill -f "php -S 127.0.0.1:${PROD_ADMIN_PORT}" 2>/dev/null || true
sleep 1
setsid php -S 127.0.0.1:${PROD_ADMIN_PORT} -t "${PROD_ADMIN_DIR}" > "${PROD_ADMIN_DIR}/php_server.log" 2>&1 < /dev/null &
disown $! 2>/dev/null
sudo systemctl enable "${ADMIN_SERVICE_NAME}" >/dev/null 2>&1 || true
sudo systemctl restart "${ADMIN_SERVICE_NAME}"
sleep 1
success "Production admin PHP server restarted on http://127.0.0.1:${PROD_ADMIN_PORT}"
success "Production admin service restarted on http://127.0.0.1:${PROD_ADMIN_PORT}"
# --- Enable and start the service ---
info "Enabling and starting ${SERVICE_NAME}..."
+2 -2
View File
@@ -13,8 +13,8 @@
// Using CRELAY_ prefix to avoid conflicts with nostr_core_lib VERSION macros
#define CRELAY_VERSION_MAJOR 2
#define CRELAY_VERSION_MINOR 1
#define CRELAY_VERSION_PATCH 40
#define CRELAY_VERSION "v2.1.40"
#define CRELAY_VERSION_PATCH 41
#define CRELAY_VERSION "v2.1.41"
// Relay metadata (authoritative source for NIP-11 information)
#define RELAY_NAME "C-Relay-PG"
+52
View File
@@ -0,0 +1,52 @@
[Unit]
Description=C-Relay-PG Production Admin Dashboard (PHP built-in server on port 7077)
Documentation=https://git.laantungir.net/laantungir/c-relay-pg.git
After=network.target network-online.target postgresql.service c-relay-pg-local.service
Wants=network-online.target
Requires=postgresql.service
# Start after the production relay so the dashboard has a live backend to admin.
Requires=c-relay-pg-local.service
[Service]
Type=simple
User=user
Group=user
WorkingDirectory=/home/user/lt/c-relay-pg/admin_prod
ExecStart=/usr/bin/php -S 127.0.0.1:7077 -t /home/user/lt/c-relay-pg/admin_prod
Restart=always
RestartSec=5
StandardOutput=journal
StandardError=journal
SyslogIdentifier=c-relay-pg-admin-prod
# Environment — point the PHP admin at the PRODUCTION database.
# admin/lib/config.php reads these; defaults to crelay_prod, set explicitly
# so the unit is self-documenting and survives future config.php changes.
Environment=C_RELAY_DB_HOST=127.0.0.1
Environment=C_RELAY_DB_PORT=5432
Environment=C_RELAY_DB_NAME=crelay_prod
Environment=C_RELAY_DB_USER=crelay
Environment=C_RELAY_DB_PASSWORD=crelay
# Security settings
NoNewPrivileges=true
ProtectSystem=strict
ProtectHome=false
ReadWritePaths=/home/user/lt/c-relay-pg/admin_prod
PrivateTmp=true
ProtectKernelTunables=true
ProtectKernelModules=true
ProtectControlGroups=true
# Network security — only needs loopback for the PHP server and PG socket.
PrivateNetwork=false
RestrictAddressFamilies=AF_UNIX AF_INET AF_INET6
# Resource limits — must be high enough to spawn php under user 'user'
# which already runs many processes (relay, caching, etc.). A low NPROC
# here causes EAGAIN ("Resource temporarily unavailable") on exec.
LimitNOFILE=65536
LimitNPROC=4096
[Install]
WantedBy=multi-user.target