v0.7.38 - Fixed error upon startup with existing db
This commit is contained in:
@@ -121,8 +121,8 @@ fuser -k 8888/tcp
|
|||||||
- Event filtering done at C level, not SQL level for NIP-40 expiration
|
- Event filtering done at C level, not SQL level for NIP-40 expiration
|
||||||
|
|
||||||
### Configuration Override Behavior
|
### Configuration Override Behavior
|
||||||
- CLI port override only affects first-time startup
|
- CLI port override applies during first-time startup and existing relay restarts
|
||||||
- After database creation, all config comes from events
|
- After database creation, all config comes from events (but CLI overrides can still be applied)
|
||||||
- Database path cannot be changed after initialization
|
- Database path cannot be changed after initialization
|
||||||
|
|
||||||
## Non-Obvious Pitfalls
|
## Non-Obvious Pitfalls
|
||||||
|
|||||||
@@ -3971,9 +3971,9 @@ function updateStatsFromTimeMonitoringEvent(monitoringData) {
|
|||||||
|
|
||||||
// Extract values from periods array
|
// Extract values from periods array
|
||||||
monitoringData.periods.forEach(period => {
|
monitoringData.periods.forEach(period => {
|
||||||
if (period.period === '24h') timeStats.last_24h = period.event_count;
|
if (period.period === '24h') timeStats.last_24h = period.count;
|
||||||
else if (period.period === '7d') timeStats.last_7d = period.event_count;
|
else if (period.period === '7d') timeStats.last_7d = period.count;
|
||||||
else if (period.period === '30d') timeStats.last_30d = period.event_count;
|
else if (period.period === '30d') timeStats.last_30d = period.count;
|
||||||
});
|
});
|
||||||
|
|
||||||
populateStatsTime({ time_stats: timeStats });
|
populateStatsTime({ time_stats: timeStats });
|
||||||
|
|||||||
@@ -1,3 +1,19 @@
|
|||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
|
|
||||||
|
# Copy the binary to the deployment location
|
||||||
cp build/c_relay_x86 ~/Storage/c_relay/crelay
|
cp build/c_relay_x86 ~/Storage/c_relay/crelay
|
||||||
|
|
||||||
|
# Copy the local service file to systemd
|
||||||
|
sudo cp systemd/c-relay-local.service /etc/systemd/system/
|
||||||
|
|
||||||
|
# Reload systemd daemon to pick up the new service
|
||||||
|
sudo systemctl daemon-reload
|
||||||
|
|
||||||
|
# Enable the service (if not already enabled)
|
||||||
|
sudo systemctl enable c-relay-local.service
|
||||||
|
|
||||||
|
# Restart the service
|
||||||
|
sudo systemctl restart c-relay-local.service
|
||||||
|
|
||||||
|
# Show service status
|
||||||
|
sudo systemctl status c-relay-local.service --no-pager -l
|
||||||
|
|||||||
@@ -133,6 +133,11 @@ if [ -n "$PORT_OVERRIDE" ]; then
|
|||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
# Validate strict port flag (only makes sense with port override)
|
||||||
|
if [ "$USE_TEST_KEYS" = true ] && [ -z "$PORT_OVERRIDE" ]; then
|
||||||
|
echo "WARNING: --strict-port is always used with test keys. Consider specifying a custom port with -p."
|
||||||
|
fi
|
||||||
|
|
||||||
# Validate debug level if provided
|
# Validate debug level if provided
|
||||||
if [ -n "$DEBUG_LEVEL" ]; then
|
if [ -n "$DEBUG_LEVEL" ]; then
|
||||||
if ! [[ "$DEBUG_LEVEL" =~ ^[0-5]$ ]]; then
|
if ! [[ "$DEBUG_LEVEL" =~ ^[0-5]$ ]]; then
|
||||||
@@ -163,6 +168,8 @@ if [ "$HELP" = true ]; then
|
|||||||
echo " $0 # Fresh start with random keys"
|
echo " $0 # Fresh start with random keys"
|
||||||
echo " $0 -a <admin-hex> -r <relay-hex> # Use custom keys"
|
echo " $0 -a <admin-hex> -r <relay-hex> # Use custom keys"
|
||||||
echo " $0 -a <admin-hex> -p 9000 # Custom admin key on port 9000"
|
echo " $0 -a <admin-hex> -p 9000 # Custom admin key on port 9000"
|
||||||
|
echo " $0 -p 7777 --strict-port # Fail if port 7777 unavailable (no fallback)"
|
||||||
|
echo " $0 -p 8080 --strict-port -d=3 # Custom port with strict binding and debug"
|
||||||
echo " $0 --debug-level=3 # Start with debug level 3 (info)"
|
echo " $0 --debug-level=3 # Start with debug level 3 (info)"
|
||||||
echo " $0 -d=5 # Start with debug level 5 (trace)"
|
echo " $0 -d=5 # Start with debug level 5 (trace)"
|
||||||
echo " $0 --preserve-database # Preserve existing database and keys"
|
echo " $0 --preserve-database # Preserve existing database and keys"
|
||||||
|
|||||||
@@ -85,3 +85,7 @@ sudo -u c-relay ./c_relay --debug-level=5 -r 85d0b37e2ae822966dcadd06b2dc9368cde
|
|||||||
|
|
||||||
sudo ufw allow 8888/tcp
|
sudo ufw allow 8888/tcp
|
||||||
sudo ufw delete allow 8888/tcp
|
sudo ufw delete allow 8888/tcp
|
||||||
|
|
||||||
|
lsof -i :7777
|
||||||
|
kill $(lsof -t -i :7777)
|
||||||
|
kill -9 $(lsof -t -i :7777)
|
||||||
21
src/config.c
21
src/config.c
@@ -837,26 +837,7 @@ int startup_existing_relay(const char* relay_pubkey, const cli_options_t* cli_op
|
|||||||
|
|
||||||
// NOTE: Database is already initialized in main.c before calling this function
|
// NOTE: Database is already initialized in main.c before calling this function
|
||||||
// Config table should already exist with complete configuration
|
// Config table should already exist with complete configuration
|
||||||
|
// CLI overrides will be applied after this function returns in main.c
|
||||||
// Check if CLI overrides need to be applied
|
|
||||||
int has_overrides = 0;
|
|
||||||
if (cli_options) {
|
|
||||||
if (cli_options->port_override > 0) has_overrides = 1;
|
|
||||||
if (cli_options->admin_pubkey_override[0] != '\0') has_overrides = 1;
|
|
||||||
if (cli_options->relay_privkey_override[0] != '\0') has_overrides = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (has_overrides) {
|
|
||||||
// Apply CLI overrides to existing database
|
|
||||||
DEBUG_INFO("Applying CLI overrides to existing database");
|
|
||||||
if (apply_cli_overrides_atomic(cli_options) != 0) {
|
|
||||||
DEBUG_ERROR("Failed to apply CLI overrides to existing database");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// No CLI overrides - config table is already available
|
|
||||||
DEBUG_INFO("No CLI overrides - config table is already available");
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|||||||
File diff suppressed because one or more lines are too long
66
src/main.c
66
src/main.c
@@ -315,15 +315,36 @@ int init_database(const char* database_path_override) {
|
|||||||
if (g_debug_level >= DEBUG_LEVEL_DEBUG) {
|
if (g_debug_level >= DEBUG_LEVEL_DEBUG) {
|
||||||
// Check config table row count immediately after database open
|
// Check config table row count immediately after database open
|
||||||
sqlite3_stmt* stmt;
|
sqlite3_stmt* stmt;
|
||||||
if (sqlite3_prepare_v2(g_db, "SELECT COUNT(*) FROM config", -1, &stmt, NULL) == SQLITE_OK) {
|
int rc = sqlite3_prepare_v2(g_db, "SELECT COUNT(*) FROM config", -1, &stmt, NULL);
|
||||||
|
if (rc == SQLITE_OK) {
|
||||||
if (sqlite3_step(stmt) == SQLITE_ROW) {
|
if (sqlite3_step(stmt) == SQLITE_ROW) {
|
||||||
int row_count = sqlite3_column_int(stmt, 0);
|
int row_count = sqlite3_column_int(stmt, 0);
|
||||||
DEBUG_LOG("Config table row count immediately after sqlite3_open(): %d", row_count);
|
DEBUG_LOG("Config table row count immediately after sqlite3_open(): %d", row_count);
|
||||||
}
|
}
|
||||||
sqlite3_finalize(stmt);
|
sqlite3_finalize(stmt);
|
||||||
|
} else {
|
||||||
|
// Capture and log the actual SQLite error instead of assuming table doesn't exist
|
||||||
|
const char* err_msg = sqlite3_errmsg(g_db);
|
||||||
|
DEBUG_LOG("Failed to prepare config table query: %s (error code: %d)", err_msg, rc);
|
||||||
|
|
||||||
|
// Check if it's actually a missing table vs other error
|
||||||
|
if (rc == SQLITE_ERROR) {
|
||||||
|
// Try to check if config table exists
|
||||||
|
sqlite3_stmt* check_stmt;
|
||||||
|
int check_rc = sqlite3_prepare_v2(g_db, "SELECT name FROM sqlite_master WHERE type='table' AND name='config'", -1, &check_stmt, NULL);
|
||||||
|
if (check_rc == SQLITE_OK) {
|
||||||
|
int has_table = (sqlite3_step(check_stmt) == SQLITE_ROW);
|
||||||
|
sqlite3_finalize(check_stmt);
|
||||||
|
if (has_table) {
|
||||||
|
DEBUG_LOG("Config table EXISTS but query failed - possible database corruption or locking issue");
|
||||||
} else {
|
} else {
|
||||||
DEBUG_LOG("Config table does not exist yet (first-time startup)");
|
DEBUG_LOG("Config table does not exist yet (first-time startup)");
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
DEBUG_LOG("Failed to check table existence: %s (error code: %d)", sqlite3_errmsg(g_db), check_rc);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
// DEBUG_GUARD_END
|
// DEBUG_GUARD_END
|
||||||
|
|
||||||
@@ -1435,7 +1456,7 @@ void print_usage(const char* program_name) {
|
|||||||
printf("Options:\n");
|
printf("Options:\n");
|
||||||
printf(" -h, --help Show this help message\n");
|
printf(" -h, --help Show this help message\n");
|
||||||
printf(" -v, --version Show version information\n");
|
printf(" -v, --version Show version information\n");
|
||||||
printf(" -p, --port PORT Override relay port (first-time startup only)\n");
|
printf(" -p, --port PORT Override relay port (first-time startup and existing relay restarts)\n");
|
||||||
printf(" --strict-port Fail if exact port is unavailable (no port increment)\n");
|
printf(" --strict-port Fail if exact port is unavailable (no port increment)\n");
|
||||||
printf(" -a, --admin-pubkey KEY Override admin public key (64-char hex or npub)\n");
|
printf(" -a, --admin-pubkey KEY Override admin public key (64-char hex or npub)\n");
|
||||||
printf(" -r, --relay-privkey KEY Override relay private key (64-char hex or nsec)\n");
|
printf(" -r, --relay-privkey KEY Override relay private key (64-char hex or nsec)\n");
|
||||||
@@ -1445,13 +1466,14 @@ void print_usage(const char* program_name) {
|
|||||||
printf("Configuration:\n");
|
printf("Configuration:\n");
|
||||||
printf(" This relay uses event-based configuration stored in the database.\n");
|
printf(" This relay uses event-based configuration stored in the database.\n");
|
||||||
printf(" On first startup, keys are automatically generated and printed once.\n");
|
printf(" On first startup, keys are automatically generated and printed once.\n");
|
||||||
printf(" Command line options like --port only apply during first-time setup.\n");
|
printf(" Command line options like --port apply during first-time setup and existing relay restarts.\n");
|
||||||
printf(" After initial setup, all configuration is managed via database events.\n");
|
printf(" After initial setup, all configuration is managed via database events.\n");
|
||||||
printf(" Database file: <relay_pubkey>.db (created automatically)\n");
|
printf(" Database file: <relay_pubkey>.db (created automatically)\n");
|
||||||
printf("\n");
|
printf("\n");
|
||||||
printf("Port Binding:\n");
|
printf("Port Binding:\n");
|
||||||
printf(" Default: Try up to 10 consecutive ports if requested port is busy\n");
|
printf(" Default: Try up to 10 consecutive ports if requested port is busy\n");
|
||||||
printf(" --strict-port: Fail immediately if exact requested port is unavailable\n");
|
printf(" --strict-port: Fail immediately if exact requested port is unavailable\n");
|
||||||
|
printf(" --strict-port works with any custom port specified via -p or --port\n");
|
||||||
printf("\n");
|
printf("\n");
|
||||||
printf("Examples:\n");
|
printf("Examples:\n");
|
||||||
printf(" %s # Start relay (auto-configure on first run)\n", program_name);
|
printf(" %s # Start relay (auto-configure on first run)\n", program_name);
|
||||||
@@ -1798,7 +1820,7 @@ int main(int argc, char* argv[]) {
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Setup existing relay (sets database path and loads config)
|
// Setup existing relay FIRST (sets database path)
|
||||||
if (startup_existing_relay(relay_pubkey, &cli_options) != 0) {
|
if (startup_existing_relay(relay_pubkey, &cli_options) != 0) {
|
||||||
DEBUG_ERROR("Failed to setup existing relay");
|
DEBUG_ERROR("Failed to setup existing relay");
|
||||||
cleanup_configuration_system();
|
cleanup_configuration_system();
|
||||||
@@ -1811,23 +1833,7 @@ int main(int argc, char* argv[]) {
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check config table row count before database initialization
|
// Initialize database with the database path set by startup_existing_relay()
|
||||||
{
|
|
||||||
sqlite3* temp_db = NULL;
|
|
||||||
if (sqlite3_open(g_database_path, &temp_db) == SQLITE_OK) {
|
|
||||||
sqlite3_stmt* stmt;
|
|
||||||
if (sqlite3_prepare_v2(temp_db, "SELECT COUNT(*) FROM config", -1, &stmt, NULL) == SQLITE_OK) {
|
|
||||||
if (sqlite3_step(stmt) == SQLITE_ROW) {
|
|
||||||
int row_count = sqlite3_column_int(stmt, 0);
|
|
||||||
printf(" Config table row count before database initialization: %d\n", row_count);
|
|
||||||
}
|
|
||||||
sqlite3_finalize(stmt);
|
|
||||||
}
|
|
||||||
sqlite3_close(temp_db);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Initialize database with existing database path
|
|
||||||
DEBUG_TRACE("Initializing existing database");
|
DEBUG_TRACE("Initializing existing database");
|
||||||
if (init_database(g_database_path) != 0) {
|
if (init_database(g_database_path) != 0) {
|
||||||
DEBUG_ERROR("Failed to initialize existing database");
|
DEBUG_ERROR("Failed to initialize existing database");
|
||||||
@@ -1842,6 +1848,20 @@ int main(int argc, char* argv[]) {
|
|||||||
}
|
}
|
||||||
DEBUG_LOG("Existing database initialized");
|
DEBUG_LOG("Existing database initialized");
|
||||||
|
|
||||||
|
// Apply CLI overrides atomically (now that database is initialized)
|
||||||
|
if (apply_cli_overrides_atomic(&cli_options) != 0) {
|
||||||
|
DEBUG_ERROR("Failed to apply CLI overrides for existing relay");
|
||||||
|
cleanup_configuration_system();
|
||||||
|
free(relay_pubkey);
|
||||||
|
for (int i = 0; existing_files[i]; i++) {
|
||||||
|
free(existing_files[i]);
|
||||||
|
}
|
||||||
|
free(existing_files);
|
||||||
|
nostr_cleanup();
|
||||||
|
close_database();
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
// DEBUG_GUARD_START
|
// DEBUG_GUARD_START
|
||||||
if (g_debug_level >= DEBUG_LEVEL_DEBUG) {
|
if (g_debug_level >= DEBUG_LEVEL_DEBUG) {
|
||||||
sqlite3_stmt* stmt;
|
sqlite3_stmt* stmt;
|
||||||
@@ -2010,8 +2030,8 @@ int main(int argc, char* argv[]) {
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
// Start WebSocket Nostr relay server (port from configuration)
|
// Start WebSocket Nostr relay server (port from CLI override or configuration)
|
||||||
int result = start_websocket_relay(-1, cli_options.strict_port); // Let config system determine port, pass strict_port flag
|
int result = start_websocket_relay(cli_options.port_override, cli_options.strict_port); // Use CLI port override if specified, otherwise config
|
||||||
|
|
||||||
// Cleanup
|
// Cleanup
|
||||||
cleanup_relay_info();
|
cleanup_relay_info();
|
||||||
|
|||||||
@@ -10,10 +10,10 @@
|
|||||||
#define MAIN_H
|
#define MAIN_H
|
||||||
|
|
||||||
// Version information (auto-updated by build system)
|
// Version information (auto-updated by build system)
|
||||||
#define VERSION "v0.7.37"
|
#define VERSION "v0.7.38"
|
||||||
#define VERSION_MAJOR 0
|
#define VERSION_MAJOR 0
|
||||||
#define VERSION_MINOR 7
|
#define VERSION_MINOR 7
|
||||||
#define VERSION_PATCH 37
|
#define VERSION_PATCH 38
|
||||||
|
|
||||||
// Relay metadata (authoritative source for NIP-11 information)
|
// Relay metadata (authoritative source for NIP-11 information)
|
||||||
#define RELAY_NAME "C-Relay"
|
#define RELAY_NAME "C-Relay"
|
||||||
|
|||||||
40
systemd/c-relay-local.service
Normal file
40
systemd/c-relay-local.service
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
[Unit]
|
||||||
|
Description=C Nostr Relay Server (Local Development)
|
||||||
|
Documentation=https://github.com/your-repo/c-relay
|
||||||
|
After=network.target
|
||||||
|
Wants=network-online.target
|
||||||
|
|
||||||
|
[Service]
|
||||||
|
Type=simple
|
||||||
|
User=teknari
|
||||||
|
WorkingDirectory=/home/teknari/Storage/c_relay
|
||||||
|
Environment=DEBUG_LEVEL=0
|
||||||
|
ExecStart=/home/teknari/Storage/c_relay/crelay --port 7777 --debug-level=$DEBUG_LEVEL
|
||||||
|
Restart=always
|
||||||
|
RestartSec=5
|
||||||
|
StandardOutput=journal
|
||||||
|
StandardError=journal
|
||||||
|
SyslogIdentifier=c-relay-local
|
||||||
|
|
||||||
|
# Security settings (relaxed for local development)
|
||||||
|
NoNewPrivileges=true
|
||||||
|
ProtectSystem=strict
|
||||||
|
ProtectHome=true
|
||||||
|
ReadWritePaths=/home/teknari/Storage/c_relay
|
||||||
|
PrivateTmp=true
|
||||||
|
|
||||||
|
# Network security
|
||||||
|
PrivateNetwork=false
|
||||||
|
RestrictAddressFamilies=AF_INET AF_INET6
|
||||||
|
|
||||||
|
# Resource limits
|
||||||
|
LimitNOFILE=65536
|
||||||
|
LimitNPROC=4096
|
||||||
|
|
||||||
|
# Event-based configuration system
|
||||||
|
# No environment variables needed - all configuration is stored as Nostr events
|
||||||
|
# Database files (<relay_pubkey>.db) are created automatically in WorkingDirectory
|
||||||
|
# Admin keys are generated and displayed only during first startup
|
||||||
|
|
||||||
|
[Install]
|
||||||
|
WantedBy=multi-user.target
|
||||||
Reference in New Issue
Block a user