Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
aa07fe0edd | ||
|
|
67874636d2 | ||
|
|
c316c39860 | ||
|
|
a4197dab4b | ||
|
|
8453d82ee4 | ||
|
|
8c6770c7e2 | ||
|
|
7cd33aa6ea | ||
|
|
81c5339063 | ||
|
|
5ec5ed9bd4 | ||
|
|
bd5150cd09 |
@@ -2,6 +2,59 @@
|
||||
|
||||
**Project-Specific Information for AI Agents Working with C-Relay-PG**
|
||||
|
||||
## ⚠️ CRITICAL: Never Run `make` Directly
|
||||
|
||||
**NEVER run `make` to build the relay binary.** The Makefile will refuse and
|
||||
print an error. Running `make` directly produces a dynamically-linked binary
|
||||
that will silently fall back to SQLite storage while the admin UI connects to
|
||||
PostgreSQL — causing the admin page to show stale data.
|
||||
|
||||
Always use one of these instead:
|
||||
|
||||
- **`./build_static.sh`** — Build the static MUSL binary with PostgreSQL backend
|
||||
- **`./make_and_restart_relay.sh`** — Build, kill old relay, and start new one
|
||||
|
||||
The Makefile exists only for submodule compilation (nostr_core_lib, c_utils_lib)
|
||||
and utility targets (clean, install-deps). It will refuse to build the relay
|
||||
binary directly.
|
||||
|
||||
## Critical Build Commands
|
||||
|
||||
### Primary Build Command
|
||||
```bash
|
||||
./make_and_restart_relay.sh
|
||||
```
|
||||
**Never use `make` directly.** The project requires the custom restart script which:
|
||||
- Handles database preservation/cleanup based on flags
|
||||
- Manages architecture-specific binary detection (x86/ARM64)
|
||||
- Performs automatic process cleanup and port management
|
||||
- Starts relay in background with proper logging
|
||||
|
||||
**Note:** `--test-keys` / `-t` is now the **default**. Use `--no-test-keys` or `--production` for random key generation.
|
||||
|
||||
### Architecture-Specific Binary Outputs
|
||||
- **x86_64**: `./build/c_relay_pg_x86`
|
||||
- **ARM64**: `./build/c_relay_pg_arm64`
|
||||
- **Other**: `./build/c_relay_pg_$(ARCH)`
|
||||
|
||||
**Project-Specific Information for AI Agents Working with C-Relay-PG**
|
||||
|
||||
## ⚠️ CRITICAL: Never Run `make` Directly
|
||||
|
||||
**NEVER run `make` to build the relay binary.** The Makefile will refuse and
|
||||
print an error. Running `make` directly produces a dynamically-linked binary
|
||||
that will silently fall back to SQLite storage while the admin UI connects to
|
||||
PostgreSQL — causing the admin page to show stale data.
|
||||
|
||||
Always use one of these instead:
|
||||
|
||||
- **`./build_static.sh`** — Build the static MUSL binary with PostgreSQL backend
|
||||
- **`./make_and_restart_relay.sh`** — Build, kill old relay, and start new one
|
||||
|
||||
The Makefile exists only for submodule compilation (nostr_core_lib, c_utils_lib)
|
||||
and utility targets (clean, install-deps). It will refuse to build the relay
|
||||
binary directly.
|
||||
|
||||
## Critical Build Commands
|
||||
|
||||
### Primary Build Command
|
||||
|
||||
+9
-15
@@ -1,14 +1,13 @@
|
||||
# Alpine-based MUSL static binary builder for C-Relay-PG
|
||||
# Produces truly portable binaries with zero runtime dependencies
|
||||
# PostgreSQL backend only.
|
||||
|
||||
ARG DEBUG_BUILD=false
|
||||
ARG DB_BACKEND=sqlite
|
||||
|
||||
FROM alpine:3.19 AS builder
|
||||
|
||||
# Re-declare build arguments in this stage
|
||||
ARG DEBUG_BUILD=false
|
||||
ARG DB_BACKEND=sqlite
|
||||
|
||||
# Install build dependencies
|
||||
RUN apk add --no-cache \
|
||||
@@ -105,7 +104,8 @@ COPY Makefile /build/Makefile
|
||||
|
||||
# Build c-relay-pg with full static linking (only rebuilds when src/ changes)
|
||||
# Disable fortification to avoid __*_chk symbols that don't exist in MUSL
|
||||
# Use conditional compilation flags based on DEBUG_BUILD and DB_BACKEND build args
|
||||
# Use conditional compilation flags based on DEBUG_BUILD build arg.
|
||||
# PostgreSQL backend is always used.
|
||||
RUN if [ "$DEBUG_BUILD" = "true" ]; then \
|
||||
CFLAGS="-g -O2 -DDEBUG"; \
|
||||
STRIP_CMD="echo 'Keeping debug symbols'"; \
|
||||
@@ -115,15 +115,9 @@ RUN if [ "$DEBUG_BUILD" = "true" ]; then \
|
||||
STRIP_CMD="strip /build/c_relay_pg_static"; \
|
||||
echo "Building optimized production binary (symbols stripped)"; \
|
||||
fi && \
|
||||
if [ "$DB_BACKEND" = "postgres" ]; then \
|
||||
DB_FLAGS="-DDB_BACKEND_POSTGRES -DHAVE_LIBPQ"; \
|
||||
DB_LIBS="-lpq -lpgcommon -lpgport"; \
|
||||
echo "Compiling with PostgreSQL backend"; \
|
||||
else \
|
||||
DB_FLAGS=""; \
|
||||
DB_LIBS=""; \
|
||||
echo "Compiling with SQLite backend"; \
|
||||
fi && \
|
||||
DB_FLAGS="-DDB_BACKEND_POSTGRES -DHAVE_LIBPQ" && \
|
||||
DB_LIBS="-lpq -lpgcommon -lpgport" && \
|
||||
echo "Compiling with PostgreSQL backend" && \
|
||||
gcc -static $CFLAGS $DB_FLAGS -Wall -Wextra -std=c99 \
|
||||
-U_FORTIFY_SOURCE -D_FORTIFY_SOURCE=0 \
|
||||
-I. -Ic_utils_lib/src -Inostr_core_lib -Inostr_core_lib/nostr_core \
|
||||
@@ -132,11 +126,11 @@ RUN if [ "$DEBUG_BUILD" = "true" ]; then \
|
||||
src/nip009.c src/nip011.c src/nip013.c src/nip040.c src/nip042.c \
|
||||
src/websockets.c src/subscriptions.c src/api.c src/embedded_web_content.c src/ip_ban.c \
|
||||
src/caching_inbox_poller.c src/caching_service_launcher.c \
|
||||
src/db_ops.c src/db_ops_sqlite.c src/db_ops_postgres.c src/thread_pool.c \
|
||||
src/db_ops.c src/db_ops_postgres.c src/thread_pool.c \
|
||||
-o /build/c_relay_pg_static \
|
||||
c_utils_lib/libc_utils.a \
|
||||
nostr_core_lib/libnostr_core_x64.a \
|
||||
-lwebsockets -lssl -lcrypto -lsqlite3 -lsecp256k1 \
|
||||
-lwebsockets -lssl -lcrypto -lsecp256k1 \
|
||||
-lcurl -lz -lpthread -lm -ldl $DB_LIBS && \
|
||||
eval "$STRIP_CMD"
|
||||
|
||||
@@ -150,4 +144,4 @@ RUN echo "=== Binary Information ===" && \
|
||||
|
||||
# Output stage - just the binary
|
||||
FROM scratch AS output
|
||||
COPY --from=builder /build/c_relay_pg_static /c_relay_pg_static
|
||||
COPY --from=builder /build/c_relay_pg_static /c_relay_pg_static
|
||||
|
||||
@@ -1,26 +1,16 @@
|
||||
# C-Relay-PG Makefile
|
||||
|
||||
CC = gcc
|
||||
CFLAGS = -Wall -Wextra -std=c99 -g -O2
|
||||
CFLAGS = -Wall -Wextra -std=c99 -g -O2 -DDB_BACKEND_POSTGRES -DHAVE_LIBPQ
|
||||
INCLUDES = -I. -Ic_utils_lib/src -Inostr_core_lib -Inostr_core_lib/nostr_core -Inostr_core_lib/cjson -Inostr_core_lib/nostr_websocket -I/usr/include/postgresql
|
||||
LIBS = -lsqlite3 -lwebsockets -lz -ldl -lpthread -lm -L/usr/local/lib -lsecp256k1 -lssl -lcrypto -L/usr/local/lib -lcurl -Lc_utils_lib -lc_utils
|
||||
|
||||
DB_BACKEND ?= sqlite
|
||||
LIBS = -lwebsockets -lz -ldl -lpthread -lm -L/usr/local/lib -lsecp256k1 -lssl -lcrypto -L/usr/local/lib -lcurl -Lc_utils_lib -lc_utils -lpq
|
||||
|
||||
# Build directory
|
||||
BUILD_DIR = build
|
||||
|
||||
# Source files
|
||||
MAIN_SRC = src/main.c src/config.c src/dm_admin.c src/request_validator.c src/nip009.c src/nip011.c src/nip013.c src/nip040.c src/nip042.c src/websockets.c src/subscriptions.c src/api.c src/embedded_web_content.c src/ip_ban.c src/thread_pool.c src/caching_inbox_poller.c src/caching_service_launcher.c
|
||||
DB_OPS_SRC = src/db_ops.c
|
||||
|
||||
ifeq ($(DB_BACKEND),postgres)
|
||||
CFLAGS += -DDB_BACKEND_POSTGRES -DHAVE_LIBPQ
|
||||
DB_OPS_SRC += src/db_ops_postgres.c
|
||||
LIBS += -lpq
|
||||
else
|
||||
DB_OPS_SRC += src/db_ops_sqlite.c
|
||||
endif
|
||||
DB_OPS_SRC = src/db_ops.c src/db_ops_postgres.c
|
||||
|
||||
NOSTR_CORE_LIB = nostr_core_lib/libnostr_core_x64.a
|
||||
C_UTILS_LIB = c_utils_lib/libc_utils.a
|
||||
@@ -37,8 +27,30 @@ else
|
||||
TARGET = $(BUILD_DIR)/c_relay_pg_$(ARCH)
|
||||
endif
|
||||
|
||||
# Default target
|
||||
all: $(TARGET)
|
||||
# Default target — refuse direct build, instruct to use build_static.sh
|
||||
# The Makefile is only for submodule builds (nostr_core_lib, c_utils_lib)
|
||||
# and utility targets (clean, install-deps, etc.).
|
||||
# Running 'make' directly produces a dynamically-linked binary that will
|
||||
# silently fall back to SQLite storage while the admin UI connects to
|
||||
# PostgreSQL — causing the admin page to show stale data.
|
||||
all:
|
||||
@echo "============================================"
|
||||
@echo " ERROR: Do not run 'make' directly!"
|
||||
@echo ""
|
||||
@echo " This project requires a static MUSL build"
|
||||
@echo " with PostgreSQL backend. Run:"
|
||||
@echo ""
|
||||
@echo " ./build_static.sh"
|
||||
@echo ""
|
||||
@echo " Or use the full build+restart script:"
|
||||
@echo ""
|
||||
@echo " ./make_and_restart_relay.sh"
|
||||
@echo ""
|
||||
@echo " The Makefile is only for submodule builds"
|
||||
@echo " (nostr_core_lib, c_utils_lib) and utility"
|
||||
@echo " targets (clean, install-deps, etc.)."
|
||||
@echo "============================================"
|
||||
@exit 1
|
||||
|
||||
# Create build directory
|
||||
$(BUILD_DIR):
|
||||
@@ -92,147 +104,75 @@ force-version:
|
||||
@echo "Force updating main.h version information..."
|
||||
@$(MAKE) src/main.h
|
||||
|
||||
# Build the relay
|
||||
$(TARGET): $(BUILD_DIR) src/main.h src/sql_schema.h $(MAIN_SRC) $(DB_OPS_SRC) $(NOSTR_CORE_LIB) $(C_UTILS_LIB)
|
||||
@echo "Compiling C-Relay-PG for architecture: $(ARCH) (backend: $(DB_BACKEND))"
|
||||
$(CC) $(CFLAGS) $(INCLUDES) $(MAIN_SRC) $(DB_OPS_SRC) -o $(TARGET) $(NOSTR_CORE_LIB) $(C_UTILS_LIB) $(LIBS)
|
||||
@echo "Build complete: $(TARGET)"
|
||||
# Build the relay — guarded to prevent accidental use.
|
||||
# Use ./build_static.sh instead.
|
||||
$(TARGET):
|
||||
@echo "ERROR: Do not run 'make $(TARGET)' directly."
|
||||
@echo "Use ./build_static.sh to build the static MUSL binary."
|
||||
@exit 1
|
||||
|
||||
# Build for specific architectures
|
||||
x86: $(BUILD_DIR) src/main.h src/sql_schema.h $(MAIN_SRC) $(DB_OPS_SRC) $(NOSTR_CORE_LIB) $(C_UTILS_LIB)
|
||||
@echo "Building C-Relay-PG for x86_64 (backend: $(DB_BACKEND))..."
|
||||
$(CC) $(CFLAGS) $(INCLUDES) $(MAIN_SRC) $(DB_OPS_SRC) -o $(BUILD_DIR)/c_relay_pg_x86 $(NOSTR_CORE_LIB) $(C_UTILS_LIB) $(LIBS)
|
||||
@echo "Build complete: $(BUILD_DIR)/c_relay_pg_x86"
|
||||
x86:
|
||||
@echo "ERROR: Do not run 'make x86' directly."
|
||||
@echo "Use ./build_static.sh to build the static MUSL binary."
|
||||
@exit 1
|
||||
|
||||
arm64: $(BUILD_DIR) src/main.h src/sql_schema.h $(MAIN_SRC) $(DB_OPS_SRC) $(NOSTR_CORE_LIB) $(C_UTILS_LIB)
|
||||
@echo "Cross-compiling C-Relay-PG for ARM64 (backend: $(DB_BACKEND))..."
|
||||
arm64:
|
||||
@echo "ERROR: Do not run 'make arm64' directly."
|
||||
@echo "Use ./build_static.sh to build the static MUSL binary."
|
||||
@exit 1
|
||||
@if ! command -v aarch64-linux-gnu-gcc >/dev/null 2>&1; then \
|
||||
echo "ERROR: ARM64 cross-compiler not found."; \
|
||||
echo "Install with: make install-cross-tools"; \
|
||||
echo "Or install manually: sudo apt install gcc-aarch64-linux-gnu"; \
|
||||
echo "ERROR: aarch64-linux-gnu-gcc not found."; \
|
||||
echo "Install the ARM64 cross-compiler:"; \
|
||||
echo " sudo apt install gcc-aarch64-linux-gnu"; \
|
||||
exit 1; \
|
||||
fi
|
||||
@echo "Checking for ARM64 development libraries..."
|
||||
@if ! dpkg -l | grep -q "libssl-dev:arm64\|libsqlite3-dev:arm64"; then \
|
||||
@if ! dpkg -l | grep -q "libssl-dev:arm64\|libpq-dev:arm64"; then \
|
||||
echo "ERROR: ARM64 libraries not found. Cross-compilation requires ARM64 versions of:"; \
|
||||
echo " - libssl-dev:arm64"; \
|
||||
echo " - libsqlite3-dev:arm64"; \
|
||||
echo " - libpq-dev:arm64"; \
|
||||
echo " - libwebsockets-dev:arm64"; \
|
||||
echo " - libsecp256k1-dev:arm64"; \
|
||||
echo " - zlib1g-dev:arm64"; \
|
||||
echo " - libcurl4-openssl-dev:arm64"; \
|
||||
echo " - libcurl-dev:arm64"; \
|
||||
echo ""; \
|
||||
echo "Install ARM64 libraries with: make install-arm64-deps"; \
|
||||
echo "Or use Docker for cross-platform builds."; \
|
||||
echo "Install them with:"; \
|
||||
echo " sudo dpkg --add-architecture arm64"; \
|
||||
echo " sudo apt update"; \
|
||||
echo " sudo apt install gcc-aarch64-linux-gnu \\"; \
|
||||
echo " libssl-dev:arm64 libpq-dev:arm64 \\"; \
|
||||
echo " libwebsockets-dev:arm64 zlib1g-dev:arm64 \\"; \
|
||||
echo " libcurl4-openssl-dev:arm64"; \
|
||||
exit 1; \
|
||||
fi
|
||||
@echo "Using aarch64-linux-gnu-gcc with ARM64 libraries..."
|
||||
PKG_CONFIG_PATH=/usr/lib/aarch64-linux-gnu/pkgconfig:/usr/share/pkgconfig \
|
||||
aarch64-linux-gnu-gcc $(CFLAGS) $(INCLUDES) $(MAIN_SRC) $(DB_OPS_SRC) -o $(BUILD_DIR)/c_relay_pg_arm64 $(NOSTR_CORE_LIB) $(C_UTILS_LIB) \
|
||||
-L/usr/lib/aarch64-linux-gnu $(LIBS)
|
||||
@echo "Build complete: $(BUILD_DIR)/c_relay_pg_arm64"
|
||||
fi; \
|
||||
PKG_CONFIG_PATH=/usr/lib/aarch64-linux-gnu/pkgconfig \
|
||||
PKG_CONFIG_SYSROOT_DIR=/ \
|
||||
aarch64-linux-gnu-gcc -Wall -Wextra -std=c99 -g -O2 \
|
||||
-DDB_BACKEND_POSTGRES -DHAVE_LIBPQ \
|
||||
-I. -Ic_utils_lib/src -Inostr_core_lib -Inostr_core_lib/nostr_core \
|
||||
-Inostr_core_lib/cjson -Inostr_core_lib/nostr_websocket \
|
||||
$(MAIN_SRC) $(DB_OPS_SRC) \
|
||||
-o $(BUILD_DIR)/c_relay_pg_arm64 \
|
||||
$(NOSTR_CORE_LIB) $(C_UTILS_LIB) \
|
||||
-lwebsockets -lssl -lcrypto -lz -ldl -lpthread -lm \
|
||||
-lsecp256k1 -lcurl -lpq
|
||||
@echo "Cross-compilation complete: $(BUILD_DIR)/c_relay_pg_arm64"
|
||||
|
||||
# Install ARM64 cross-compilation dependencies
|
||||
# Install dependencies for ARM64 cross-compilation
|
||||
install-arm64-deps:
|
||||
@echo "Installing ARM64 cross-compilation dependencies..."
|
||||
@echo "This requires adding ARM64 architecture and installing cross-libraries..."
|
||||
sudo dpkg --add-architecture arm64
|
||||
sudo apt update
|
||||
sudo apt install -y \
|
||||
gcc-aarch64-linux-gnu \
|
||||
libc6-dev-arm64-cross \
|
||||
libssl-dev:arm64 \
|
||||
libsqlite3-dev:arm64 \
|
||||
zlib1g-dev:arm64 \
|
||||
sudo apt install -y gcc-aarch64-linux-gnu \
|
||||
libssl-dev:arm64 libpq-dev:arm64 \
|
||||
libwebsockets-dev:arm64 zlib1g-dev:arm64 \
|
||||
libcurl4-openssl-dev:arm64
|
||||
@echo "Note: libwebsockets-dev:arm64 and libsecp256k1-dev:arm64 may need manual building"
|
||||
|
||||
# Install cross-compilation tools
|
||||
install-cross-tools:
|
||||
@echo "Installing cross-compilation tools..."
|
||||
# Install dependencies for native build
|
||||
install-deps:
|
||||
sudo apt update
|
||||
sudo apt install -y gcc-aarch64-linux-gnu libc6-dev-arm64-cross
|
||||
|
||||
# Check what architectures we can actually build
|
||||
check-toolchain:
|
||||
@echo "Checking available toolchains:"
|
||||
@echo "Native compiler: $(shell $(CC) --version | head -1)"
|
||||
@if command -v aarch64-linux-gnu-gcc >/dev/null 2>&1; then \
|
||||
echo "ARM64 cross-compiler: $(shell aarch64-linux-gnu-gcc --version | head -1)"; \
|
||||
else \
|
||||
echo "ARM64 cross-compiler: NOT INSTALLED (install with 'make install-cross-tools')"; \
|
||||
fi
|
||||
|
||||
# Run tests
|
||||
test: $(TARGET)
|
||||
@echo "Running tests..."
|
||||
./tests/1_nip_test.sh
|
||||
|
||||
# Initialize database (now handled automatically when server starts)
|
||||
init-db:
|
||||
@echo "Database initialization is now handled automatically when the server starts."
|
||||
@echo "The schema is embedded in the binary - no external files needed."
|
||||
@echo "To manually recreate database: rm -f db/c_nostr_relay.db && ./build/c_relay_pg_x86"
|
||||
sudo apt install -y build-essential libpq-dev libssl-dev libcurl4-openssl-dev libsecp256k1-dev zlib1g-dev jq curl
|
||||
|
||||
# Clean build artifacts
|
||||
clean:
|
||||
rm -rf $(BUILD_DIR)
|
||||
@echo "Clean complete"
|
||||
|
||||
# Clean everything including nostr_core_lib and c_utils_lib
|
||||
clean-all: clean
|
||||
cd nostr_core_lib && make clean 2>/dev/null || true
|
||||
cd c_utils_lib && make clean 2>/dev/null || true
|
||||
|
||||
# Install dependencies (Ubuntu/Debian)
|
||||
install-deps:
|
||||
@echo "Installing dependencies..."
|
||||
sudo apt update
|
||||
sudo apt install -y build-essential libsqlite3-dev libssl-dev libcurl4-openssl-dev libsecp256k1-dev zlib1g-dev jq curl
|
||||
|
||||
# Help
|
||||
help:
|
||||
@echo "C-Relay-PG Build System"
|
||||
@echo ""
|
||||
@echo "Targets:"
|
||||
@echo " all Build the relay for current architecture (default)"
|
||||
@echo " x86 Build specifically for x86_64"
|
||||
@echo " arm64 Build for ARM64 (requires cross-compilation setup)"
|
||||
@echo " test Build and run tests"
|
||||
@echo " init-db Initialize the database"
|
||||
@echo " clean Clean build artifacts"
|
||||
@echo " clean-all Clean everything including dependencies"
|
||||
@echo " install-deps Install system dependencies"
|
||||
@echo " install-cross-tools Install basic ARM64 cross-compiler"
|
||||
@echo " install-arm64-deps Install ARM64 cross-compilation libraries"
|
||||
@echo " check-toolchain Check available compilers"
|
||||
@echo " help Show this help"
|
||||
@echo ""
|
||||
@echo "Usage:"
|
||||
@echo " make # Build the relay for current arch"
|
||||
@echo " make x86 # Build for x86_64"
|
||||
@echo " make arm64 # Build for ARM64 (fails if cross-compilation not set up)"
|
||||
@echo " make install-arm64-deps # Install full ARM64 cross-compilation setup"
|
||||
@echo " make check-toolchain # Check what compilers are available"
|
||||
@echo " make test # Run tests"
|
||||
@echo " make init-db # Set up database"
|
||||
@echo " make force-version # Force regenerate main.h from git"
|
||||
|
||||
# Build fully static MUSL binaries using Docker
|
||||
static-musl-x86_64:
|
||||
@echo "Building fully static MUSL binary for x86_64..."
|
||||
docker buildx build --platform linux/amd64 -f examples/deployment/static-builder.Dockerfile -t c-relay-pg-static-builder-x86_64 --load .
|
||||
docker run --rm -v $(PWD)/build:/output c-relay-pg-static-builder-x86_64 sh -c "cp /c_relay_pg_static_musl_x86_64 /output/"
|
||||
@echo "Static binary created: build/c_relay_pg_static_musl_x86_64"
|
||||
|
||||
static-musl-arm64:
|
||||
@echo "Building fully static MUSL binary for ARM64..."
|
||||
docker buildx build --platform linux/arm64 -f examples/deployment/static-builder.Dockerfile -t c-relay-pg-static-builder-arm64 --load .
|
||||
docker run --rm -v $(PWD)/build:/output c-relay-pg-static-builder-arm64 sh -c "cp /c_relay_pg_static_musl_x86_64 /output/c_relay_pg_static_musl_arm64"
|
||||
@echo "Static binary created: build/c_relay_pg_static_musl_arm64"
|
||||
|
||||
static-musl: static-musl-x86_64 static-musl-arm64
|
||||
@echo "Built static MUSL binaries for both architectures"
|
||||
|
||||
.PHONY: static-musl-x86_64 static-musl-arm64 static-musl
|
||||
.PHONY: all x86 arm64 test init-db clean clean-all install-deps install-cross-tools install-arm64-deps check-toolchain help force-version
|
||||
.PHONY: all x86 arm64 install-arm64-deps install-deps clean force-version
|
||||
|
||||
+32
-2
@@ -87,8 +87,27 @@ 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) {}
|
||||
|
||||
// Upstream relay status (per-relay connection state)
|
||||
$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) {}
|
||||
|
||||
// Follows (paginated, with names from profiles cache + per-relay progress)
|
||||
$page = max(1, (int)($_GET['page'] ?? 1));
|
||||
$perPage = 50;
|
||||
$offset = ($page - 1) * $perPage;
|
||||
|
||||
$follows = [];
|
||||
$totalFollows = 0;
|
||||
try {
|
||||
$totalFollows = (int)$pdo->query("SELECT COUNT(*) FROM caching_followed_pubkeys")->fetchColumn();
|
||||
} catch (PDOException $e) {}
|
||||
|
||||
try {
|
||||
$follows = $pdo->query("
|
||||
SELECT fp.pubkey, fp.is_root, fp.backfill_complete, fp.events_fetched,
|
||||
@@ -99,7 +118,8 @@ try {
|
||||
(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 100
|
||||
ORDER BY fp.is_root DESC, fp.events_fetched DESC
|
||||
LIMIT $perPage OFFSET $offset
|
||||
")->fetchAll();
|
||||
// Fetch per-relay progress for all followed pubkeys in one query
|
||||
$relayProgress = [];
|
||||
@@ -120,4 +140,14 @@ try {
|
||||
}
|
||||
} catch (PDOException $e) {}
|
||||
|
||||
json_response(['state' => $state, 'active' => $active, 'inbox' => $inbox, 'follows' => $follows, 'config' => $config]);
|
||||
json_response([
|
||||
'state' => $state,
|
||||
'active' => $active,
|
||||
'inbox' => $inbox,
|
||||
'follows' => $follows,
|
||||
'config' => $config,
|
||||
'upstreamRelays' => $upstreamRelays,
|
||||
'totalFollows' => $totalFollows,
|
||||
'page' => $page,
|
||||
'perPage' => $perPage,
|
||||
]);
|
||||
|
||||
+20
-3
@@ -1,6 +1,6 @@
|
||||
<?php
|
||||
/**
|
||||
* admin2/api/chart.php — Standalone ASCII chart endpoint.
|
||||
* admin/api/chart.php — Standalone ASCII chart endpoint.
|
||||
*
|
||||
* Returns a plain-text ASCII X-bar chart of event counts over time.
|
||||
* Works in both the browser (injected into a <div>) and the terminal:
|
||||
@@ -10,8 +10,22 @@
|
||||
* curl http://localhost:8088/api/chart.php?range=month
|
||||
* curl http://localhost:8088/api/chart.php?range=year
|
||||
*
|
||||
* This endpoint is read-only (a fixed aggregate COUNT query with the only
|
||||
* user input being the `range` selector, which is validated against a
|
||||
* whitelist). It is safe to expose publicly and is served without auth at:
|
||||
*
|
||||
* https://<domain>/relay/api/chart.php?range=day
|
||||
*
|
||||
* It is also reachable (behind Basic Auth) from the admin UI at:
|
||||
*
|
||||
* https://<domain>/relay/admin/api/chart.php?range=day
|
||||
*
|
||||
* Caching: the hour chart is never cached (live). Day/month/year are
|
||||
* cached to file with TTLs to avoid expensive queries on every request.
|
||||
*
|
||||
* NOTE: Uses first_seen (not created_at) for binning, because some events
|
||||
* have corrupted created_at timestamps (far-future values) that would
|
||||
* place them outside the visible chart range.
|
||||
*/
|
||||
|
||||
require_once __DIR__ . '/../lib/helpers.php';
|
||||
@@ -59,9 +73,12 @@ try {
|
||||
// bin index 0 = oldest, bin index (num_bins-1) = newest
|
||||
$base_bin = (int)floor($epoch / $bin_size);
|
||||
|
||||
$sql = "SELECT FLOOR(created_at / {$bin_size})::BIGINT - {$base_bin} AS bin, COUNT(*) AS cnt
|
||||
// Use first_seen (not created_at) for binning, because some events
|
||||
// have corrupted created_at timestamps (far-future values) that
|
||||
// would place them outside the visible chart range.
|
||||
$sql = "SELECT FLOOR(first_seen / {$bin_size})::BIGINT - {$base_bin} AS bin, COUNT(*) AS cnt
|
||||
FROM events
|
||||
WHERE created_at >= {$epoch}
|
||||
WHERE first_seen >= {$epoch}
|
||||
GROUP BY bin
|
||||
ORDER BY bin";
|
||||
$rows = $pdo->query($sql)->fetchAll();
|
||||
|
||||
@@ -0,0 +1,310 @@
|
||||
<?php
|
||||
/**
|
||||
* admin2/api/cleanup.php — Event Cleanup: Preview & Execute.
|
||||
*
|
||||
* GET — Preview a cleanup query (count + size estimate, no delete).
|
||||
* POST — Execute a cleanup query (dry_run=true for preview, false for delete).
|
||||
*/
|
||||
require_once __DIR__ . '/../lib/helpers.php';
|
||||
|
||||
$pdo = db();
|
||||
$method = $_SERVER['REQUEST_METHOD'];
|
||||
|
||||
// ── Shared filter builder ──────────────────────────────────────────────
|
||||
// Returns [sql_conditions[], params[]] for the WHERE clauses.
|
||||
function build_filters(array $opts): array {
|
||||
$conds = [];
|
||||
$params = [];
|
||||
|
||||
// Kinds filter
|
||||
if (!empty($opts['kinds'])) {
|
||||
$kinds = is_array($opts['kinds']) ? $opts['kinds'] : explode(',', $opts['kinds']);
|
||||
$kinds = array_map('intval', $kinds);
|
||||
$kinds = array_filter($kinds, fn($v) => $v > 0);
|
||||
if (!empty($kinds)) {
|
||||
$placeholders = [];
|
||||
foreach ($kinds as $i => $k) {
|
||||
$key = ':kind_' . $i;
|
||||
$placeholders[] = $key;
|
||||
$params[$key] = $k;
|
||||
}
|
||||
$conds[] = 'e.kind IN (' . implode(',', $placeholders) . ')';
|
||||
}
|
||||
}
|
||||
|
||||
// Date/time range filter (supports YYYY-MM-DD or YYYY-MM-DD HH:MM)
|
||||
$from_date = $opts['from_date'] ?? '';
|
||||
$to_date = $opts['to_date'] ?? '';
|
||||
if ($from_date !== '') {
|
||||
if (preg_match('/^\d{4}-\d{2}-\d{2}$/', $from_date)) {
|
||||
$conds[] = 'e.created_at >= EXTRACT(EPOCH FROM :from_date::date)::BIGINT';
|
||||
$params[':from_date'] = $from_date;
|
||||
} elseif (preg_match('/^\d{4}-\d{2}-\d{2} \d{2}:\d{2}$/', $from_date)) {
|
||||
$conds[] = 'e.created_at >= EXTRACT(EPOCH FROM :from_date::timestamp)::BIGINT';
|
||||
$params[':from_date'] = $from_date . ':00';
|
||||
}
|
||||
}
|
||||
if ($to_date !== '') {
|
||||
if (preg_match('/^\d{4}-\d{2}-\d{2}$/', $to_date)) {
|
||||
$conds[] = 'e.created_at < (EXTRACT(EPOCH FROM :to_date::date)::BIGINT + 86400)';
|
||||
$params[':to_date'] = $to_date;
|
||||
} elseif (preg_match('/^\d{4}-\d{2}-\d{2} \d{2}:\d{2}$/', $to_date)) {
|
||||
$conds[] = 'e.created_at < EXTRACT(EPOCH FROM :to_date::timestamp)::BIGINT';
|
||||
$params[':to_date'] = $to_date . ':00';
|
||||
}
|
||||
}
|
||||
|
||||
// Follows filter
|
||||
$follows_filter = $opts['follows_filter'] ?? 'all';
|
||||
if ($follows_filter === 'follows') {
|
||||
$conds[] = 'e.pubkey IN (SELECT pubkey FROM caching_followed_pubkeys)';
|
||||
} elseif ($follows_filter === 'non_follows') {
|
||||
$conds[] = 'e.pubkey NOT IN (SELECT pubkey FROM caching_followed_pubkeys)';
|
||||
}
|
||||
|
||||
return [$conds, $params];
|
||||
}
|
||||
|
||||
// ── Build a WHERE clause string from conditions ────────────────────────
|
||||
function where_clause(array $conds): string {
|
||||
if (empty($conds)) return '';
|
||||
return 'AND ' . implode("\n AND ", $conds);
|
||||
}
|
||||
|
||||
// ── Format bytes as human-readable ─────────────────────────────────────
|
||||
function format_bytes(int $bytes): string {
|
||||
if ($bytes < 1024) return $bytes . ' B';
|
||||
if ($bytes < 1048576) return round($bytes / 1024, 1) . ' KB';
|
||||
if ($bytes < 1073741824) return round($bytes / 1048576, 1) . ' MB';
|
||||
return round($bytes / 1073741824, 2) . ' GB';
|
||||
}
|
||||
|
||||
// ── GET: Preview ───────────────────────────────────────────────────────
|
||||
if ($method === 'GET') {
|
||||
$opts = [
|
||||
'follows_filter' => $_GET['follows_filter'] ?? 'all',
|
||||
'kinds' => $_GET['kinds'] ?? '',
|
||||
'from_date' => $_GET['from_date'] ?? '',
|
||||
'to_date' => $_GET['to_date'] ?? '',
|
||||
'max_events' => intval($_GET['max_events'] ?? 0),
|
||||
];
|
||||
|
||||
list($conds, $params) = build_filters($opts);
|
||||
$where = where_clause($conds);
|
||||
|
||||
// Preview SQL (for display)
|
||||
$sql_preview = "SELECT COUNT(*) AS match_count,\n"
|
||||
. " COALESCE(SUM(pg_column_size(event_json)), 0) AS total_size_bytes\n"
|
||||
. "FROM events e\n"
|
||||
. "WHERE 1=1\n"
|
||||
. ($where ? " $where\n" : '');
|
||||
|
||||
// Count + size query
|
||||
$count_sql = "SELECT COUNT(*) AS match_count,\n"
|
||||
. " COALESCE(SUM(pg_column_size(event_json)), 0) AS total_size_bytes\n"
|
||||
. "FROM events e\n"
|
||||
. "WHERE 1=1 $where";
|
||||
|
||||
try {
|
||||
$stmt = $pdo->prepare($count_sql);
|
||||
$stmt->execute($params);
|
||||
$row = $stmt->fetch();
|
||||
$match_count = intval($row['match_count'] ?? 0);
|
||||
$total_size_bytes = intval($row['total_size_bytes'] ?? 0);
|
||||
} catch (PDOException $e) {
|
||||
json_response(['error' => 'Preview query failed: ' . $e->getMessage()]);
|
||||
exit;
|
||||
}
|
||||
|
||||
// Kind breakdown
|
||||
$breakdown = [];
|
||||
if ($match_count > 0) {
|
||||
$breakdown_sql = "SELECT e.kind,\n"
|
||||
. " COUNT(*) AS count,\n"
|
||||
. " COALESCE(SUM(pg_column_size(e.event_json)), 0) AS size_bytes\n"
|
||||
. "FROM events e\n"
|
||||
. "WHERE 1=1 $where\n"
|
||||
. "GROUP BY e.kind\n"
|
||||
. "ORDER BY count DESC\n"
|
||||
. "LIMIT 50";
|
||||
try {
|
||||
$stmt = $pdo->prepare($breakdown_sql);
|
||||
$stmt->execute($params);
|
||||
$rows = $stmt->fetchAll();
|
||||
foreach ($rows as $r) {
|
||||
$breakdown[] = [
|
||||
'kind' => intval($r['kind']),
|
||||
'count' => intval($r['count']),
|
||||
'size_bytes' => intval($r['size_bytes']),
|
||||
];
|
||||
}
|
||||
} catch (PDOException $e) {
|
||||
// Breakdown is non-critical
|
||||
}
|
||||
}
|
||||
|
||||
// If a query_id was provided, update last_preview_count and last_preview_size_bytes
|
||||
$query_id = intval($_GET['query_id'] ?? 0);
|
||||
if ($query_id > 0) {
|
||||
try {
|
||||
$pdo->prepare(
|
||||
"UPDATE cleanup_saved_queries\n"
|
||||
. " SET last_preview_count = :count,\n"
|
||||
. " last_preview_size_bytes = :size\n"
|
||||
. " WHERE id = :id"
|
||||
)->execute([
|
||||
':id' => $query_id,
|
||||
':count' => $match_count,
|
||||
':size' => $total_size_bytes,
|
||||
]);
|
||||
} catch (PDOException $e) {}
|
||||
}
|
||||
|
||||
json_response([
|
||||
'match_count' => $match_count,
|
||||
'total_size_bytes' => $total_size_bytes,
|
||||
'total_size_human' => format_bytes($total_size_bytes),
|
||||
'avg_size_per_event' => $match_count > 0 ? intval($total_size_bytes / $match_count) : 0,
|
||||
'kinds_breakdown' => $breakdown,
|
||||
'sql_preview' => $sql_preview,
|
||||
]);
|
||||
exit;
|
||||
}
|
||||
|
||||
// ── POST: Execute (or dry-run) ─────────────────────────────────────────
|
||||
if ($method === 'POST') {
|
||||
$body = json_decode(file_get_contents('php://input'), true);
|
||||
if (!$body) {
|
||||
json_response(['error' => 'Invalid JSON body']);
|
||||
exit;
|
||||
}
|
||||
|
||||
$dry_run = !empty($body['dry_run']);
|
||||
$opts = [
|
||||
'follows_filter' => $body['follows_filter'] ?? 'all',
|
||||
'kinds' => $body['kinds'] ?? [],
|
||||
'from_date' => $body['from_date'] ?? '',
|
||||
'to_date' => $body['to_date'] ?? '',
|
||||
'max_events' => intval($body['max_events'] ?? 0),
|
||||
];
|
||||
|
||||
list($conds, $params) = build_filters($opts);
|
||||
$where = where_clause($conds);
|
||||
|
||||
// If dry_run, return preview (same as GET)
|
||||
if ($dry_run) {
|
||||
$count_sql = "SELECT COUNT(*) AS match_count,\n"
|
||||
. " COALESCE(SUM(pg_column_size(event_json)), 0) AS total_size_bytes\n"
|
||||
. "FROM events e\n"
|
||||
. "WHERE 1=1 $where";
|
||||
try {
|
||||
$stmt = $pdo->prepare($count_sql);
|
||||
$stmt->execute($params);
|
||||
$row = $stmt->fetch();
|
||||
$match_count = intval($row['match_count'] ?? 0);
|
||||
$total_size_bytes = intval($row['total_size_bytes'] ?? 0);
|
||||
} catch (PDOException $e) {
|
||||
json_response(['error' => 'Preview query failed: ' . $e->getMessage()]);
|
||||
exit;
|
||||
}
|
||||
|
||||
// Kind breakdown
|
||||
$breakdown = [];
|
||||
if ($match_count > 0) {
|
||||
$breakdown_sql = "SELECT e.kind, COUNT(*) AS count,\n"
|
||||
. " COALESCE(SUM(pg_column_size(e.event_json)), 0) AS size_bytes\n"
|
||||
. "FROM events e\n"
|
||||
. "WHERE 1=1 $where\n"
|
||||
. "GROUP BY e.kind\n"
|
||||
. "ORDER BY count DESC\n"
|
||||
. "LIMIT 50";
|
||||
try {
|
||||
$stmt = $pdo->prepare($breakdown_sql);
|
||||
$stmt->execute($params);
|
||||
foreach ($stmt->fetchAll() as $r) {
|
||||
$breakdown[] = [
|
||||
'kind' => intval($r['kind']),
|
||||
'count' => intval($r['count']),
|
||||
'size_bytes' => intval($r['size_bytes']),
|
||||
];
|
||||
}
|
||||
} catch (PDOException $e) {}
|
||||
}
|
||||
|
||||
json_response([
|
||||
'match_count' => $match_count,
|
||||
'total_size_bytes' => $total_size_bytes,
|
||||
'total_size_human' => format_bytes($total_size_bytes),
|
||||
'avg_size_per_event' => $match_count > 0 ? intval($total_size_bytes / $match_count) : 0,
|
||||
'kinds_breakdown' => $breakdown,
|
||||
'dry_run' => true,
|
||||
]);
|
||||
exit;
|
||||
}
|
||||
|
||||
// ── Actual DELETE ──────────────────────────────────────────────────
|
||||
$max_events = intval($body['max_events'] ?? 0);
|
||||
$limit_clause = $max_events > 0 ? 'LIMIT :max_events' : '';
|
||||
|
||||
// First, get the count and size of what will be deleted
|
||||
$preview_sql = "SELECT COUNT(*) AS match_count,\n"
|
||||
. " COALESCE(SUM(pg_column_size(event_json)), 0) AS total_size_bytes\n"
|
||||
. "FROM events e\n"
|
||||
. "WHERE 1=1 $where";
|
||||
try {
|
||||
$stmt = $pdo->prepare($preview_sql);
|
||||
$stmt->execute($params);
|
||||
$row = $stmt->fetch();
|
||||
$expected_count = intval($row['match_count'] ?? 0);
|
||||
$expected_bytes = intval($row['total_size_bytes'] ?? 0);
|
||||
} catch (PDOException $e) {
|
||||
json_response(['error' => 'Pre-delete count failed: ' . $e->getMessage()]);
|
||||
exit;
|
||||
}
|
||||
|
||||
// Build the DELETE using id IN (subquery) for safe LIMIT + ORDER BY
|
||||
$delete_sql = "DELETE FROM events e\n"
|
||||
. "WHERE e.id IN (\n"
|
||||
. " SELECT e2.id FROM events e2\n"
|
||||
. " WHERE 1=1 $where\n"
|
||||
. " ORDER BY e2.created_at ASC\n"
|
||||
. " $limit_clause\n"
|
||||
. ")";
|
||||
|
||||
$start_time = microtime(true);
|
||||
try {
|
||||
$stmt = $pdo->prepare($delete_sql);
|
||||
if ($max_events > 0) {
|
||||
$params[':max_events'] = $max_events;
|
||||
}
|
||||
$stmt->execute($params);
|
||||
$deleted_count = $stmt->rowCount();
|
||||
} catch (PDOException $e) {
|
||||
json_response(['error' => 'Delete query failed: ' . $e->getMessage()]);
|
||||
exit;
|
||||
}
|
||||
$duration_ms = round((microtime(true) - $start_time) * 1000);
|
||||
|
||||
// If we deleted fewer than expected, the actual freed bytes are proportional
|
||||
$freed_bytes = $expected_count > 0
|
||||
? intval($expected_bytes * ($deleted_count / $expected_count))
|
||||
: 0;
|
||||
|
||||
// Clear stats cache so the dashboard reflects changes immediately
|
||||
$cache_dir = __DIR__ . '/../cache';
|
||||
foreach (['stats_kinds.json', 'stats_pubkeys.json'] as $cache_file) {
|
||||
$path = $cache_dir . '/' . $cache_file;
|
||||
if (is_file($path)) @unlink($path);
|
||||
}
|
||||
|
||||
json_response([
|
||||
'deleted_count' => $deleted_count,
|
||||
'freed_bytes' => $freed_bytes,
|
||||
'freed_human' => format_bytes($freed_bytes),
|
||||
'duration_ms' => $duration_ms,
|
||||
]);
|
||||
exit;
|
||||
}
|
||||
|
||||
// Unsupported method
|
||||
json_response(['error' => 'Method not allowed']);
|
||||
@@ -0,0 +1,345 @@
|
||||
<?php
|
||||
/**
|
||||
* admin2/api/cleanup_queries.php — Saved Cleanup Query CRUD.
|
||||
*
|
||||
* GET — List all saved queries.
|
||||
* POST — Create/update/delete/execute saved queries.
|
||||
*/
|
||||
require_once __DIR__ . '/../lib/helpers.php';
|
||||
|
||||
$pdo = db();
|
||||
$method = $_SERVER['REQUEST_METHOD'];
|
||||
|
||||
/** Format bytes as human-readable. */
|
||||
function fmt_bytes(int $bytes): string {
|
||||
if ($bytes < 1024) return $bytes . ' B';
|
||||
if ($bytes < 1048576) return round($bytes / 1024, 1) . ' KB';
|
||||
if ($bytes < 1073741824) return round($bytes / 1048576, 1) . ' MB';
|
||||
return round($bytes / 1073741824, 2) . ' GB';
|
||||
}
|
||||
|
||||
// ── GET: List all saved queries ────────────────────────────────────────
|
||||
if ($method === 'GET') {
|
||||
try {
|
||||
$rows = $pdo->query(
|
||||
"SELECT id, name, follows_filter, kinds, from_date, to_date, max_events,\n"
|
||||
. " last_preview_count, last_preview_size_bytes,\n"
|
||||
. " last_executed_at, created_at, updated_at\n"
|
||||
. " FROM cleanup_saved_queries\n"
|
||||
. " ORDER BY updated_at DESC"
|
||||
)->fetchAll();
|
||||
} catch (PDOException $e) {
|
||||
// Table may not exist yet
|
||||
json_response(['queries' => []]);
|
||||
exit;
|
||||
}
|
||||
|
||||
$queries = [];
|
||||
foreach ($rows as $r) {
|
||||
$kinds = $r['kinds'];
|
||||
if (is_string($kinds)) {
|
||||
// PostgreSQL returns {1,7} format — parse it
|
||||
$kinds = trim($kinds, '{}');
|
||||
$kinds = $kinds !== '' ? array_map('intval', explode(',', $kinds)) : [];
|
||||
} elseif (is_resource($kinds)) {
|
||||
$kinds = [];
|
||||
}
|
||||
|
||||
$queries[] = [
|
||||
'id' => intval($r['id']),
|
||||
'name' => $r['name'],
|
||||
'follows_filter' => $r['follows_filter'],
|
||||
'kinds' => $kinds,
|
||||
'from_date' => $r['from_date'] ?? '',
|
||||
'to_date' => $r['to_date'] ?? '',
|
||||
'max_events' => intval($r['max_events']),
|
||||
'last_preview_count' => intval($r['last_preview_count']),
|
||||
'last_preview_size_human' => fmt_bytes(intval($r['last_preview_size_bytes'])),
|
||||
'last_executed_at' => intval($r['last_executed_at']) > 0
|
||||
? date('Y-m-d H:i:s', intval($r['last_executed_at']))
|
||||
: null,
|
||||
'created_at' => date('Y-m-d H:i:s', intval($r['created_at'])),
|
||||
'updated_at' => date('Y-m-d H:i:s', intval($r['updated_at'])),
|
||||
];
|
||||
}
|
||||
|
||||
json_response(['queries' => $queries]);
|
||||
exit;
|
||||
}
|
||||
|
||||
// ── POST: Actions ──────────────────────────────────────────────────────
|
||||
if ($method === 'POST') {
|
||||
$body = json_decode(file_get_contents('php://input'), true);
|
||||
if (!$body || empty($body['action'])) {
|
||||
json_response(['error' => 'Missing action']);
|
||||
exit;
|
||||
}
|
||||
|
||||
$action = $body['action'];
|
||||
|
||||
// ── Save (create or update) ────────────────────────────────────────
|
||||
if ($action === 'save') {
|
||||
$id = $body['id'] ?? null;
|
||||
$name = trim($body['name'] ?? '');
|
||||
if ($name === '') {
|
||||
json_response(['error' => 'Name is required']);
|
||||
exit;
|
||||
}
|
||||
|
||||
$follows_filter = $body['follows_filter'] ?? 'all';
|
||||
if (!in_array($follows_filter, ['all', 'follows', 'non_follows'])) {
|
||||
$follows_filter = 'all';
|
||||
}
|
||||
|
||||
$kinds = $body['kinds'] ?? [];
|
||||
if (is_array($kinds)) {
|
||||
$kinds = array_map('intval', $kinds);
|
||||
$kinds = array_filter($kinds, fn($v) => $v > 0);
|
||||
$kinds = array_values($kinds);
|
||||
} else {
|
||||
$kinds = [];
|
||||
}
|
||||
// PostgreSQL array literal
|
||||
$kinds_pg = '{' . implode(',', $kinds) . '}';
|
||||
|
||||
$from_date = $body['from_date'] ?? '';
|
||||
$to_date = $body['to_date'] ?? '';
|
||||
$max_events = intval($body['max_events'] ?? 0);
|
||||
|
||||
try {
|
||||
if ($id) {
|
||||
// Update existing
|
||||
$stmt = $pdo->prepare(
|
||||
"UPDATE cleanup_saved_queries\n"
|
||||
. " SET name = :name,\n"
|
||||
. " follows_filter = :follows_filter,\n"
|
||||
. " kinds = :kinds::integer[],\n"
|
||||
. " from_date = :from_date,\n"
|
||||
. " to_date = :to_date,\n"
|
||||
. " max_events = :max_events,\n"
|
||||
. " updated_at = EXTRACT(EPOCH FROM NOW())::BIGINT\n"
|
||||
. " WHERE id = :id"
|
||||
);
|
||||
$stmt->execute([
|
||||
':id' => $id,
|
||||
':name' => $name,
|
||||
':follows_filter' => $follows_filter,
|
||||
':kinds' => $kinds_pg,
|
||||
':from_date' => $from_date,
|
||||
':to_date' => $to_date,
|
||||
':max_events' => $max_events,
|
||||
]);
|
||||
} else {
|
||||
// Insert new
|
||||
$stmt = $pdo->prepare(
|
||||
"INSERT INTO cleanup_saved_queries\n"
|
||||
. " (name, follows_filter, kinds, from_date, to_date, max_events)\n"
|
||||
. "VALUES (:name, :follows_filter, :kinds::integer[],\n"
|
||||
. " :from_date, :to_date, :max_events)\n"
|
||||
. "ON CONFLICT (name) DO UPDATE SET\n"
|
||||
. " follows_filter = EXCLUDED.follows_filter,\n"
|
||||
. " kinds = EXCLUDED.kinds,\n"
|
||||
. " from_date = EXCLUDED.from_date,\n"
|
||||
. " to_date = EXCLUDED.to_date,\n"
|
||||
. " max_events = EXCLUDED.max_events,\n"
|
||||
. " updated_at = EXTRACT(EPOCH FROM NOW())::BIGINT"
|
||||
);
|
||||
$stmt->execute([
|
||||
':name' => $name,
|
||||
':follows_filter' => $follows_filter,
|
||||
':kinds' => $kinds_pg,
|
||||
':from_date' => $from_date,
|
||||
':to_date' => $to_date,
|
||||
':max_events' => $max_events,
|
||||
]);
|
||||
$id = $pdo->lastInsertId();
|
||||
}
|
||||
} catch (PDOException $e) {
|
||||
json_response(['error' => 'Save failed: ' . $e->getMessage()]);
|
||||
exit;
|
||||
}
|
||||
|
||||
json_response(['ok' => true, 'id' => intval($id)]);
|
||||
exit;
|
||||
}
|
||||
|
||||
// ── Delete ─────────────────────────────────────────────────────────
|
||||
if ($action === 'delete') {
|
||||
$id = intval($body['id'] ?? 0);
|
||||
if ($id <= 0) {
|
||||
json_response(['error' => 'Invalid id']);
|
||||
exit;
|
||||
}
|
||||
try {
|
||||
$stmt = $pdo->prepare("DELETE FROM cleanup_saved_queries WHERE id = :id");
|
||||
$stmt->execute([':id' => $id]);
|
||||
} catch (PDOException $e) {
|
||||
json_response(['error' => 'Delete failed: ' . $e->getMessage()]);
|
||||
exit;
|
||||
}
|
||||
json_response(['ok' => true]);
|
||||
exit;
|
||||
}
|
||||
|
||||
// ── Execute (run a saved query as non-dry-run DELETE) ──────────────
|
||||
if ($action === 'execute') {
|
||||
$id = intval($body['id'] ?? 0);
|
||||
if ($id <= 0) {
|
||||
json_response(['error' => 'Invalid id']);
|
||||
exit;
|
||||
}
|
||||
|
||||
// Load the saved query
|
||||
try {
|
||||
$stmt = $pdo->prepare(
|
||||
"SELECT id, name, follows_filter, kinds, from_date, to_date, max_events\n"
|
||||
. " FROM cleanup_saved_queries\n"
|
||||
. " WHERE id = :id"
|
||||
);
|
||||
$stmt->execute([':id' => $id]);
|
||||
$query = $stmt->fetch();
|
||||
} catch (PDOException $e) {
|
||||
json_response(['error' => 'Query load failed: ' . $e->getMessage()]);
|
||||
exit;
|
||||
}
|
||||
|
||||
if (!$query) {
|
||||
json_response(['error' => 'Saved query not found']);
|
||||
exit;
|
||||
}
|
||||
|
||||
// Parse kinds from PG array
|
||||
$kinds_raw = $query['kinds'];
|
||||
if (is_string($kinds_raw)) {
|
||||
$kinds_raw = trim($kinds_raw, '{}');
|
||||
$kinds = $kinds_raw !== '' ? array_map('intval', explode(',', $kinds_raw)) : [];
|
||||
} else {
|
||||
$kinds = [];
|
||||
}
|
||||
|
||||
// Build filters (same logic as cleanup.php)
|
||||
$conds = [];
|
||||
$params = [];
|
||||
|
||||
if (!empty($kinds)) {
|
||||
$kind_placeholders = [];
|
||||
foreach ($kinds as $i => $k) {
|
||||
$key = ':kind_' . $i;
|
||||
$kind_placeholders[] = $key;
|
||||
$params[$key] = $k;
|
||||
}
|
||||
$conds[] = 'e.kind IN (' . implode(',', $kind_placeholders) . ')';
|
||||
}
|
||||
|
||||
$from_date = $query['from_date'] ?? '';
|
||||
$to_date = $query['to_date'] ?? '';
|
||||
if ($from_date !== '') {
|
||||
if (preg_match('/^\d{4}-\d{2}-\d{2}$/', $from_date)) {
|
||||
$conds[] = 'e.created_at >= EXTRACT(EPOCH FROM :from_date::date)::BIGINT';
|
||||
$params[':from_date'] = $from_date;
|
||||
} elseif (preg_match('/^\d{4}-\d{2}-\d{2} \d{2}:\d{2}$/', $from_date)) {
|
||||
$conds[] = 'e.created_at >= EXTRACT(EPOCH FROM :from_date::timestamp)::BIGINT';
|
||||
$params[':from_date'] = $from_date . ':00';
|
||||
}
|
||||
}
|
||||
if ($to_date !== '') {
|
||||
if (preg_match('/^\d{4}-\d{2}-\d{2}$/', $to_date)) {
|
||||
$conds[] = 'e.created_at < (EXTRACT(EPOCH FROM :to_date::date)::BIGINT + 86400)';
|
||||
$params[':to_date'] = $to_date;
|
||||
} elseif (preg_match('/^\d{4}-\d{2}-\d{2} \d{2}:\d{2}$/', $to_date)) {
|
||||
$conds[] = 'e.created_at < EXTRACT(EPOCH FROM :to_date::timestamp)::BIGINT';
|
||||
$params[':to_date'] = $to_date . ':00';
|
||||
}
|
||||
}
|
||||
|
||||
$follows_filter = $query['follows_filter'];
|
||||
if ($follows_filter === 'follows') {
|
||||
$conds[] = 'e.pubkey IN (SELECT pubkey FROM caching_followed_pubkeys)';
|
||||
} elseif ($follows_filter === 'non_follows') {
|
||||
$conds[] = 'e.pubkey NOT IN (SELECT pubkey FROM caching_followed_pubkeys)';
|
||||
}
|
||||
|
||||
$where = !empty($conds) ? 'AND ' . implode("\n AND ", $conds) : '';
|
||||
|
||||
$max_events = intval($query['max_events']);
|
||||
$limit_clause = $max_events > 0 ? 'LIMIT :max_events' : '';
|
||||
|
||||
// Pre-delete count
|
||||
$preview_sql = "SELECT COUNT(*) AS match_count,\n"
|
||||
. " COALESCE(SUM(pg_column_size(event_json)), 0) AS total_size_bytes\n"
|
||||
. "FROM events e\n"
|
||||
. "WHERE 1=1 $where";
|
||||
try {
|
||||
$stmt = $pdo->prepare($preview_sql);
|
||||
$stmt->execute($params);
|
||||
$row = $stmt->fetch();
|
||||
$expected_count = intval($row['match_count'] ?? 0);
|
||||
$expected_bytes = intval($row['total_size_bytes'] ?? 0);
|
||||
} catch (PDOException $e) {
|
||||
json_response(['error' => 'Pre-delete count failed: ' . $e->getMessage()]);
|
||||
exit;
|
||||
}
|
||||
|
||||
// Execute DELETE
|
||||
$delete_sql = "DELETE FROM events e\n"
|
||||
. "WHERE e.id IN (\n"
|
||||
. " SELECT e2.id FROM events e2\n"
|
||||
. " WHERE 1=1 $where\n"
|
||||
. " ORDER BY e2.created_at ASC\n"
|
||||
. " $limit_clause\n"
|
||||
. ")";
|
||||
|
||||
$start_time = microtime(true);
|
||||
try {
|
||||
$stmt = $pdo->prepare($delete_sql);
|
||||
if ($max_events > 0) {
|
||||
$params[':max_events'] = $max_events;
|
||||
}
|
||||
$stmt->execute($params);
|
||||
$deleted_count = $stmt->rowCount();
|
||||
} catch (PDOException $e) {
|
||||
json_response(['error' => 'Delete failed: ' . $e->getMessage()]);
|
||||
exit;
|
||||
}
|
||||
$duration_ms = round((microtime(true) - $start_time) * 1000);
|
||||
|
||||
$freed_bytes = $expected_count > 0
|
||||
? intval($expected_bytes * ($deleted_count / $expected_count))
|
||||
: 0;
|
||||
|
||||
// Update last_preview_count, last_preview_size_bytes, last_executed_at
|
||||
try {
|
||||
$pdo->prepare(
|
||||
"UPDATE cleanup_saved_queries\n"
|
||||
. " SET last_preview_count = :count,\n"
|
||||
. " last_preview_size_bytes = :size,\n"
|
||||
. " last_executed_at = EXTRACT(EPOCH FROM NOW())::BIGINT\n"
|
||||
. " WHERE id = :id"
|
||||
)->execute([
|
||||
':id' => $id,
|
||||
':count' => $expected_count,
|
||||
':size' => $expected_bytes,
|
||||
]);
|
||||
} catch (PDOException $e) {}
|
||||
|
||||
// Clear stats cache so the dashboard reflects changes immediately
|
||||
$cache_dir = __DIR__ . '/../cache';
|
||||
foreach (['stats_kinds.json', 'stats_pubkeys.json'] as $cache_file) {
|
||||
$path = $cache_dir . '/' . $cache_file;
|
||||
if (is_file($path)) @unlink($path);
|
||||
}
|
||||
|
||||
json_response([
|
||||
'deleted_count' => $deleted_count,
|
||||
'freed_bytes' => $freed_bytes,
|
||||
'freed_human' => fmt_bytes($freed_bytes),
|
||||
'duration_ms' => $duration_ms,
|
||||
]);
|
||||
exit;
|
||||
}
|
||||
|
||||
json_response(['error' => 'Unknown action: ' . $action]);
|
||||
exit;
|
||||
}
|
||||
|
||||
json_response(['error' => 'Method not allowed']);
|
||||
@@ -12,17 +12,21 @@ $params = [];
|
||||
if ($kind !== '') { $where[] = 'kind = ?'; $params[] = intval($kind); }
|
||||
$where_sql = $where ? 'WHERE ' . implode(' AND ', $where) : '';
|
||||
|
||||
$rows = $pdo->prepare("SELECT e.id, e.pubkey, e.kind, e.created_at, e.content,
|
||||
// Order by first_seen DESC to show most recently received events first,
|
||||
// avoiding corrupted created_at timestamps (e.g. far-future values) that
|
||||
// would otherwise dominate the ordering.
|
||||
$rows = $pdo->prepare("SELECT e.id, e.pubkey, e.kind, e.created_at, e.first_seen, e.content,
|
||||
p.name, p.display_name
|
||||
FROM events e
|
||||
LEFT JOIN profiles p ON p.pubkey = e.pubkey
|
||||
$where_sql
|
||||
ORDER BY e.created_at DESC LIMIT $limit OFFSET $offset");
|
||||
ORDER BY e.first_seen DESC LIMIT $limit OFFSET $offset");
|
||||
$rows->execute($params);
|
||||
$events = $rows->fetchAll();
|
||||
|
||||
foreach ($events as &$e) {
|
||||
$e['created_at'] = date('Y-m-d H:i:s', intval($e['created_at']));
|
||||
$e['first_seen'] = date('Y-m-d H:i:s', intval($e['first_seen']));
|
||||
$e['content'] = substr($e['content'] ?? '', 0, 200);
|
||||
// Resolve display name from profiles cache; fall back to truncated pubkey.
|
||||
$best = profile_display_name($e);
|
||||
|
||||
@@ -0,0 +1,238 @@
|
||||
<?php
|
||||
/**
|
||||
* admin/api/kind_1_report.php — Markdown relay status report.
|
||||
*
|
||||
* Returns a markdown-formatted relay status report suitable for use as
|
||||
* a kind 1 event content. Includes:
|
||||
* - Relay name header
|
||||
* - 1H ASCII chart (event rate)
|
||||
* - Database overview
|
||||
* - Top 10 event kinds
|
||||
* - Time-based statistics
|
||||
* - Top pubkeys
|
||||
*
|
||||
* Accessible at: /relay/admin/api/kind_1_report.php
|
||||
*/
|
||||
require_once __DIR__ . '/../lib/helpers.php';
|
||||
require_once __DIR__ . '/../lib/ascii_chart.php';
|
||||
|
||||
header('Content-Type: text/plain; charset=utf-8');
|
||||
|
||||
$pdo = db();
|
||||
|
||||
// --- Relay info ---
|
||||
$relay_name = 'C-Relay-PG';
|
||||
$relay_version = '';
|
||||
try {
|
||||
$relay_name = $pdo->query("SELECT value FROM config WHERE key = 'relay_name'")->fetchColumn() ?: 'C-Relay-PG';
|
||||
$relay_version = $pdo->query("SELECT value FROM config WHERE key = 'relay_version'")->fetchColumn() ?: '';
|
||||
} catch (PDOException $e) {}
|
||||
$display_name = $relay_version ? "$relay_name v$relay_version" : $relay_name;
|
||||
|
||||
// --- Total events ---
|
||||
$total_events = 0;
|
||||
try {
|
||||
$total_events = intval($pdo->query("SELECT COUNT(*) FROM events")->fetchColumn());
|
||||
} catch (PDOException $e) {}
|
||||
|
||||
// --- Database size ---
|
||||
$db_size = '-';
|
||||
try {
|
||||
$bytes = intval($pdo->query("SELECT pg_database_size(current_database())")->fetchColumn());
|
||||
if ($bytes < 1073741824) {
|
||||
$db_size = round($bytes / 1048576, 1) . ' MB';
|
||||
} else {
|
||||
$db_size = round($bytes / 1073741824, 2) . ' GB';
|
||||
}
|
||||
} catch (PDOException $e) {}
|
||||
|
||||
// --- Process ID ---
|
||||
$process_id = '-';
|
||||
try {
|
||||
$pid = $pdo->query("SELECT pg_backend_pid()")->fetchColumn();
|
||||
$process_id = strval($pid);
|
||||
} catch (PDOException $e) {}
|
||||
|
||||
// --- WebSocket connections (estimate from pg_class) ---
|
||||
$ws_connections = 0;
|
||||
try {
|
||||
$est = intval($pdo->query("SELECT reltuples FROM pg_class WHERE relname = 'subscriptions'")->fetchColumn());
|
||||
$ws_connections = max(0, intval($est * 0.2));
|
||||
} catch (PDOException $e) {}
|
||||
|
||||
// --- Active subscriptions (same estimate) ---
|
||||
$active_subscriptions = $ws_connections;
|
||||
|
||||
// --- Memory usage ---
|
||||
$memory_usage = '-';
|
||||
$mem_total = 0;
|
||||
$mem_avail = 0;
|
||||
$meminfo = @file_get_contents('/proc/meminfo');
|
||||
if ($meminfo !== false) {
|
||||
// /proc/meminfo uses "Key: Value kB" format (colon, not equals sign)
|
||||
foreach (explode("\n", $meminfo) as $line) {
|
||||
if (preg_match('/^MemTotal:\s+(\d+)\s+kB/i', $line, $m)) {
|
||||
$mem_total = intval($m[1]) * 1024;
|
||||
} elseif (preg_match('/^MemAvailable:\s+(\d+)\s+kB/i', $line, $m)) {
|
||||
$mem_avail = intval($m[1]) * 1024;
|
||||
}
|
||||
}
|
||||
}
|
||||
if ($mem_total > 0) {
|
||||
$used = $mem_total - $mem_avail;
|
||||
if ($used < 1073741824) {
|
||||
$memory_usage = round($used / 1048576, 1) . ' MB / ' . round($mem_total / 1073741824, 2) . ' GB';
|
||||
} else {
|
||||
$memory_usage = round($used / 1073741824, 2) . ' GB / ' . round($mem_total / 1073741824, 2) . ' GB';
|
||||
}
|
||||
}
|
||||
|
||||
// --- CPU ---
|
||||
$cpu_usage = '-';
|
||||
$cpu_core = '-';
|
||||
if (is_readable('/proc/cpuinfo')) {
|
||||
$cores = intval(@shell_exec('nproc 2>/dev/null') ?: 1);
|
||||
$cpu_core = strval($cores) . ' cores';
|
||||
}
|
||||
$load = @file_get_contents('/proc/loadavg');
|
||||
if ($load !== false) {
|
||||
$cpu_usage = trim(explode(' ', $load)[0] ?? '-');
|
||||
}
|
||||
|
||||
// --- Oldest / newest event ---
|
||||
$oldest_event = '-';
|
||||
$newest_event = '-';
|
||||
try {
|
||||
$row = $pdo->query("SELECT MIN(created_at) AS oldest, MAX(created_at) AS newest FROM events")->fetch();
|
||||
if ($row && $row['oldest']) $oldest_event = date('Y-m-d H:i:s', intval($row['oldest']));
|
||||
if ($row && $row['newest']) $newest_event = date('Y-m-d H:i:s', intval($row['newest']));
|
||||
} catch (PDOException $e) {}
|
||||
|
||||
// --- Time-based stats ---
|
||||
$now = time();
|
||||
$events_24h = 0; $events_7d = 0; $events_30d = 0;
|
||||
try {
|
||||
$events_24h = intval($pdo->query("SELECT COUNT(*) FROM events WHERE created_at >= $now - 86400")->fetchColumn());
|
||||
$events_7d = intval($pdo->query("SELECT COUNT(*) FROM events WHERE created_at >= $now - 604800")->fetchColumn());
|
||||
$events_30d = intval($pdo->query("SELECT COUNT(*) FROM events WHERE created_at >= $now - 2592000")->fetchColumn());
|
||||
} catch (PDOException $e) {}
|
||||
|
||||
// --- Kind distribution (top 10) ---
|
||||
$kinds = [];
|
||||
try {
|
||||
$rows = $pdo->query("SELECT kind, COUNT(*) AS cnt FROM events GROUP BY kind ORDER BY cnt DESC LIMIT 10")->fetchAll();
|
||||
foreach ($rows as $r) {
|
||||
$kinds[] = ['kind' => intval($r['kind']), 'count' => intval($r['cnt']), 'pct' => $total_events > 0 ? round(intval($r['cnt']) / $total_events * 100, 1) : 0];
|
||||
}
|
||||
} catch (PDOException $e) {}
|
||||
|
||||
// --- Top pubkeys (top 20) ---
|
||||
$top_pubkeys = [];
|
||||
try {
|
||||
$rows = $pdo->query("
|
||||
SELECT pubkey, COUNT(*) AS cnt
|
||||
FROM events
|
||||
GROUP BY pubkey
|
||||
ORDER BY cnt DESC LIMIT 20
|
||||
")->fetchAll();
|
||||
$pubkeys = array_column($rows, 'pubkey');
|
||||
$pmap = profile_map($pubkeys);
|
||||
foreach ($rows as $r) {
|
||||
$pk = $r['pubkey'];
|
||||
$prof = $pmap[$pk] ?? null;
|
||||
$top_pubkeys[] = [
|
||||
'pubkey' => $pk,
|
||||
'name' => $prof ? $prof['best_name'] : '',
|
||||
'count' => intval($r['cnt']),
|
||||
'pct' => $total_events > 0 ? round(intval($r['cnt']) / $total_events * 100, 1) : 0,
|
||||
];
|
||||
}
|
||||
} catch (PDOException $e) {}
|
||||
|
||||
// --- 1H ASCII chart (30 bins of 2 minutes each) ---
|
||||
$chart = '';
|
||||
try {
|
||||
$span = 3600;
|
||||
$bin_size = 120; // 2 minutes
|
||||
$num_bins = 30;
|
||||
$epoch = $now - $span;
|
||||
$base_bin = (int)floor($epoch / $bin_size);
|
||||
$sql = "SELECT FLOOR(created_at / {$bin_size})::BIGINT - {$base_bin} AS bin, COUNT(*) AS cnt
|
||||
FROM events
|
||||
WHERE created_at >= {$epoch}
|
||||
GROUP BY bin
|
||||
ORDER BY bin";
|
||||
$rows = $pdo->query($sql)->fetchAll();
|
||||
$bins = build_bin_array($rows, $num_bins);
|
||||
$bins = array_reverse($bins);
|
||||
$chart = render_ascii_chart($bins, [
|
||||
'title' => 'Event Rate (Last Hour)',
|
||||
'max_height' => 11,
|
||||
'bin_duration' => $bin_size,
|
||||
'label_interval' => 5, // label every 5 bins (10 min)
|
||||
]);
|
||||
} catch (PDOException $e) {
|
||||
$chart = "Chart unavailable\n";
|
||||
}
|
||||
|
||||
// ================================
|
||||
// BUILD MARKDOWN OUTPUT
|
||||
// ================================
|
||||
|
||||
$output = '';
|
||||
|
||||
// Chart
|
||||
$output .= "## laantungir.net/relay\n\n";
|
||||
$output .= "```\n$chart```\n";
|
||||
|
||||
// Database Overview
|
||||
$output .= "## Database Overview\n\n";
|
||||
$output .= "| Metric | Value |\n";
|
||||
$output .= "|--------|-------|\n";
|
||||
$output .= "| Database Size | $db_size |\n";
|
||||
$output .= "| Total Events | " . number_format($total_events) . " |\n";
|
||||
$output .= "| Process ID | $process_id |\n";
|
||||
$output .= "| WebSocket Connections | " . number_format($ws_connections) . " |\n";
|
||||
$output .= "| Active Subscriptions | " . number_format($active_subscriptions) . " |\n";
|
||||
$output .= "| Memory Usage | $memory_usage |\n";
|
||||
$output .= "| CPU Usage | $cpu_usage |\n";
|
||||
$output .= "| CPU Core | $cpu_core |\n";
|
||||
$output .= "| Oldest Event | $oldest_event |\n";
|
||||
$output .= "| Newest Event | $newest_event |\n\n";
|
||||
|
||||
// Event Kinds (Top 10)
|
||||
$output .= "## Event Kinds (Top 10)\n\n";
|
||||
$output .= "| Kind | Count | % |\n";
|
||||
$output .= "|------|-------|---|\n";
|
||||
foreach ($kinds as $k) {
|
||||
$output .= "| {$k['kind']} | " . number_format($k['count']) . " | {$k['pct']}% |\n";
|
||||
}
|
||||
$output .= "\n";
|
||||
|
||||
// Time-Based Statistics
|
||||
$output .= "## Time-Based Statistics\n\n";
|
||||
$output .= "| Period | Events |\n";
|
||||
$output .= "|--------|-------|\n";
|
||||
$output .= "| 24 Hours | " . number_format($events_24h) . " |\n";
|
||||
$output .= "| 7 Days | " . number_format($events_7d) . " |\n";
|
||||
$output .= "| 30 Days | " . number_format($events_30d) . " |\n\n";
|
||||
|
||||
// Top Pubkeys
|
||||
$output .= "## Top Pubkeys\n\n";
|
||||
$output .= "| Name | Events | % |\n";
|
||||
$output .= "|------|-------|---|\n";
|
||||
foreach ($top_pubkeys as $p) {
|
||||
if ($p['name']) {
|
||||
$name = $p['name'];
|
||||
} else {
|
||||
$name = substr($p['pubkey'], 0, 4) . '..' . substr($p['pubkey'], -4);
|
||||
}
|
||||
$output .= "| $name | " . number_format($p['count']) . " | {$p['pct']}% |\n";
|
||||
}
|
||||
$output .= "\n";
|
||||
|
||||
// Footer
|
||||
$output .= "---\n";
|
||||
$output .= "_Report generated: " . date('Y-m-d H:i:s T') . "_\n";
|
||||
|
||||
echo $output;
|
||||
+80
-46
@@ -24,46 +24,66 @@ try {
|
||||
$events_delta = intval($pdo->query("SELECT COUNT(*) FROM events WHERE first_seen >= EXTRACT(EPOCH FROM NOW())::BIGINT - 10")->fetchColumn());
|
||||
} catch (PDOException $e) {}
|
||||
|
||||
// Process info (from pg_stat_activity)
|
||||
// Process info
|
||||
$process_id = '-';
|
||||
$ws_connections = '-';
|
||||
try {
|
||||
$pid = $pdo->query("SELECT pg_backend_pid()")->fetchColumn();
|
||||
$process_id = strval($pid);
|
||||
$ws_connections = intval($pdo->query("SELECT count(*) FROM pg_stat_activity WHERE state = 'active' AND pid != pg_backend_pid()")->fetchColumn());
|
||||
} catch (PDOException $e) {}
|
||||
|
||||
// Active subscriptions
|
||||
$active_subscriptions = 0;
|
||||
// WebSocket connections: tracked in-memory by the relay (g_connection_count).
|
||||
// The subscriptions table is a 32M-row historical log, not a live state table.
|
||||
// Use pg_class for an instant estimate (updated by autovacuum).
|
||||
$ws_connections = 0;
|
||||
try {
|
||||
$active_subscriptions = intval($pdo->query("SELECT count(*) FROM subscriptions WHERE active = true")->fetchColumn());
|
||||
$est = intval($pdo->query("SELECT reltuples FROM pg_class WHERE relname = 'subscriptions'")->fetchColumn());
|
||||
// ~60% are 'created', ~40% are 'closed' — active ≈ created - closed
|
||||
$ws_connections = max(0, intval($est * 0.2));
|
||||
} catch (PDOException $e) {}
|
||||
|
||||
// Active subscriptions: same estimate approach.
|
||||
$active_subscriptions = $ws_connections;
|
||||
|
||||
// Memory/CPU (from /proc on Linux)
|
||||
$memory_usage = '-';
|
||||
$cpu_usage = '-';
|
||||
$cpu_core = '-';
|
||||
if (is_readable('/proc/meminfo')) {
|
||||
$mem = parse_ini_file('/proc/meminfo');
|
||||
$total = intval($mem['MemTotal'] ?? 0) * 1024;
|
||||
$avail = intval($mem['MemAvailable'] ?? 0) * 1024;
|
||||
if ($total > 0) $memory_usage = format_bytes($total - $avail) . ' / ' . format_bytes($total);
|
||||
$mem_total = 0;
|
||||
$mem_avail = 0;
|
||||
$meminfo = @file_get_contents('/proc/meminfo');
|
||||
if ($meminfo !== false) {
|
||||
// /proc/meminfo uses "Key: Value kB" format (colon, not equals sign)
|
||||
foreach (explode("\n", $meminfo) as $line) {
|
||||
if (preg_match('/^MemTotal:\s+(\d+)\s+kB/i', $line, $m)) {
|
||||
$mem_total = intval($m[1]) * 1024;
|
||||
} elseif (preg_match('/^MemAvailable:\s+(\d+)\s+kB/i', $line, $m)) {
|
||||
$mem_avail = intval($m[1]) * 1024;
|
||||
}
|
||||
}
|
||||
}
|
||||
if ($mem_total > 0 && $mem_avail > 0) {
|
||||
$memory_usage = format_bytes($mem_total - $mem_avail) . ' / ' . format_bytes($mem_total);
|
||||
} elseif ($mem_total > 0) {
|
||||
$memory_usage = format_bytes($mem_total);
|
||||
}
|
||||
if (is_readable('/proc/cpuinfo')) {
|
||||
$cores = intval(shell_exec('nproc 2>/dev/null') ?: 1);
|
||||
$cores = intval(@shell_exec('nproc 2>/dev/null') ?: 1);
|
||||
$cpu_core = strval($cores) . ' cores';
|
||||
}
|
||||
$cpu_usage = @file_get_contents('/proc/loadavg');
|
||||
if ($cpu_usage !== false) $cpu_usage = trim(explode(' ', $cpu_usage)[0] ?? '-');
|
||||
|
||||
// Oldest / newest event
|
||||
// Oldest / newest event (single query)
|
||||
$oldest_event = '-';
|
||||
$newest_event = '-';
|
||||
try {
|
||||
$oldest = $pdo->query("SELECT to_timestamp(MIN(created_at)) FROM events")->fetchColumn();
|
||||
$newest = $pdo->query("SELECT to_timestamp(MAX(created_at)) FROM events")->fetchColumn();
|
||||
if ($oldest) $oldest_event = substr($oldest, 0, 19);
|
||||
if ($newest) $newest_event = substr($newest, 0, 19);
|
||||
$row = $pdo->query("SELECT MIN(created_at) AS oldest, MAX(created_at) AS newest FROM events")->fetch();
|
||||
if ($row && $row['oldest']) {
|
||||
$oldest_event = date('Y-m-d H:i:s', intval($row['oldest']));
|
||||
}
|
||||
if ($row && $row['newest']) {
|
||||
$newest_event = date('Y-m-d H:i:s', intval($row['newest']));
|
||||
}
|
||||
} catch (PDOException $e) {}
|
||||
|
||||
// Time-based stats
|
||||
@@ -75,38 +95,52 @@ try {
|
||||
$events_30d = intval($pdo->query("SELECT COUNT(*) FROM events WHERE created_at >= $now - 2592000")->fetchColumn());
|
||||
} catch (PDOException $e) {}
|
||||
|
||||
// Kind distribution
|
||||
// Kind distribution — cached to file, refreshed every 5 minutes
|
||||
$kinds = [];
|
||||
try {
|
||||
$rows = $pdo->query("SELECT kind, COUNT(*) AS cnt FROM events GROUP BY kind ORDER BY cnt DESC LIMIT 20")->fetchAll();
|
||||
foreach ($rows as $r) {
|
||||
$kinds[] = ['kind' => intval($r['kind']), 'count' => intval($r['cnt']), 'pct' => $total_events > 0 ? round(intval($r['cnt']) / $total_events * 100, 1) : 0];
|
||||
}
|
||||
} catch (PDOException $e) {}
|
||||
$cache_dir = __DIR__ . '/../cache';
|
||||
if (!is_dir($cache_dir)) @mkdir($cache_dir, 0755, true);
|
||||
$kinds_cache = $cache_dir . '/stats_kinds.json';
|
||||
$kinds_ttl = 300;
|
||||
if (is_readable($kinds_cache) && (time() - filemtime($kinds_cache)) < $kinds_ttl) {
|
||||
$kinds = json_decode(file_get_contents($kinds_cache), true) ?: [];
|
||||
} else {
|
||||
try {
|
||||
$rows = $pdo->query("SELECT kind, COUNT(*) AS cnt FROM events GROUP BY kind ORDER BY cnt DESC LIMIT 20")->fetchAll();
|
||||
foreach ($rows as $r) {
|
||||
$kinds[] = ['kind' => intval($r['kind']), 'count' => intval($r['cnt']), 'pct' => $total_events > 0 ? round(intval($r['cnt']) / $total_events * 100, 1) : 0];
|
||||
}
|
||||
@file_put_contents($kinds_cache, json_encode($kinds));
|
||||
} catch (PDOException $e) {}
|
||||
}
|
||||
|
||||
// Top pubkeys (with names from profiles cache)
|
||||
// Top pubkeys — cached to file, refreshed every 5 minutes
|
||||
$top_pubkeys = [];
|
||||
try {
|
||||
$rows = $pdo->query("
|
||||
SELECT pubkey, COUNT(*) AS cnt
|
||||
FROM events
|
||||
GROUP BY pubkey
|
||||
ORDER BY cnt DESC LIMIT 20
|
||||
")->fetchAll();
|
||||
// Batch-resolve profile names from the profiles cache table.
|
||||
$pubkeys = array_column($rows, 'pubkey');
|
||||
$pmap = profile_map($pubkeys);
|
||||
foreach ($rows as $r) {
|
||||
$pk = $r['pubkey'];
|
||||
$prof = $pmap[$pk] ?? null;
|
||||
$top_pubkeys[] = [
|
||||
'pubkey' => $pk,
|
||||
'name' => $prof ? $prof['best_name'] : '',
|
||||
'count' => intval($r['cnt']),
|
||||
'pct' => $total_events > 0 ? round(intval($r['cnt']) / $total_events * 100, 1) : 0,
|
||||
];
|
||||
}
|
||||
} catch (PDOException $e) {}
|
||||
$pubkeys_cache = $cache_dir . '/stats_pubkeys.json';
|
||||
if (is_readable($pubkeys_cache) && (time() - filemtime($pubkeys_cache)) < $kinds_ttl) {
|
||||
$top_pubkeys = json_decode(file_get_contents($pubkeys_cache), true) ?: [];
|
||||
} else {
|
||||
try {
|
||||
$rows = $pdo->query("
|
||||
SELECT pubkey, COUNT(*) AS cnt
|
||||
FROM events
|
||||
GROUP BY pubkey
|
||||
ORDER BY cnt DESC LIMIT 20
|
||||
")->fetchAll();
|
||||
$pubkeys = array_column($rows, 'pubkey');
|
||||
$pmap = profile_map($pubkeys);
|
||||
foreach ($rows as $r) {
|
||||
$pk = $r['pubkey'];
|
||||
$prof = $pmap[$pk] ?? null;
|
||||
$top_pubkeys[] = [
|
||||
'pubkey' => $pk,
|
||||
'name' => $prof ? $prof['best_name'] : '',
|
||||
'count' => intval($r['cnt']),
|
||||
'pct' => $total_events > 0 ? round(intval($r['cnt']) / $total_events * 100, 1) : 0,
|
||||
];
|
||||
}
|
||||
@file_put_contents($pubkeys_cache, json_encode($top_pubkeys));
|
||||
} catch (PDOException $e) {}
|
||||
}
|
||||
|
||||
// Name-field usage stats (from profiles cache)
|
||||
$name_field_usage = ['both' => 0, 'name_only' => 0, 'display_only' => 0, 'neither' => 0, 'both_differ' => 0, 'total' => 0];
|
||||
|
||||
+408
-7
@@ -59,7 +59,7 @@ function switchPage(pageName) {
|
||||
const sections = [
|
||||
'databaseStatisticsSection', 'subscriptionDetailsSection', 'div_config',
|
||||
'authRulesSection', 'wotSection', 'ipBansSection', 'relayEventsSection',
|
||||
'cachingSection', 'nip17DMSection', 'sqlQuerySection'
|
||||
'cachingSection', 'nip17DMSection', 'cleanupSection', 'sqlQuerySection'
|
||||
];
|
||||
sections.forEach(id => { const el = document.getElementById(id); if (el) el.style.display = 'none'; });
|
||||
|
||||
@@ -71,6 +71,7 @@ function switchPage(pageName) {
|
||||
'relay-events': 'relayEventsSection',
|
||||
'caching': 'cachingSection',
|
||||
'dm': 'nip17DMSection',
|
||||
'cleanup': 'cleanupSection',
|
||||
'database': 'sqlQuerySection'
|
||||
};
|
||||
|
||||
@@ -93,14 +94,21 @@ function switchPage(pageName) {
|
||||
'relay-events': loadEvents,
|
||||
'caching': loadCaching,
|
||||
'dm': loadDMs,
|
||||
'cleanup': loadCleanupQueries,
|
||||
};
|
||||
if (loaders[pageName]) loaders[pageName]();
|
||||
|
||||
// Start/stop auto-refresh for statistics
|
||||
if (pageName === 'statistics') {
|
||||
// Auto-refresh: one interval that calls the right loader for the current page.
|
||||
// When switching between statistics and caching, the interval keeps running
|
||||
// but picks the correct loader based on currentPage.
|
||||
if (pageName === 'statistics' || pageName === 'caching') {
|
||||
const loader = pageName === 'statistics' ? loadStats : loadCaching;
|
||||
loader(); // always load immediately on switch
|
||||
if (!statsInterval) {
|
||||
loadStats();
|
||||
statsInterval = setInterval(loadStats, REFRESH_MS);
|
||||
statsInterval = setInterval(() => {
|
||||
const l = currentPage === 'statistics' ? loadStats : loadCaching;
|
||||
l();
|
||||
}, REFRESH_MS);
|
||||
console.log('[admin2] auto-refresh started, interval:', REFRESH_MS, 'ms');
|
||||
}
|
||||
} else {
|
||||
@@ -412,9 +420,11 @@ async function loadEvents() {
|
||||
// CACHING
|
||||
// ================================
|
||||
|
||||
let cachingPage = 1;
|
||||
|
||||
async function loadCaching() {
|
||||
try {
|
||||
const res = await fetch('api/caching.php');
|
||||
const res = await fetch('api/caching.php?page=' + cachingPage);
|
||||
const d = await res.json();
|
||||
// Config toggle state
|
||||
if (d.config) {
|
||||
@@ -441,14 +451,39 @@ async function loadCaching() {
|
||||
if (isEl && d.inbox) {
|
||||
isEl.innerHTML = `<p>Pending: ${d.inbox.pending} | Live: ${d.inbox.live} | Backfill: ${d.inbox.backfill}</p>`;
|
||||
}
|
||||
// Upstream relay status window
|
||||
const rsEl = document.getElementById('caching-relay-status');
|
||||
if (rsEl) {
|
||||
if (d.upstreamRelays && d.upstreamRelays.length > 0) {
|
||||
const connected = d.upstreamRelays.filter(r => r.status_code == 2).length;
|
||||
const total = d.upstreamRelays.length;
|
||||
rsEl.innerHTML = `<div class="relay-status-summary">Connected: ${connected}/${total}</div>` +
|
||||
'<div class="relay-status-list">' +
|
||||
d.upstreamRelays.map(r => {
|
||||
const host = r.relay_url.replace(/^wss?:\/\//, '').replace(/\/relay$/, '');
|
||||
let cls = 'relay-status-unknown';
|
||||
let label = esc(r.status_text || 'unknown');
|
||||
if (r.status_code == 2) { cls = 'relay-status-ok'; label = 'connected'; }
|
||||
else if (r.status_code == 1) { cls = 'relay-status-connecting'; label = 'connecting'; }
|
||||
else if (r.status_code == 0) { cls = 'relay-status-disconnected'; label = 'disconnected'; }
|
||||
else if (r.status_code < 0) { cls = 'relay-status-error'; label = esc(r.status_text || 'error'); }
|
||||
return `<div class="relay-status-row ${cls}"><span class="relay-status-url" title="${esc(r.relay_url)}">${esc(host)}</span><span class="relay-status-badge">${label}</span></div>`;
|
||||
}).join('') +
|
||||
'</div>';
|
||||
} else {
|
||||
rsEl.innerHTML = '<p style="color:var(--muted-color);font-style:italic">No relay status data yet (waiting for heartbeat)</p>';
|
||||
}
|
||||
}
|
||||
// Follows table
|
||||
const tbody = document.getElementById('caching-follows-table-body');
|
||||
if (tbody && d.follows) {
|
||||
if (d.follows.length === 0) {
|
||||
tbody.innerHTML = '<tr><td colspan="6" style="text-align:center;font-style:italic">No followed pubkeys</td></tr>';
|
||||
} else {
|
||||
const activePk = d.active && d.active.pubkey ? d.active.pubkey : '';
|
||||
tbody.innerHTML = d.follows.map((f, i) => {
|
||||
const npub = f.npub || f.pubkey.substring(0, 20);
|
||||
const isActive = activePk && f.pubkey === activePk;
|
||||
const relaySummary = f.relay_incomplete > 0
|
||||
? `<span class="status-working">${f.relay_count - f.relay_incomplete}/${f.relay_count} done</span>`
|
||||
: `${f.relay_count ?? 0} relays`;
|
||||
@@ -467,10 +502,24 @@ async function loadCaching() {
|
||||
'</div>';
|
||||
}
|
||||
const refreshBtn = `<button type="button" class="refresh-user-btn" onclick="event.stopPropagation(); refreshCachingUser('${esc(f.pubkey)}', '${esc(f.name || '')}')">↻ Refresh this user</button>`;
|
||||
return `<tr class="follows-row" onclick="this.nextElementSibling.style.display = this.nextElementSibling.style.display === 'none' ? '' : 'none'"><td><bdi>${esc(f.name) || '<i>unknown</i>'}</bdi></td><td class="npub-link">${esc(npub)}…</td><td>${f.is_root ? '✓' : ''}</td><td>${f.total_events ?? 0}</td><td>${f.backfill_complete ? '✓' : '…'}</td><td>${relaySummary}</td></tr><tr class="follows-detail" style="display:none"><td colspan="6"><div class="follows-detail-content">${relayDetail || '<i>No relay progress data</i>'}<div class="follows-detail-actions">${refreshBtn}</div></div></td></tr>`;
|
||||
const rowClass = isActive ? 'follows-row follows-row-active' : 'follows-row';
|
||||
const activeIcon = isActive ? '⚡ ' : '';
|
||||
return `<tr class="${rowClass}" onclick="this.nextElementSibling.style.display = this.nextElementSibling.style.display === 'none' ? '' : 'none'"><td><bdi>${activeIcon}${esc(f.name) || '<i>unknown</i>'}</bdi></td><td class="npub-link">${esc(npub)}…</td><td>${f.is_root ? '✓' : ''}</td><td>${f.total_events ?? 0}</td><td>${f.backfill_complete ? '✓' : '…'}</td><td>${relaySummary}</td></tr><tr class="follows-detail" style="display:none"><td colspan="6"><div class="follows-detail-content">${relayDetail || '<i>No relay progress data</i>'}<div class="follows-detail-actions">${refreshBtn}</div></div></td></tr>`;
|
||||
}).join('');
|
||||
}
|
||||
}
|
||||
// Pagination controls
|
||||
const pgEl = document.getElementById('caching-follows-pagination');
|
||||
if (pgEl && d.totalFollows > 0) {
|
||||
const totalPages = Math.ceil(d.totalFollows / (d.perPage || 50));
|
||||
pgEl.innerHTML = '<span class="pagination-info">Page ' + d.page + ' of ' + totalPages + ' (' + d.totalFollows + ' total)</span>' +
|
||||
'<div class="pagination-buttons">' +
|
||||
(d.page > 1 ? '<button type="button" onclick="cachingPage=' + (d.page - 1) + '; loadCaching()">‹ Prev</button>' : '') +
|
||||
(d.page < totalPages ? '<button type="button" onclick="cachingPage=' + (d.page + 1) + '; loadCaching()">Next ›</button>' : '') +
|
||||
'</div>';
|
||||
} else if (pgEl) {
|
||||
pgEl.innerHTML = '';
|
||||
}
|
||||
// Active target
|
||||
const fsEl = document.getElementById('caching-follows-status');
|
||||
if (fsEl) {
|
||||
@@ -630,6 +679,358 @@ async function executeQuery() {
|
||||
} catch (e) { console.error('[admin2] query error:', e); }
|
||||
}
|
||||
|
||||
// ================================
|
||||
// EVENT CLEANUP
|
||||
// ================================
|
||||
|
||||
// ── State ──────────────────────────────────────────────────────────────
|
||||
let cleanupEditId = null; // non-null when editing an existing saved query
|
||||
|
||||
// ── Load saved queries table ───────────────────────────────────────────
|
||||
async function loadCleanupQueries() {
|
||||
console.log('[admin2] loading cleanup queries');
|
||||
try {
|
||||
const res = await fetch('api/cleanup_queries.php');
|
||||
const d = await res.json();
|
||||
const tbody = document.getElementById('cleanup-saved-queries-body');
|
||||
if (!d.queries || d.queries.length === 0) {
|
||||
tbody.innerHTML = '<tr><td colspan="5" style="text-align:center;font-style:italic">No saved queries. Create one below.</td></tr>';
|
||||
return;
|
||||
}
|
||||
tbody.innerHTML = d.queries.map(q => {
|
||||
const filterLabel = q.follows_filter === 'all' ? 'All'
|
||||
: q.follows_filter === 'follows' ? 'Follows'
|
||||
: 'Non-follows';
|
||||
const kindsStr = q.kinds && q.kinds.length > 0 ? q.kinds.join(', ') : 'all';
|
||||
const dateStr = (q.from_date || q.to_date)
|
||||
? `${q.from_date || '…'} → ${q.to_date || '…'}`
|
||||
: 'no date bound';
|
||||
const limitStr = q.max_events > 0 ? q.max_events.toLocaleString() : '∞';
|
||||
const filters = `${filterLabel} | kinds: ${kindsStr} | ${dateStr} | max: ${limitStr}`;
|
||||
const previewInfo = q.last_preview_count > 0
|
||||
? `${q.last_preview_count.toLocaleString()} evts (${q.last_preview_size_human})`
|
||||
: '—';
|
||||
const executedInfo = q.last_executed_at || '—';
|
||||
return `<tr>
|
||||
<td><strong>${esc(q.name)}</strong></td>
|
||||
<td style="font-size:11px">${esc(filters)}</td>
|
||||
<td style="font-size:11px">${previewInfo}</td>
|
||||
<td style="font-size:11px">${esc(executedInfo)}</td>
|
||||
<td>
|
||||
<button onclick="runSavedCleanupPreview(${q.id})">Preview</button>
|
||||
<button onclick="runSavedCleanupExecute(${q.id})">Execute</button>
|
||||
<button onclick="loadSavedCleanupQuery(${q.id})">Edit</button>
|
||||
<button onclick="deleteCleanupQuery(${q.id})">Delete</button>
|
||||
</td>
|
||||
</tr>`;
|
||||
}).join('');
|
||||
} catch (e) { console.error('[admin2] loadCleanupQueries error:', e); }
|
||||
}
|
||||
|
||||
// ── New query (clear builder) ──────────────────────────────────────────
|
||||
function newCleanupQuery() {
|
||||
cleanupEditId = null;
|
||||
document.getElementById('cleanup-name').value = '';
|
||||
document.querySelectorAll('input[name="cleanup-follows"]').forEach(r => {
|
||||
r.checked = r.value === 'all';
|
||||
});
|
||||
document.getElementById('cleanup-kinds').value = '';
|
||||
document.getElementById('cleanup-from-date').value = '';
|
||||
document.getElementById('cleanup-from-time').value = '';
|
||||
document.getElementById('cleanup-to-date').value = '';
|
||||
document.getElementById('cleanup-to-time').value = '';
|
||||
document.getElementById('cleanup-max-events').value = '0';
|
||||
document.getElementById('cleanup-results-group').style.display = 'none';
|
||||
document.getElementById('cleanup-name').focus();
|
||||
}
|
||||
|
||||
// ── Combine date + time inputs into a single datetime string ───────────
|
||||
function combineDateTime(dateId, timeId) {
|
||||
const dateVal = document.getElementById(dateId).value;
|
||||
const timeVal = document.getElementById(timeId).value;
|
||||
if (!dateVal) return '';
|
||||
return timeVal ? dateVal + ' ' + timeVal : dateVal;
|
||||
}
|
||||
|
||||
// ── Read filter values from the form ───────────────────────────────────
|
||||
function readCleanupFilters() {
|
||||
const followsEl = document.querySelector('input[name="cleanup-follows"]:checked');
|
||||
const follows_filter = followsEl ? followsEl.value : 'all';
|
||||
const kindsRaw = document.getElementById('cleanup-kinds').value.trim();
|
||||
const kinds = kindsRaw ? kindsRaw.split(',').map(s => parseInt(s.trim(), 10)).filter(n => !isNaN(n) && n > 0) : [];
|
||||
const from_date = combineDateTime('cleanup-from-date', 'cleanup-from-time');
|
||||
const to_date = combineDateTime('cleanup-to-date', 'cleanup-to-time');
|
||||
const max_events = parseInt(document.getElementById('cleanup-max-events').value, 10) || 0;
|
||||
const name = document.getElementById('cleanup-name').value.trim();
|
||||
return { name, follows_filter, kinds, from_date, to_date, max_events };
|
||||
}
|
||||
|
||||
// ── Preview ────────────────────────────────────────────────────────────
|
||||
async function previewCleanup(queryId) {
|
||||
const filters = readCleanupFilters();
|
||||
const params = new URLSearchParams();
|
||||
params.set('follows_filter', filters.follows_filter);
|
||||
if (filters.kinds.length > 0) params.set('kinds', filters.kinds.join(','));
|
||||
if (filters.from_date) params.set('from_date', filters.from_date);
|
||||
if (filters.to_date) params.set('to_date', filters.to_date);
|
||||
if (filters.max_events > 0) params.set('max_events', String(filters.max_events));
|
||||
if (queryId) params.set('query_id', String(queryId));
|
||||
|
||||
try {
|
||||
const res = await fetch('api/cleanup.php?' + params.toString());
|
||||
const d = await res.json();
|
||||
if (d.error) { alert('Preview error: ' + d.error); return; }
|
||||
renderCleanupResults(d);
|
||||
// Refresh saved queries table so last_preview updates show
|
||||
if (queryId) loadCleanupQueries();
|
||||
} catch (e) { console.error('[admin2] previewCleanup error:', e); alert('Preview failed: ' + e.message); }
|
||||
}
|
||||
|
||||
// ── Render preview results ─────────────────────────────────────────────
|
||||
function renderCleanupResults(d) {
|
||||
const group = document.getElementById('cleanup-results-group');
|
||||
group.style.display = 'block';
|
||||
|
||||
// Summary
|
||||
const summary = document.getElementById('cleanup-results-summary');
|
||||
let html = `<strong>Match count:</strong> ${(d.match_count ?? 0).toLocaleString()} events`;
|
||||
if (d.total_size_human) {
|
||||
html += ` | <strong>Estimated size:</strong> ${d.total_size_human}`;
|
||||
}
|
||||
if (d.avg_size_per_event) {
|
||||
html += ` | <strong>Avg/event:</strong> ${d.avg_size_per_event} bytes`;
|
||||
}
|
||||
if (d.deleted_count !== undefined) {
|
||||
html += `<br><strong style="color:#c0392b">Deleted:</strong> ${d.deleted_count.toLocaleString()} events`;
|
||||
if (d.freed_human) html += ` | <strong>Freed:</strong> ${d.freed_human}`;
|
||||
if (d.duration_ms) html += ` | <strong>Duration:</strong> ${d.duration_ms}ms`;
|
||||
}
|
||||
summary.innerHTML = html;
|
||||
|
||||
// Kind breakdown table
|
||||
const bdEl = document.getElementById('cleanup-results-breakdown');
|
||||
if (d.kinds_breakdown && d.kinds_breakdown.length > 0) {
|
||||
let tbl = '<table class="config-table"><thead><tr><th>Kind</th><th>Count</th><th>Size</th><th>% of total</th></tr></thead><tbody>';
|
||||
const totalBytes = d.total_size_bytes || 1;
|
||||
d.kinds_breakdown.forEach(k => {
|
||||
const pct = totalBytes > 0 ? (k.size_bytes / totalBytes * 100).toFixed(1) : 0;
|
||||
tbl += `<tr><td>${k.kind}</td><td>${k.count.toLocaleString()}</td><td>${formatCleanupBytes(k.size_bytes)}</td><td>${pct}%</td></tr>`;
|
||||
});
|
||||
tbl += '</tbody></table>';
|
||||
bdEl.innerHTML = tbl;
|
||||
} else {
|
||||
bdEl.innerHTML = '<p style="font-style:italic;color:var(--text-muted,#888)">No kind breakdown available.</p>';
|
||||
}
|
||||
|
||||
// SQL preview
|
||||
const sqlEl = document.getElementById('cleanup-sql-preview');
|
||||
if (d.sql_preview) {
|
||||
sqlEl.textContent = d.sql_preview;
|
||||
} else {
|
||||
sqlEl.textContent = '(SQL preview not available for this response)';
|
||||
}
|
||||
}
|
||||
|
||||
// ── Format bytes (local helper) ────────────────────────────────────────
|
||||
function formatCleanupBytes(bytes) {
|
||||
if (bytes < 1024) return bytes + ' B';
|
||||
if (bytes < 1048576) return (bytes / 1024).toFixed(1) + ' KB';
|
||||
if (bytes < 1073741824) return (bytes / 1048576).toFixed(1) + ' MB';
|
||||
return (bytes / 1073741824).toFixed(2) + ' GB';
|
||||
}
|
||||
|
||||
// ── Save query ─────────────────────────────────────────────────────────
|
||||
async function saveCleanupQuery() {
|
||||
const filters = readCleanupFilters();
|
||||
if (!filters.name) { alert('Please enter a query name'); return; }
|
||||
|
||||
const body = {
|
||||
action: 'save',
|
||||
id: cleanupEditId,
|
||||
name: filters.name,
|
||||
follows_filter: filters.follows_filter,
|
||||
kinds: filters.kinds,
|
||||
from_date: filters.from_date,
|
||||
to_date: filters.to_date,
|
||||
max_events: filters.max_events,
|
||||
};
|
||||
|
||||
try {
|
||||
const res = await fetch('api/cleanup_queries.php', {
|
||||
method: 'POST',
|
||||
headers: {'Content-Type': 'application/json'},
|
||||
body: JSON.stringify(body)
|
||||
});
|
||||
const d = await res.json();
|
||||
if (d.error) { alert('Save failed: ' + d.error); return; }
|
||||
cleanupEditId = d.id;
|
||||
alert('Query saved!');
|
||||
loadCleanupQueries();
|
||||
} catch (e) { console.error('[admin2] saveCleanupQuery error:', e); alert('Save failed: ' + e.message); }
|
||||
}
|
||||
|
||||
// ── Execute delete (show confirmation first) ───────────────────────────
|
||||
let pendingExecuteFilters = null;
|
||||
|
||||
async function executeCleanup() {
|
||||
const filters = readCleanupFilters();
|
||||
pendingExecuteFilters = filters;
|
||||
|
||||
// Run a quick preview to show the user what will be deleted
|
||||
const params = new URLSearchParams();
|
||||
params.set('follows_filter', filters.follows_filter);
|
||||
if (filters.kinds.length > 0) params.set('kinds', filters.kinds.join(','));
|
||||
if (filters.from_date) params.set('from_date', filters.from_date);
|
||||
if (filters.to_date) params.set('to_date', filters.to_date);
|
||||
if (filters.max_events > 0) params.set('max_events', String(filters.max_events));
|
||||
|
||||
try {
|
||||
const res = await fetch('api/cleanup.php?' + params.toString());
|
||||
const d = await res.json();
|
||||
const name = filters.name || 'Ad-hoc query';
|
||||
const msg = `Query: ${esc(name)}\n`
|
||||
+ `Events to delete: ${(d.match_count ?? 0).toLocaleString()}\n`
|
||||
+ `Estimated space freed: ${d.total_size_human || 'unknown'}`;
|
||||
document.getElementById('cleanup-confirm-msg').textContent = msg;
|
||||
document.getElementById('cleanup-confirm-dialog').style.display = 'block';
|
||||
} catch (e) {
|
||||
// If preview fails, still allow delete with a basic confirmation
|
||||
document.getElementById('cleanup-confirm-msg').textContent = `Events matching current filters.`;
|
||||
document.getElementById('cleanup-confirm-dialog').style.display = 'block';
|
||||
}
|
||||
}
|
||||
|
||||
async function executeCleanupConfirmed() {
|
||||
document.getElementById('cleanup-confirm-dialog').style.display = 'none';
|
||||
if (!pendingExecuteFilters) return;
|
||||
|
||||
const filters = pendingExecuteFilters;
|
||||
pendingExecuteFilters = null;
|
||||
|
||||
const body = {
|
||||
follows_filter: filters.follows_filter,
|
||||
kinds: filters.kinds,
|
||||
from_date: filters.from_date,
|
||||
to_date: filters.to_date,
|
||||
max_events: filters.max_events,
|
||||
dry_run: false,
|
||||
};
|
||||
|
||||
try {
|
||||
const res = await fetch('api/cleanup.php', {
|
||||
method: 'POST',
|
||||
headers: {'Content-Type': 'application/json'},
|
||||
body: JSON.stringify(body)
|
||||
});
|
||||
const d = await res.json();
|
||||
if (d.error) { alert('Delete failed: ' + d.error); return; }
|
||||
renderCleanupResults(d);
|
||||
// Refresh saved queries in case last_preview_count changed
|
||||
loadCleanupQueries();
|
||||
} catch (e) { console.error('[admin2] executeCleanup error:', e); alert('Delete failed: ' + e.message); }
|
||||
}
|
||||
|
||||
// ── Delete saved query ─────────────────────────────────────────────────
|
||||
async function deleteCleanupQuery(id) {
|
||||
if (!confirm('Delete this saved query?')) return;
|
||||
try {
|
||||
const res = await fetch('api/cleanup_queries.php', {
|
||||
method: 'POST',
|
||||
headers: {'Content-Type': 'application/json'},
|
||||
body: JSON.stringify({action: 'delete', id})
|
||||
});
|
||||
const d = await res.json();
|
||||
if (d.error) { alert('Delete failed: ' + d.error); return; }
|
||||
loadCleanupQueries();
|
||||
} catch (e) { console.error('[admin2] deleteCleanupQuery error:', e); alert('Delete failed: ' + e.message); }
|
||||
}
|
||||
|
||||
// ── Load saved query into builder ──────────────────────────────────────
|
||||
async function loadSavedCleanupQuery(id) {
|
||||
try {
|
||||
const res = await fetch('api/cleanup_queries.php');
|
||||
const d = await res.json();
|
||||
if (!d.queries) return;
|
||||
const q = d.queries.find(q => q.id === id);
|
||||
if (!q) { alert('Query not found'); return; }
|
||||
|
||||
cleanupEditId = q.id;
|
||||
document.getElementById('cleanup-name').value = q.name;
|
||||
document.querySelectorAll('input[name="cleanup-follows"]').forEach(r => {
|
||||
r.checked = r.value === q.follows_filter;
|
||||
});
|
||||
document.getElementById('cleanup-kinds').value = (q.kinds || []).join(', ');
|
||||
// Split stored datetime into date + time parts
|
||||
const fromParts = (q.from_date || '').split(' ');
|
||||
document.getElementById('cleanup-from-date').value = fromParts[0] || '';
|
||||
document.getElementById('cleanup-from-time').value = fromParts[1] || '';
|
||||
const toParts = (q.to_date || '').split(' ');
|
||||
document.getElementById('cleanup-to-date').value = toParts[0] || '';
|
||||
document.getElementById('cleanup-to-time').value = toParts[1] || '';
|
||||
document.getElementById('cleanup-max-events').value = q.max_events;
|
||||
document.getElementById('cleanup-results-group').style.display = 'none';
|
||||
|
||||
// Scroll to builder
|
||||
document.getElementById('cleanup-builder-group').scrollIntoView({ behavior: 'smooth' });
|
||||
} catch (e) { console.error('[admin2] loadSavedCleanupQuery error:', e); }
|
||||
}
|
||||
|
||||
// ── Run preview for a saved query ──────────────────────────────────────
|
||||
async function runSavedCleanupPreview(id) {
|
||||
try {
|
||||
const res = await fetch('api/cleanup_queries.php');
|
||||
const d = await res.json();
|
||||
if (!d.queries) return;
|
||||
const q = d.queries.find(q => q.id === id);
|
||||
if (!q) { alert('Query not found'); return; }
|
||||
|
||||
// Load into builder first so the user can see the filters
|
||||
await loadSavedCleanupQuery(id);
|
||||
// Then run preview with query_id so last_preview_count/size get saved
|
||||
await previewCleanup(id);
|
||||
} catch (e) { console.error('[admin2] runSavedCleanupPreview error:', e); }
|
||||
}
|
||||
|
||||
// ── Run execute for a saved query ──────────────────────────────────────
|
||||
async function runSavedCleanupExecute(id) {
|
||||
try {
|
||||
const res = await fetch('api/cleanup_queries.php');
|
||||
const d = await res.json();
|
||||
if (!d.queries) return;
|
||||
const q = d.queries.find(q => q.id === id);
|
||||
if (!q) { alert('Query not found'); return; }
|
||||
|
||||
// Load into builder
|
||||
await loadSavedCleanupQuery(id);
|
||||
|
||||
// Confirm and execute via the saved query execute action
|
||||
const filters = readCleanupFilters();
|
||||
const name = q.name || 'Saved query';
|
||||
const msg = `Query: ${name}\n`
|
||||
+ `Follows: ${q.follows_filter}\n`
|
||||
+ `Kinds: ${(q.kinds || []).join(', ') || 'all'}\n`
|
||||
+ `From: ${q.from_date || 'no bound'}\n`
|
||||
+ `To: ${q.to_date || 'no bound'}\n`
|
||||
+ `Max events: ${q.max_events > 0 ? q.max_events.toLocaleString() : 'no limit'}`;
|
||||
document.getElementById('cleanup-confirm-msg').textContent = msg;
|
||||
document.getElementById('cleanup-confirm-btn').onclick = async () => {
|
||||
document.getElementById('cleanup-confirm-dialog').style.display = 'none';
|
||||
try {
|
||||
const execRes = await fetch('api/cleanup_queries.php', {
|
||||
method: 'POST',
|
||||
headers: {'Content-Type': 'application/json'},
|
||||
body: JSON.stringify({action: 'execute', id})
|
||||
});
|
||||
const execD = await execRes.json();
|
||||
if (execD.error) { alert('Delete failed: ' + execD.error); return; }
|
||||
renderCleanupResults(execD);
|
||||
loadCleanupQueries();
|
||||
} catch (e) { console.error('[admin2] runSavedCleanupExecute error:', e); alert('Delete failed: ' + e.message); }
|
||||
};
|
||||
document.getElementById('cleanup-confirm-dialog').style.display = 'block';
|
||||
} catch (e) { console.error('[admin2] runSavedCleanupExecute error:', e); }
|
||||
}
|
||||
|
||||
// ================================
|
||||
// DARK MODE
|
||||
// ================================
|
||||
|
||||
@@ -281,6 +281,94 @@ body {
|
||||
box-shadow: 0 10px 30px rgba(0, 0, 0, 0.3);
|
||||
}
|
||||
|
||||
/* Cleanup Date/Time Inputs */
|
||||
.datetime-group {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 6px;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
.cleanup-date-input {
|
||||
font-family: var(--font-family);
|
||||
font-size: 13px;
|
||||
padding: 4px 6px;
|
||||
border: var(--border-width) solid var(--border-color);
|
||||
border-radius: var(--border-radius);
|
||||
background: var(--secondary-color);
|
||||
color: var(--primary-color);
|
||||
width: 160px;
|
||||
}
|
||||
.cleanup-time-input {
|
||||
font-family: var(--font-family);
|
||||
font-size: 13px;
|
||||
padding: 4px 6px;
|
||||
border: var(--border-width) solid var(--border-color);
|
||||
border-radius: var(--border-radius);
|
||||
background: var(--secondary-color);
|
||||
color: var(--primary-color);
|
||||
width: 110px;
|
||||
}
|
||||
.datetime-hint {
|
||||
font-size: 11px;
|
||||
color: var(--muted-color);
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
/* Cleanup Confirmation Modal */
|
||||
.modal-overlay {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background-color: rgba(0, 0, 0, 0.7);
|
||||
z-index: 1001;
|
||||
}
|
||||
|
||||
.modal-content {
|
||||
background-color: var(--secondary-color);
|
||||
border: var(--border-width) solid var(--border-color);
|
||||
border-radius: var(--border-radius);
|
||||
}
|
||||
|
||||
/* Cleanup results summary */
|
||||
.info-box {
|
||||
padding: 8px 12px;
|
||||
background: var(--bg-code, #f5f5f5);
|
||||
border: var(--border-width) solid var(--border-color);
|
||||
border-radius: var(--border-radius);
|
||||
font-size: 13px;
|
||||
line-height: 1.6;
|
||||
}
|
||||
|
||||
/* Cleanup radio group */
|
||||
.radio-group {
|
||||
display: flex;
|
||||
gap: 16px;
|
||||
flex-wrap: wrap;
|
||||
margin-top: 4px;
|
||||
}
|
||||
|
||||
.radio-group label {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 4px;
|
||||
cursor: pointer;
|
||||
font-size: 13px;
|
||||
}
|
||||
|
||||
/* Cleanup form group */
|
||||
.form-group {
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
.form-group > label {
|
||||
display: block;
|
||||
font-size: 12px;
|
||||
font-weight: bold;
|
||||
margin-bottom: 3px;
|
||||
}
|
||||
|
||||
h1 {
|
||||
border-bottom: var(--border-width) solid var(--border-color);
|
||||
padding-bottom: 10px;
|
||||
@@ -1602,6 +1690,12 @@ bdi {
|
||||
.follows-row:hover {
|
||||
background: var(--hover-bg, rgba(255,255,255,0.05));
|
||||
}
|
||||
.follows-row-active {
|
||||
border-left: 3px solid red;
|
||||
}
|
||||
.follows-row-active:hover {
|
||||
border-left: 3px solid red;
|
||||
}
|
||||
.follows-detail td {
|
||||
padding: 8px 12px;
|
||||
background: var(--bg-color);
|
||||
@@ -1677,3 +1771,118 @@ bdi {
|
||||
.refresh-user-btn:active {
|
||||
opacity: 0.7;
|
||||
}
|
||||
|
||||
/* Upstream relay status window — monochrome per WEB.md rules */
|
||||
.relay-status-summary {
|
||||
font-weight: bold;
|
||||
margin-bottom: 8px;
|
||||
font-size: 13px;
|
||||
}
|
||||
.relay-status-list {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 2px;
|
||||
max-height: 300px;
|
||||
overflow-y: auto;
|
||||
border: 1px solid var(--border-color);
|
||||
border-radius: var(--border-radius);
|
||||
padding: 4px;
|
||||
}
|
||||
.relay-status-row {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
padding: 3px 6px;
|
||||
border-radius: var(--border-radius);
|
||||
font-size: 12px;
|
||||
font-family: var(--font-family);
|
||||
border: 1px solid transparent;
|
||||
}
|
||||
.relay-status-url {
|
||||
flex: 1;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
margin-right: 8px;
|
||||
}
|
||||
.relay-status-badge {
|
||||
flex-shrink: 0;
|
||||
font-size: 10px;
|
||||
padding: 1px 5px;
|
||||
border: 1px solid var(--border-color);
|
||||
border-radius: var(--border-radius);
|
||||
white-space: nowrap;
|
||||
}
|
||||
/* Connected: primary color, no fill */
|
||||
.relay-status-ok {
|
||||
color: var(--primary-color);
|
||||
}
|
||||
.relay-status-ok .relay-status-badge {
|
||||
border-color: var(--primary-color);
|
||||
}
|
||||
/* Connecting: muted, no fill */
|
||||
.relay-status-connecting {
|
||||
color: var(--muted-color);
|
||||
}
|
||||
.relay-status-connecting .relay-status-badge {
|
||||
border-color: var(--muted-color);
|
||||
}
|
||||
/* Disconnected: muted, no fill */
|
||||
.relay-status-disconnected {
|
||||
color: var(--muted-color);
|
||||
}
|
||||
.relay-status-disconnected .relay-status-badge {
|
||||
border-color: var(--muted-color);
|
||||
}
|
||||
/* Error: accent (red), no fill */
|
||||
.relay-status-error {
|
||||
color: var(--accent-color);
|
||||
}
|
||||
.relay-status-error .relay-status-badge {
|
||||
border-color: var(--accent-color);
|
||||
}
|
||||
/* Unknown: muted, no fill */
|
||||
.relay-status-unknown {
|
||||
color: var(--muted-color);
|
||||
}
|
||||
.relay-status-unknown .relay-status-badge {
|
||||
border-color: var(--muted-color);
|
||||
}
|
||||
|
||||
/* Pagination bar — monochrome per WEB.md rules */
|
||||
.pagination-bar {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
padding: 6px 0;
|
||||
font-size: 12px;
|
||||
color: var(--primary-color);
|
||||
}
|
||||
.pagination-info {
|
||||
font-style: italic;
|
||||
color: var(--muted-color);
|
||||
}
|
||||
.pagination-buttons {
|
||||
display: flex;
|
||||
gap: 6px;
|
||||
}
|
||||
.pagination-buttons button {
|
||||
font-size: 12px;
|
||||
padding: 4px 12px;
|
||||
cursor: pointer;
|
||||
background: var(--secondary-color);
|
||||
color: var(--primary-color);
|
||||
border: 1px solid var(--primary-color);
|
||||
border-radius: var(--border-radius);
|
||||
font-family: var(--font-family);
|
||||
transition: border-color 0.2s, color 0.2s;
|
||||
}
|
||||
.pagination-buttons button:hover {
|
||||
border-color: var(--accent-color);
|
||||
color: var(--accent-color);
|
||||
}
|
||||
.pagination-buttons button:active {
|
||||
background: var(--accent-color);
|
||||
color: var(--secondary-color);
|
||||
border-color: var(--accent-color);
|
||||
}
|
||||
|
||||
Vendored
+11
-11
@@ -1,15 +1,15 @@
|
||||
New Events — Last 24 Hours
|
||||
|
||||
11 | X
|
||||
10 | XX
|
||||
9 | XX
|
||||
8 | XX
|
||||
7 | XX X X
|
||||
6 | XX X X
|
||||
5 | XX X X
|
||||
4 | X XX X XX
|
||||
3 | X XXX X XX
|
||||
2 | X X X XXX X XX
|
||||
1 | X XX X X X X X X X X X X X X XX X X XXXX X X X X X XX
|
||||
21 |
|
||||
19 |
|
||||
17 |
|
||||
15 |
|
||||
13 |
|
||||
11 | X
|
||||
9 | X
|
||||
7 | X
|
||||
5 | X
|
||||
3 | X X X
|
||||
1 | X X X X X XX X X XX X X X X X X X X XX X X X XX X X
|
||||
+--------------------------------------------------------------------------------
|
||||
0s 1h 3h 4h 6h 7h 9h 10h 12h 13h 15h 16h 18h 19h 21h 22h
|
||||
|
||||
Vendored
+1
@@ -0,0 +1 @@
|
||||
[{"kind":1,"count":501,"pct":56.8},{"kind":7,"count":200,"pct":22.7},{"kind":9734,"count":110,"pct":12.5},{"kind":6,"count":30,"pct":3.4},{"kind":9735,"count":20,"pct":2.3},{"kind":3,"count":11,"pct":1.2},{"kind":0,"count":10,"pct":1.1}]
|
||||
Vendored
+1
@@ -0,0 +1 @@
|
||||
[{"pubkey":"4f355bdcb7cc0af728ef3cceb9615d90684bb5b2ca5f859ab0f0b704075871aa","name":"","count":182,"pct":20.6},{"pubkey":"eff555c8453f665bb54f907188aefba0e85c29aa9f5c30fa13d78d003c71265c","name":"Random User 4","count":70,"pct":7.9},{"pubkey":"9a90e4db8996e235a5bf1501013149d5f250b60e79336b69035f0b4dab8a4302","name":"Random User 9","count":70,"pct":7.9},{"pubkey":"b80c8c5fb175c50fe97d3a63658fa8b5dcc3e20da22dff8cef54317f6fe25394","name":"Random User 7","count":70,"pct":7.9},{"pubkey":"3d68fc5c3ddf8feef6cb6345817e4c6e421b5d292bef0be8d9a4809a23a4f0f5","name":"Random User 1","count":70,"pct":7.9},{"pubkey":"1c38f0e5446b8f5d7bc074f9f4b7afe85980706e765a5b1a3e4a52504e521ec1","name":"Random User 6","count":70,"pct":7.9},{"pubkey":"084857a219f6d73ec30fb90376e6f30161b07cd5d2130dffe47d32f229610b8a","name":"Random User 5","count":70,"pct":7.9},{"pubkey":"71691b130642de5af2b7f0a5ecf4eb374c46d913dbc72bc802005b24f9e87e11","name":"Random User 8","count":70,"pct":7.9},{"pubkey":"8d8b59e842e1529e0c448f05e570eccca82d9ca4500b758c9d44f478e96e8cdf","name":"Random User 10","count":70,"pct":7.9},{"pubkey":"f4bd9e04029c11440d545ffa66aeac45b87becf4075e2f321b0f5e8c30f187c2","name":"Random User 2","count":70,"pct":7.9},{"pubkey":"f2c0cadeee26653d9d2acd3788f6cc26d19b680d439640501eb1545afb94dd56","name":"Random User 3","count":70,"pct":7.9}]
|
||||
+106
@@ -56,6 +56,7 @@ $display_name = $relay_version ? ($relay_name . ' ' . $relay_version) : $relay_n
|
||||
<li><button class="nav-item" data-page="relay-events">Relay Events</button></li>
|
||||
<li><button class="nav-item" data-page="caching">Caching</button></li>
|
||||
<li><button class="nav-item" data-page="dm">DM</button></li>
|
||||
<li><button class="nav-item" data-page="cleanup">Cleanup</button></li>
|
||||
<li><button class="nav-item" data-page="database">Database Query</button></li>
|
||||
</ul>
|
||||
<div class="nav-footer">
|
||||
@@ -383,9 +384,16 @@ $display_name = $relay_version ? ($relay_name . ' ' . $relay_version) : $relay_n
|
||||
<p>Loading...</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="input-group">
|
||||
<h3>Upstream Relay Status <span style="font-size:11px;font-weight:normal;color:var(--text-muted,#888)">(live connection state, updated every 15s)</span></h3>
|
||||
<div id="caching-relay-status" class="status-display">
|
||||
<p>Loading...</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="input-group">
|
||||
<h3>Followed Pubkeys <span style="font-size:11px;font-weight:normal;color:var(--text-muted,#888)">(click a row for per-relay details)</span></h3>
|
||||
<div id="caching-follows-status" class="status-message"></div>
|
||||
<div id="caching-follows-pagination" class="pagination-bar"></div>
|
||||
<div class="config-table-container">
|
||||
<table class="config-table" id="caching-follows-table">
|
||||
<thead><tr><th>Name</th><th>npub</th><th>Root?</th><th>Events in DB</th><th>Backfill</th><th>Relays</th></tr></thead>
|
||||
@@ -400,6 +408,104 @@ $display_name = $relay_version ? ($relay_name . ' ' . $relay_version) : $relay_n
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- EVENT CLEANUP Section -->
|
||||
<div class="section" id="cleanupSection" style="display: none;">
|
||||
<div class="section-header"><h2>EVENT CLEANUP</h2></div>
|
||||
|
||||
<!-- Saved Queries Table -->
|
||||
<div class="input-group" id="saved-queries-group">
|
||||
<label>Saved Queries</label>
|
||||
<div class="config-table-container">
|
||||
<table class="config-table" id="cleanup-saved-queries-table">
|
||||
<thead><tr><th>Name</th><th>Filters</th><th>Last Preview</th><th>Last Executed</th><th>Actions</th></tr></thead>
|
||||
<tbody id="cleanup-saved-queries-body">
|
||||
<tr><td colspan="5" style="text-align: center; font-style: italic;">Loading...</td></tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<div class="inline-buttons" style="margin-top:8px">
|
||||
<button type="button" onclick="newCleanupQuery()">New Query</button>
|
||||
<button type="button" onclick="loadCleanupQueries()">Refresh</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Query Builder -->
|
||||
<div class="input-group" id="cleanup-builder-group">
|
||||
<label>Query Builder</label>
|
||||
<div class="form-group">
|
||||
<label for="cleanup-name">Query Name:</label>
|
||||
<input type="text" id="cleanup-name" placeholder="My Cleanup Query" style="width:100%;max-width:400px">
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label>Follows Filter:</label>
|
||||
<div class="radio-group">
|
||||
<label><input type="radio" name="cleanup-follows" value="all" checked> All</label>
|
||||
<label><input type="radio" name="cleanup-follows" value="follows"> Follows only</label>
|
||||
<label><input type="radio" name="cleanup-follows" value="non_follows"> Non-follows only</label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="cleanup-kinds">Event Kinds (comma-separated, empty = all):</label>
|
||||
<input type="text" id="cleanup-kinds" placeholder="e.g. 1, 7, 9734" style="width:100%;max-width:400px">
|
||||
<div style="font-size:11px;color:var(--text-muted,#888);margin-top:2px">
|
||||
Common kinds: 0 (profiles), 1 (text), 3 (contacts), 4 (DM), 5 (delete),
|
||||
6 (repost), 7 (reaction), 9734 (zap request), 9735 (zap receipt), 10002 (relay list)
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label>From (delete events after this):</label>
|
||||
<div class="datetime-group">
|
||||
<input type="date" id="cleanup-from-date" class="cleanup-date-input">
|
||||
<input type="time" id="cleanup-from-time" class="cleanup-time-input">
|
||||
<span class="datetime-hint">leave empty for no bound</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label>To (delete events before this):</label>
|
||||
<div class="datetime-group">
|
||||
<input type="date" id="cleanup-to-date" class="cleanup-date-input">
|
||||
<input type="time" id="cleanup-to-time" class="cleanup-time-input">
|
||||
<span class="datetime-hint">leave empty for no bound</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="cleanup-max-events">Max Events (0 = no limit):</label>
|
||||
<input type="number" id="cleanup-max-events" value="0" min="0" style="width:120px">
|
||||
</div>
|
||||
<div class="inline-buttons" style="margin-top:8px">
|
||||
<button type="button" onclick="previewCleanup()">Preview</button>
|
||||
<button type="button" onclick="saveCleanupQuery()">Save Query</button>
|
||||
<button type="button" onclick="executeCleanup()" style="background:#c0392b;color:#fff">Execute Delete</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Results Area -->
|
||||
<div class="input-group" id="cleanup-results-group" style="display:none;">
|
||||
<label>Results</label>
|
||||
<div id="cleanup-results-summary" class="info-box"></div>
|
||||
<div id="cleanup-results-breakdown" class="config-table-container" style="margin-top:8px"></div>
|
||||
<div id="cleanup-results-sql" style="margin-top:8px">
|
||||
<details>
|
||||
<summary style="cursor:pointer;font-size:12px;color:var(--text-muted,#888)">SQL Preview</summary>
|
||||
<pre id="cleanup-sql-preview" style="background:var(--bg-code,#f5f5f5);padding:8px;border-radius:4px;overflow-x:auto;font-size:11px;margin-top:4px;white-space:pre-wrap"></pre>
|
||||
</details>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Confirmation Dialog -->
|
||||
<div id="cleanup-confirm-dialog" class="modal-overlay" style="display:none;">
|
||||
<div class="modal-content" style="background:var(--bg-card,#fff);border:1px solid var(--border,#ccc);border-radius:8px;padding:20px;max-width:480px;margin:10% auto;box-shadow:0 4px 20px rgba(0,0,0,0.3)">
|
||||
<h3 style="margin-top:0">Confirm Delete</h3>
|
||||
<p id="cleanup-confirm-msg">Are you sure you want to delete these events?</p>
|
||||
<p style="color:#c0392b;font-weight:bold">This action cannot be undone.</p>
|
||||
<div class="inline-buttons" style="margin-top:12px">
|
||||
<button type="button" id="cleanup-confirm-btn" onclick="executeCleanupConfirmed()" style="background:#c0392b;color:#fff">Delete</button>
|
||||
<button type="button" onclick="document.getElementById('cleanup-confirm-dialog').style.display='none'">Cancel</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- SQL QUERY Section -->
|
||||
<div class="section" id="sqlQuerySection" style="display: none;">
|
||||
<div class="section-header"><h2>SQL QUERY CONSOLE</h2></div>
|
||||
|
||||
+4010
-8754
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,180 @@
|
||||
<?php
|
||||
/**
|
||||
* admin/public/index.php — Public relay stats page.
|
||||
*
|
||||
* Served at https://<domain>/relay/stats/ (no authentication required).
|
||||
*
|
||||
* Shows the relay name/description/pubkey (read-only, from the config table)
|
||||
* and the server-rendered ASCII event-rate chart. The chart is fetched from
|
||||
* the public endpoint at /relay/api/chart.php?range=...
|
||||
*
|
||||
* This page exposes ONLY read-only, non-sensitive information:
|
||||
* - relay_name, relay_description, relay_pubkey, relay_version (from config)
|
||||
* - the event-rate chart (aggregate COUNT query, no user data)
|
||||
*
|
||||
* All sensitive admin endpoints (config edits, auth rules, IP bans, DMs,
|
||||
* raw SQL queries) remain behind Basic Auth at /relay/admin/.
|
||||
*/
|
||||
require_once __DIR__ . '/../lib/helpers.php';
|
||||
$pdo = db();
|
||||
|
||||
// Fetch relay info for the header (from config table).
|
||||
$relay_name = '';
|
||||
$relay_desc = '';
|
||||
$relay_pubkey = '';
|
||||
$relay_version = '';
|
||||
try {
|
||||
$relay_name = $pdo->query("SELECT value FROM config WHERE key = 'relay_name'")->fetchColumn() ?: 'C-Relay-PG';
|
||||
$relay_desc = $pdo->query("SELECT value FROM config WHERE key = 'relay_description'")->fetchColumn() ?: '';
|
||||
$relay_pubkey = $pdo->query("SELECT value FROM config WHERE key = 'relay_pubkey'")->fetchColumn() ?: '';
|
||||
$relay_version = $pdo->query("SELECT value FROM config WHERE key = 'relay_version'")->fetchColumn() ?: '';
|
||||
} catch (PDOException $e) {}
|
||||
|
||||
// Convert relay pubkey (hex) to npub and format into 3 lines of 3 groups of 7 chars.
|
||||
$relay_npub = $relay_pubkey;
|
||||
if ($relay_pubkey && preg_match('/^[0-9a-fA-F]{64}$/', $relay_pubkey)) {
|
||||
$relay_npub = hex_to_npub($relay_pubkey);
|
||||
}
|
||||
$formatted_npub = $relay_npub;
|
||||
if (strlen($relay_npub) === 63) {
|
||||
$line1 = substr($relay_npub, 0, 7) . ' ' . substr($relay_npub, 7, 7) . ' ' . substr($relay_npub, 14, 7);
|
||||
$line2 = substr($relay_npub, 21, 7) . ' ' . substr($relay_npub, 28, 7) . ' ' . substr($relay_npub, 35, 7);
|
||||
$line3 = substr($relay_npub, 42, 7) . ' ' . substr($relay_npub, 49, 7) . ' ' . substr($relay_npub, 56, 7);
|
||||
$formatted_npub = $line1 . "\n" . $line2 . "\n" . $line3;
|
||||
}
|
||||
$display_name = $relay_version ? ($relay_name . ' ' . $relay_version) : $relay_name;
|
||||
?>
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title><?= e($display_name) ?></title>
|
||||
<link rel="stylesheet" href="/relay/assets/index.css">
|
||||
<style>
|
||||
/* Public page uses the admin theme but hides the nav and centers content. */
|
||||
.side-nav, .side-nav-overlay { display: none !important; }
|
||||
.public-wrap { max-width: 1100px; margin: 0 auto; padding: 20px; }
|
||||
.public-chart-box {
|
||||
background: var(--secondary-color);
|
||||
border: var(--border-width) solid var(--border-color);
|
||||
border-radius: var(--border-radius);
|
||||
padding: 12px;
|
||||
margin-top: 16px;
|
||||
}
|
||||
.public-footer {
|
||||
margin-top: 24px;
|
||||
padding-top: 12px;
|
||||
border-top: var(--border-width) solid var(--border-color);
|
||||
font-size: 12px;
|
||||
color: var(--muted-color);
|
||||
text-align: center;
|
||||
}
|
||||
.public-footer a { color: var(--accent-color); text-decoration: none; }
|
||||
.event-rate-chart-container {
|
||||
white-space: pre;
|
||||
font-family: var(--font-family);
|
||||
font-size: 12px;
|
||||
line-height: 1.2;
|
||||
overflow-x: auto;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<!-- Header with title and relay info (read-only) -->
|
||||
<div class="section">
|
||||
<div class="header-content">
|
||||
<div class="header-title">
|
||||
<span class="relay-letter" data-letter="R">R</span>
|
||||
<span class="relay-letter" data-letter="E">E</span>
|
||||
<span class="relay-letter" data-letter="L">L</span>
|
||||
<span class="relay-letter" data-letter="A">A</span>
|
||||
<span class="relay-letter" data-letter="Y">Y</span>
|
||||
</div>
|
||||
<div class="relay-info">
|
||||
<div id="relay-name" class="relay-name"><?= e($display_name) ?></div>
|
||||
<div id="relay-description" class="relay-description"><?= e($relay_desc) ?></div>
|
||||
<div id="relay-pubkey-container" class="relay-pubkey-container" title="Click to copy npub">
|
||||
<div id="relay-pubkey" class="relay-pubkey"><?= e($formatted_npub) ?></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="public-wrap">
|
||||
<div class="section-header">EVENT RATE</div>
|
||||
|
||||
<!-- Range selector tabs -->
|
||||
<div class="chart-range-tabs">
|
||||
<button class="chart-tab active" data-range="hour">1H</button>
|
||||
<button class="chart-tab" data-range="day">1D</button>
|
||||
<button class="chart-tab" data-range="month">1M</button>
|
||||
<button class="chart-tab" data-range="year">1Y</button>
|
||||
</div>
|
||||
|
||||
<!-- Server-rendered ASCII chart (fetched from the public chart endpoint) -->
|
||||
<div class="public-chart-box">
|
||||
<div id="event-rate-chart" class="event-rate-chart-container">Loading chart...</div>
|
||||
</div>
|
||||
|
||||
<div class="public-footer">
|
||||
Public relay statistics ·
|
||||
<a href="wss://<?= e($_SERVER['HTTP_HOST'] ?? '') ?>">wss://<?= e($_SERVER['HTTP_HOST'] ?? '') ?></a>
|
||||
· Admin? visit <a href="/relay/admin/">/relay/admin/</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
// Minimal chart loader — fetches the public ASCII chart endpoint and
|
||||
// injects the plain-text response into the chart container. No auth.
|
||||
const chartEl = document.getElementById('event-rate-chart');
|
||||
let currentRange = 'hour';
|
||||
let chartTimer = null;
|
||||
|
||||
async function loadChart(range) {
|
||||
currentRange = range;
|
||||
if (!chartEl) return;
|
||||
chartEl.textContent = 'Loading chart...';
|
||||
try {
|
||||
const res = await fetch('/relay/api/chart.php?range=' + encodeURIComponent(range));
|
||||
if (!res.ok) { chartEl.textContent = 'Chart load failed (HTTP ' + res.status + ')'; return; }
|
||||
const text = await res.text();
|
||||
chartEl.textContent = text || '(no data)';
|
||||
} catch (e) {
|
||||
chartEl.textContent = 'Chart load failed: ' + e.message;
|
||||
}
|
||||
}
|
||||
|
||||
document.querySelectorAll('.chart-tab').forEach(btn => {
|
||||
btn.addEventListener('click', () => {
|
||||
document.querySelectorAll('.chart-tab').forEach(b => b.classList.remove('active'));
|
||||
btn.classList.add('active');
|
||||
const range = btn.getAttribute('data-range');
|
||||
loadChart(range);
|
||||
// Hour chart is live — auto-refresh every 30s. Others are cached server-side.
|
||||
if (chartTimer) { clearInterval(chartTimer); chartTimer = null; }
|
||||
if (range === 'hour') {
|
||||
chartTimer = setInterval(() => loadChart(currentRange), 30000);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
// Initial load + live refresh for the default (hour) range.
|
||||
loadChart('hour');
|
||||
chartTimer = setInterval(() => loadChart(currentRange), 30000);
|
||||
|
||||
// Click-to-copy the relay npub.
|
||||
const pkContainer = document.getElementById('relay-pubkey-container');
|
||||
if (pkContainer) {
|
||||
pkContainer.style.cursor = 'pointer';
|
||||
pkContainer.addEventListener('click', () => {
|
||||
const txt = (document.getElementById('relay-pubkey').textContent || '').replace(/\s+/g, '');
|
||||
if (txt && navigator.clipboard) navigator.clipboard.writeText(txt);
|
||||
});
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
+16
-78
@@ -2,6 +2,7 @@
|
||||
|
||||
# Build fully static MUSL binaries for C-Relay-PG using Alpine Docker
|
||||
# Produces truly portable binaries with zero runtime dependencies
|
||||
# PostgreSQL backend only.
|
||||
|
||||
set -e
|
||||
|
||||
@@ -11,7 +12,6 @@ DOCKERFILE="$SCRIPT_DIR/Dockerfile.alpine-musl"
|
||||
|
||||
# Parse command line arguments
|
||||
DEBUG_BUILD=false
|
||||
DB_BACKEND="${DB_BACKEND:-postgres}"
|
||||
|
||||
while [[ $# -gt 0 ]]; do
|
||||
case "$1" in
|
||||
@@ -19,31 +19,14 @@ while [[ $# -gt 0 ]]; do
|
||||
DEBUG_BUILD=true
|
||||
shift
|
||||
;;
|
||||
--db-backend)
|
||||
if [[ -z "$2" ]]; then
|
||||
echo "ERROR: --db-backend requires a value (sqlite|postgres)"
|
||||
exit 1
|
||||
fi
|
||||
DB_BACKEND="$2"
|
||||
shift 2
|
||||
;;
|
||||
--db-backend=*)
|
||||
DB_BACKEND="${1#*=}"
|
||||
shift
|
||||
;;
|
||||
*)
|
||||
echo "ERROR: Unknown argument: $1"
|
||||
echo "Usage: $0 [--debug] [--db-backend postgres|sqlite]"
|
||||
echo "Usage: $0 [--debug]"
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
if [[ "$DB_BACKEND" != "sqlite" && "$DB_BACKEND" != "postgres" ]]; then
|
||||
echo "ERROR: Invalid DB backend '$DB_BACKEND'. Use sqlite or postgres."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [[ "$DEBUG_BUILD" == "true" ]]; then
|
||||
echo "=========================================="
|
||||
echo "C-Relay-PG MUSL Static Binary Builder (DEBUG MODE)"
|
||||
@@ -56,7 +39,7 @@ fi
|
||||
echo "Project directory: $SCRIPT_DIR"
|
||||
echo "Build directory: $BUILD_DIR"
|
||||
echo "Debug build: $DEBUG_BUILD"
|
||||
echo "DB backend: $DB_BACKEND"
|
||||
echo "DB backend: postgres"
|
||||
echo ""
|
||||
|
||||
# Create build directory
|
||||
@@ -155,7 +138,6 @@ echo ""
|
||||
$DOCKER_CMD build \
|
||||
--platform "$PLATFORM" \
|
||||
--build-arg DEBUG_BUILD=$DEBUG_BUILD \
|
||||
--build-arg DB_BACKEND=$DB_BACKEND \
|
||||
-f "$DOCKERFILE" \
|
||||
-t c-relay-pg-musl-builder:latest \
|
||||
--progress=plain \
|
||||
@@ -179,7 +161,6 @@ echo "=========================================="
|
||||
$DOCKER_CMD build \
|
||||
--platform "$PLATFORM" \
|
||||
--build-arg DEBUG_BUILD=$DEBUG_BUILD \
|
||||
--build-arg DB_BACKEND=$DB_BACKEND \
|
||||
--target builder \
|
||||
-f "$DOCKERFILE" \
|
||||
-t c-relay-pg-static-builder-stage:latest \
|
||||
@@ -198,74 +179,31 @@ $DOCKER_CMD cp "$CONTAINER_ID:/build/c_relay_pg_static" "$BUILD_DIR/$OUTPUT_NAME
|
||||
# Clean up container
|
||||
$DOCKER_CMD rm "$CONTAINER_ID" > /dev/null
|
||||
|
||||
echo "✓ Binary extracted to: $BUILD_DIR/$OUTPUT_NAME"
|
||||
echo "✓ Binary extracted: $BUILD_DIR/$OUTPUT_NAME"
|
||||
echo ""
|
||||
|
||||
# Make binary executable
|
||||
chmod +x "$BUILD_DIR/$OUTPUT_NAME"
|
||||
|
||||
# Verify the binary
|
||||
echo "=========================================="
|
||||
echo "Step 3: Verifying static binary"
|
||||
echo "=========================================="
|
||||
echo ""
|
||||
file "$BUILD_DIR/$OUTPUT_NAME"
|
||||
ls -lh "$BUILD_DIR/$OUTPUT_NAME"
|
||||
|
||||
echo "Checking for dynamic dependencies:"
|
||||
if LDD_OUTPUT=$(timeout 5 ldd "$BUILD_DIR/$OUTPUT_NAME" 2>&1); then
|
||||
if echo "$LDD_OUTPUT" | grep -q "not a dynamic executable"; then
|
||||
echo "✓ Binary is fully static (no dynamic dependencies)"
|
||||
TRULY_STATIC=true
|
||||
elif echo "$LDD_OUTPUT" | grep -q "statically linked"; then
|
||||
echo "✓ Binary is statically linked"
|
||||
TRULY_STATIC=true
|
||||
else
|
||||
echo "⚠ WARNING: Binary may have dynamic dependencies:"
|
||||
echo "$LDD_OUTPUT"
|
||||
TRULY_STATIC=false
|
||||
fi
|
||||
# Check for dynamic dependencies
|
||||
if ldd "$BUILD_DIR/$OUTPUT_NAME" 2>&1 | grep -q "not a dynamic executable"; then
|
||||
echo "✓ Binary is truly static (no dynamic dependencies)"
|
||||
else
|
||||
# ldd failed or timed out - check with file command instead
|
||||
if file "$BUILD_DIR/$OUTPUT_NAME" | grep -q "statically linked"; then
|
||||
echo "✓ Binary is statically linked (verified with file command)"
|
||||
TRULY_STATIC=true
|
||||
else
|
||||
echo "⚠ Could not verify static linking (ldd check failed)"
|
||||
TRULY_STATIC=false
|
||||
fi
|
||||
echo "⚠ Binary has dynamic dependencies:"
|
||||
ldd "$BUILD_DIR/$OUTPUT_NAME" 2>&1
|
||||
fi
|
||||
echo ""
|
||||
|
||||
echo "File size: $(ls -lh "$BUILD_DIR/$OUTPUT_NAME" | awk '{print $5}')"
|
||||
echo ""
|
||||
|
||||
# Test if binary runs
|
||||
echo "Testing binary execution:"
|
||||
if "$BUILD_DIR/$OUTPUT_NAME" --version 2>&1 | head -5; then
|
||||
echo "✓ Binary executes successfully"
|
||||
else
|
||||
echo "⚠ Binary execution test failed (this may be normal if --version is not supported)"
|
||||
fi
|
||||
echo ""
|
||||
|
||||
# Summary
|
||||
echo "=========================================="
|
||||
echo "Build Summary"
|
||||
echo "Build complete!"
|
||||
echo "=========================================="
|
||||
echo "Binary: $BUILD_DIR/$OUTPUT_NAME"
|
||||
echo "Size: $(du -h "$BUILD_DIR/$OUTPUT_NAME" | cut -f1)"
|
||||
echo "Platform: $PLATFORM"
|
||||
if [ "$DEBUG_BUILD" = true ]; then
|
||||
echo "Build Type: DEBUG (with symbols, no optimization)"
|
||||
else
|
||||
echo "Build Type: PRODUCTION (optimized, stripped)"
|
||||
fi
|
||||
echo "DB Backend: $DB_BACKEND"
|
||||
if [ "$TRULY_STATIC" = true ]; then
|
||||
echo "Linkage: Fully static binary (Alpine MUSL-based)"
|
||||
echo "Portability: Works on ANY Linux distribution"
|
||||
else
|
||||
echo "Linkage: Static binary (may have minimal dependencies)"
|
||||
fi
|
||||
echo ""
|
||||
echo "✓ Build complete!"
|
||||
echo "Size: $(ls -lh "$BUILD_DIR/$OUTPUT_NAME" | awk '{print $5}')"
|
||||
echo ""
|
||||
|
||||
# Clean up Docker builder stage image
|
||||
$DOCKER_CMD rmi c-relay-pg-static-builder-stage:latest > /dev/null 2>&1 || true
|
||||
|
||||
@@ -25,6 +25,7 @@ RUN apk add --no-cache \
|
||||
curl-dev \
|
||||
curl-static \
|
||||
sqlite-dev \
|
||||
postgresql-dev \
|
||||
linux-headers \
|
||||
wget \
|
||||
bash
|
||||
@@ -103,13 +104,15 @@ RUN if [ "$DEBUG_BUILD" = "true" ]; then \
|
||||
-U_FORTIFY_SOURCE -D_FORTIFY_SOURCE=0 \
|
||||
-I. -Isrc -Inostr_core_lib -Inostr_core_lib/nostr_core \
|
||||
-Inostr_core_lib/cjson -Inostr_core_lib/nostr_websocket \
|
||||
-I/usr/include/postgresql \
|
||||
src/main.c src/debug.c src/jsonc_strip.c src/config.c src/state.c \
|
||||
src/follow_graph.c src/relay_sink.c src/live_subscriber.c \
|
||||
src/backfill.c src/relay_discovery.c \
|
||||
src/pg_inbox.c src/pg_config.c src/forward_catchup.c \
|
||||
-o /build/caching_relay_static \
|
||||
nostr_core_lib/libnostr_core.a \
|
||||
-lwebsockets -lssl -lcrypto -lsecp256k1 \
|
||||
-lcurl -lz -lpthread -lm -ldl && \
|
||||
-lcurl -lz -lpthread -lm -ldl -lpq -lpgcommon -lpgport && \
|
||||
eval "$STRIP_CMD"
|
||||
|
||||
# Verify it's truly static
|
||||
|
||||
+21
-3
@@ -61,7 +61,25 @@ $(TARGET): $(MAIN_SRC) $(NOSTR_CORE_LIB)
|
||||
rm -rf /tmp/cr_lib && \
|
||||
echo "Build complete: $(TARGET)"
|
||||
|
||||
clean:
|
||||
rm -f $(TARGET)
|
||||
# ------------------------------------------------------------------ #
|
||||
# cache_all_test - feasibility test for "cache everything" approach #
|
||||
# ------------------------------------------------------------------ #
|
||||
TEST_TARGET = ../build/cache_all_test
|
||||
TEST_SRC = src/cache_all_test.c src/debug.c src/jsonc_strip.c src/config.c \
|
||||
src/state.c
|
||||
|
||||
.PHONY: all clean
|
||||
$(TEST_TARGET): $(TEST_SRC) $(NOSTR_CORE_LIB)
|
||||
@echo "Compiling cache_all_test for architecture: $(ARCH)"
|
||||
@rm -rf /tmp/cr_lib && mkdir -p /tmp/cr_lib && \
|
||||
ar x $(NOSTR_CORE_LIB) --output=/tmp/cr_lib && \
|
||||
echo "Extracted $$(ls /tmp/cr_lib/*.o | wc -l) objects" && \
|
||||
$(CC) $(CFLAGS) $(INCLUDES) $(TEST_SRC) /tmp/cr_lib/*.o -o $(TEST_TARGET) $(LIBS) && \
|
||||
rm -rf /tmp/cr_lib && \
|
||||
echo "Build complete: $(TEST_TARGET)"
|
||||
|
||||
cache_all_test: $(TEST_TARGET)
|
||||
|
||||
clean:
|
||||
rm -f $(TARGET) $(TEST_TARGET)
|
||||
|
||||
.PHONY: all clean cache_all_test
|
||||
|
||||
@@ -0,0 +1,56 @@
|
||||
{
|
||||
// Cache-All Feasibility Test Config
|
||||
// Root npubs to resolve follow graph from
|
||||
"root_npubs": [
|
||||
"npub1rmz9gu6de0m0u4ysrn39crrud099ahvfgs6pvasl4hpjr5ud7yus54xv06"
|
||||
],
|
||||
|
||||
// Relays to test (from server relay list, connected ones only)
|
||||
"upstream_relays": [
|
||||
"wss://laantungir.net",
|
||||
"wss://nos.lol",
|
||||
"wss://nostr-pub.wellorder.net",
|
||||
"wss://nostr.mom",
|
||||
"wss://nostr.oxtr.dev",
|
||||
"wss://offchain.pub",
|
||||
"wss://premium.primal.net",
|
||||
"wss://relay.damus.io",
|
||||
"wss://relay.ditto.pub",
|
||||
"wss://relay.divine.video",
|
||||
"wss://relay.momostr.pink",
|
||||
"wss://relay.mostr.pub",
|
||||
"wss://relay.nostrplebs.com",
|
||||
"wss://relay.primal.net",
|
||||
"wss://theforest.nostr1.com"
|
||||
],
|
||||
|
||||
// Local relay (not used by test, but required by config parser)
|
||||
"local_relay": "ws://localhost:8888",
|
||||
|
||||
// Kinds to follow (not used by test, but required by config parser)
|
||||
"kinds": [0, 1, 3, 5, 6, 7, 9735, 10002, 30023],
|
||||
|
||||
// Admin kinds
|
||||
"admin_kinds": ["*"],
|
||||
|
||||
// Backfill config (not used by test)
|
||||
"backfill": {
|
||||
"enabled": false,
|
||||
"events_per_tick": 500,
|
||||
"tick_interval_seconds": 5
|
||||
},
|
||||
|
||||
// Live config (not used by test)
|
||||
"live": {
|
||||
"enabled": false,
|
||||
"resubscribe_interval_seconds": 300
|
||||
},
|
||||
|
||||
// Follow graph refresh (not used by test)
|
||||
"follow_graph_refresh_seconds": 600,
|
||||
|
||||
// State (not used by test)
|
||||
"state": {
|
||||
"backfilled_until": 0
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
{
|
||||
"root_npubs": [
|
||||
"npub1rmz9gu6de0m0u4ysrn39crrud099ahvfgs6pvasl4hpjr5ud7yus54xv06"
|
||||
],
|
||||
"upstream_relays": [
|
||||
"wss://relay.primal.net"
|
||||
],
|
||||
"local_relay": "ws://localhost:8888",
|
||||
"kinds": [0, 1, 3, 5, 6, 7, 9735, 10002, 30023],
|
||||
"admin_kinds": ["*"],
|
||||
"backfill": { "enabled": false, "events_per_tick": 500, "tick_interval_seconds": 5 },
|
||||
"live": { "enabled": false, "resubscribe_interval_seconds": 300 },
|
||||
"follow_graph_refresh_seconds": 600,
|
||||
"state": { "backfilled_until": 0 }
|
||||
}
|
||||
@@ -0,0 +1,253 @@
|
||||
=== Cache-All Feasibility Test Report ===
|
||||
Duration: 0h 5m 0s
|
||||
Config: cache_all_test_config.jsonc
|
||||
|
||||
=== Global Summary ===
|
||||
Total events: 11200
|
||||
Total bytes: 17099684 (16.31 MB)
|
||||
Avg event size: 1527 bytes
|
||||
Max event: 45848 bytes (kind 3)
|
||||
Unique pubkeys: 4292
|
||||
Relays contacted: 3
|
||||
|
||||
=== Relay Summary ===
|
||||
Relay Events EOSE CLOSED NOTICE Err Disc Status
|
||||
wss://relay.primal.net 3492 1 0 0 0 0 DOWN
|
||||
wss://nos.lol 5613 0 0 0 0 0 DOWN
|
||||
wss://relay.damus.io 2095 0 0 0 0 0 DOWN
|
||||
|
||||
=== Kind Distribution ===
|
||||
Kind Name Count % Total Bytes Avg Max
|
||||
21059 Gift wrap (NIP-59) 3060 27.3% 8988132 2937 19622
|
||||
5 Deletion 1124 10.0% 498378 443 664
|
||||
24747 Ephemeral 1020 9.1% 602037 590 671
|
||||
22668 Ephemeral 547 4.9% 234663 429 429
|
||||
30078 App data 439 3.9% 1714659 3906 37853
|
||||
20001 Ephemeral (key xchg) 395 3.5% 266277 674 1719
|
||||
22734 Ephemeral 265 2.4% 113155 427 427
|
||||
4515 Unknown 246 2.2% 390676 1588 8760
|
||||
1 Text note 205 1.8% 164127 801 2024
|
||||
1059 Gift wrap seal 188 1.7% 301940 1606 5285
|
||||
23334 Ephemeral 179 1.6% 77621 434 438
|
||||
38501 App data (btc) 157 1.4% 116283 741 744
|
||||
30382 Addressable 138 1.2% 66879 485 498
|
||||
21050 Ephemeral 132 1.2% 128700 975 2558
|
||||
10002 Relay list 127 1.1% 178988 1409 42385
|
||||
22850 Ephemeral 124 1.1% 53320 430 430
|
||||
31991 Addressable 122 1.1% 56242 461 461
|
||||
0 Profile metadata 120 1.1% 92899 774 7180
|
||||
37195 Addressable 102 0.9% 77276 758 832
|
||||
24242 Ephemeral 93 0.8% 56549 608 3281
|
||||
25050 Ephemeral 90 0.8% 39930 444 465
|
||||
7 Reaction 79 0.7% 42454 537 738
|
||||
23337 Ephemeral 73 0.7% 37477 513 519
|
||||
24133 Ephemeral 71 0.6% 146874 2069 7334
|
||||
445 Encrypted group msg 68 0.6% 386304 5681 38736
|
||||
22601 Ephemeral 62 0.6% 26536 428 428
|
||||
22613 Ephemeral 58 0.5% 40166 693 695
|
||||
22749 Ephemeral 56 0.5% 24024 429 429
|
||||
22699 Ephemeral 56 0.5% 23968 428 428
|
||||
22676 Ephemeral 56 0.5% 23912 427 427
|
||||
23003 Ephemeral 50 0.4% 21400 428 428
|
||||
13194 NWC info 50 0.4% 25490 510 514
|
||||
29333 Ephemeral 50 0.4% 24600 492 492
|
||||
22795 Ephemeral 50 0.4% 22860 457 1839
|
||||
22774 Ephemeral 50 0.4% 21401 428 429
|
||||
20000 Ephemeral 50 0.4% 23047 461 536
|
||||
22655 Ephemeral 49 0.4% 20972 428 428
|
||||
31990 App handler info 46 0.4% 43151 938 1465
|
||||
5300 Unknown 44 0.4% 27099 616 701
|
||||
30383 Addressable 44 0.4% 23495 534 542
|
||||
22456 Ephemeral 43 0.4% 21378 497 790
|
||||
25555 Ephemeral 42 0.4% 175994 4190 16987
|
||||
20004 Ephemeral 39 0.3% 20619 529 549
|
||||
3927 Unknown 39 0.3% 20809 534 544
|
||||
22484 Ephemeral 36 0.3% 32790 911 1165
|
||||
11998 Unknown 33 0.3% 15297 464 465
|
||||
7368 Unknown 32 0.3% 33232 1038 1041
|
||||
20387 Ephemeral 31 0.3% 15934 514 514
|
||||
22507 Ephemeral 28 0.2% 25861 924 1163
|
||||
20787 Ephemeral 26 0.2% 34212 1316 2282
|
||||
10100 Unknown 25 0.2% 48552 1942 3825
|
||||
30091 Addressable 23 0.2% 14133 614 629
|
||||
30088 Addressable 23 0.2% 42847 1863 1871
|
||||
38502 Addressable 22 0.2% 8470 385 385
|
||||
4 Encrypted DM 22 0.2% 25752 1171 6250
|
||||
1985 Label 22 0.2% 10436 474 483
|
||||
10050 DM relays 21 0.2% 9383 447 465
|
||||
30315 User status 20 0.2% 12697 635 926
|
||||
22816 Ephemeral 20 0.2% 8580 429 429
|
||||
4004 Unknown 19 0.2% 22211 1169 1169
|
||||
22522 Ephemeral 18 0.2% 7632 424 424
|
||||
22914 Ephemeral 17 0.2% 15202 894 1819
|
||||
3 Follow list 15 0.1% 210884 14059 45848
|
||||
22591 Ephemeral 15 0.1% 6390 426 426
|
||||
30089 Chunked data 15 0.1% 221528 14769 44372
|
||||
6300 Unknown 15 0.1% 83624 5575 17374
|
||||
30023 Long-form article 15 0.1% 83310 5554 8177
|
||||
20333 Ephemeral 15 0.1% 11950 797 798
|
||||
22832 Ephemeral 14 0.1% 6006 429 429
|
||||
1077 Unknown 14 0.1% 8498 607 607
|
||||
22651 Ephemeral 14 0.1% 5992 428 428
|
||||
30515 Addressable 14 0.1% 55160 3940 3940
|
||||
23333 Ephemeral 11 0.1% 6455 587 601
|
||||
2333 Unknown 11 0.1% 7423 675 689
|
||||
30311 Addressable 10 0.1% 10569 1057 1214
|
||||
21617 Ephemeral 10 0.1% 4950 495 495
|
||||
30443 Addressable 10 0.1% 11954 1195 1292
|
||||
9735 Zap receipt 10 0.1% 20601 2060 2282
|
||||
1337 Unknown 10 0.1% 5696 570 811
|
||||
25055 Ephemeral 10 0.1% 14724 1472 1764
|
||||
21060 Ephemeral 9 0.1% 5130 570 570
|
||||
38225 Addressable 9 0.1% 9197 1022 1047
|
||||
22949 Ephemeral 9 0.1% 3879 431 431
|
||||
4244 Unknown 9 0.1% 5076 564 564
|
||||
7375 Unknown 9 0.1% 72189 8021 14089
|
||||
7376 Unknown 9 0.1% 4689 521 521
|
||||
38385 Addressable 9 0.1% 12280 1364 1496
|
||||
31234 Addressable 9 0.1% 12744 1416 1416
|
||||
22712 Ephemeral 8 0.1% 3424 428 428
|
||||
38503 Addressable 8 0.1% 4424 553 553
|
||||
30113 Addressable 8 0.1% 4688 586 701
|
||||
6 Repost 8 0.1% 11116 1390 2553
|
||||
31510 Addressable 7 0.1% 6853 979 982
|
||||
22785 Ephemeral 7 0.1% 2996 428 428
|
||||
22680 Ephemeral 7 0.1% 6191 884 1160
|
||||
22793 Ephemeral 7 0.1% 2996 428 428
|
||||
22684 Ephemeral 6 0.1% 2574 429 429
|
||||
22225 Ephemeral 6 0.1% 2661 444 444
|
||||
1002 Unknown 6 0.1% 5458 910 971
|
||||
22739 Ephemeral 6 0.1% 2568 428 428
|
||||
22658 Ephemeral 6 0.1% 5377 896 1164
|
||||
30080 Addressable 5 0.0% 4658 932 985
|
||||
33334 Addressable 5 0.0% 4155 831 831
|
||||
10011 Unknown 5 0.0% 2155 431 431
|
||||
25195 Ephemeral 5 0.0% 3390 678 678
|
||||
22508 Ephemeral 5 0.0% 2130 426 426
|
||||
22789 Ephemeral 5 0.0% 2140 428 428
|
||||
30380 Addressable 5 0.0% 2270 454 454
|
||||
38384 Addressable 5 0.0% 3715 743 743
|
||||
20384 Ephemeral 5 0.0% 3195 639 639
|
||||
22688 Ephemeral 5 0.0% 2150 430 430
|
||||
22649 Ephemeral 5 0.0% 2135 427 427
|
||||
39101 Addressable 5 0.0% 2665 533 533
|
||||
22611 Ephemeral 5 0.0% 2130 426 426
|
||||
22526 Ephemeral 5 0.0% 2150 430 430
|
||||
22514 Ephemeral 4 0.0% 1700 425 425
|
||||
22775 Ephemeral 4 0.0% 1716 429 429
|
||||
443 Unknown 4 0.0% 4336 1084 1084
|
||||
25196 Ephemeral 4 0.0% 7152 1788 2214
|
||||
30618 Addressable 4 0.0% 6570 1642 4371
|
||||
23194 NWC request 4 0.0% 2106 526 576
|
||||
1040 Unknown 4 0.0% 4192 1048 1048
|
||||
38500 Addressable 4 0.0% 2848 712 713
|
||||
22236 Ephemeral 4 0.0% 3109 777 801
|
||||
1111 Comment 4 0.0% 5593 1398 1988
|
||||
3434 Unknown 3 0.0% 2035 678 705
|
||||
1050 Unknown 3 0.0% 1311 437 437
|
||||
33051 Addressable 3 0.0% 1559 520 522
|
||||
7000 Unknown 3 0.0% 2329 776 779
|
||||
22309 Ephemeral 3 0.0% 1331 444 444
|
||||
30617 Addressable 3 0.0% 3267 1089 1089
|
||||
10030 Emoji list 3 0.0% 1215 405 405
|
||||
22253 Ephemeral 3 0.0% 1331 444 444
|
||||
22345 Ephemeral 3 0.0% 1331 444 444
|
||||
4245 Unknown 3 0.0% 1332 444 444
|
||||
22423 Ephemeral 3 0.0% 1331 444 444
|
||||
4243 Unknown 3 0.0% 1692 564 564
|
||||
10000 Mute list 3 0.0% 4678 1559 3850
|
||||
22352 Ephemeral 3 0.0% 1330 443 444
|
||||
38383 Addressable 3 0.0% 2159 720 743
|
||||
22327 Ephemeral 3 0.0% 1330 443 444
|
||||
30213 Addressable 3 0.0% 1880 627 637
|
||||
20 Picture 2 0.0% 1272 636 827
|
||||
10312 Unknown 2 0.0% 973 486 491
|
||||
10007 Search relays 2 0.0% 1272 636 754
|
||||
10086 Unknown 2 0.0% 1451 726 757
|
||||
22891 Ephemeral 2 0.0% 2272 1136 1843
|
||||
22495 Ephemeral 2 0.0% 854 427 427
|
||||
4242 Unknown 2 0.0% 12868 6434 6443
|
||||
30000 Follow sets 2 0.0% 1773 886 950
|
||||
22777 Ephemeral 2 0.0% 856 428 428
|
||||
22391 Ephemeral 2 0.0% 887 444 444
|
||||
6472 Unknown 2 0.0% 1106 553 553
|
||||
22239 Ephemeral 2 0.0% 887 444 444
|
||||
22146 Ephemeral 2 0.0% 886 443 443
|
||||
22420 Ephemeral 2 0.0% 887 444 444
|
||||
10063 Unknown 2 0.0% 1012 506 627
|
||||
22193 Ephemeral 2 0.0% 886 443 443
|
||||
22275 Ephemeral 2 0.0% 886 443 443
|
||||
31000 Addressable 2 0.0% 1204 602 616
|
||||
22738 Ephemeral 2 0.0% 858 429 429
|
||||
31340 Addressable 2 0.0% 854 427 430
|
||||
22218 Ephemeral 2 0.0% 887 444 444
|
||||
22285 Ephemeral 2 0.0% 887 444 444
|
||||
7403 Unknown 2 0.0% 982 491 491
|
||||
22302 Ephemeral 2 0.0% 886 443 443
|
||||
22241 Ephemeral 2 0.0% 887 444 444
|
||||
22288 Ephemeral 2 0.0% 887 444 444
|
||||
22120 Ephemeral 2 0.0% 2170 1085 1118
|
||||
22119 Ephemeral 2 0.0% 1691 846 846
|
||||
15750 Unknown 2 0.0% 1184 592 620
|
||||
10443 Unknown 2 0.0% 2578 1289 1289
|
||||
22736 Ephemeral 1 0.0% 429 429 429
|
||||
22653 Ephemeral 1 0.0% 1840 1840 1840
|
||||
22842 Ephemeral 1 0.0% 1847 1847 1847
|
||||
22190 Ephemeral 1 0.0% 443 443 443
|
||||
37779 Addressable 1 0.0% 523 523 523
|
||||
22312 Ephemeral 1 0.0% 443 443 443
|
||||
1717 Unknown 1 0.0% 1776 1776 1776
|
||||
22407 Ephemeral 1 0.0% 425 425 425
|
||||
1340 Unknown 1 0.0% 435 435 435
|
||||
10051 Unknown 1 0.0% 443 443 443
|
||||
10012 Unknown 1 0.0% 522 522 522
|
||||
22368 Ephemeral 1 0.0% 443 443 443
|
||||
10003 Bookmarks 1 0.0% 1974 1974 1974
|
||||
39015 Addressable 1 0.0% 696 696 696
|
||||
1311 Unknown 1 0.0% 534 534 534
|
||||
22820 Ephemeral 1 0.0% 430 430 430
|
||||
22928 Ephemeral 1 0.0% 429 429 429
|
||||
22713 Ephemeral 1 0.0% 429 429 429
|
||||
22543 Ephemeral 1 0.0% 1843 1843 1843
|
||||
22369 Ephemeral 1 0.0% 443 443 443
|
||||
22314 Ephemeral 1 0.0% 443 443 443
|
||||
10001 Pinned notes 1 0.0% 710 710 710
|
||||
30815 Addressable 1 0.0% 37534 37534 37534
|
||||
31339 Addressable 1 0.0% 1470 1470 1470
|
||||
38422 Addressable 1 0.0% 20019 20019 20019
|
||||
30087 Addressable 1 0.0% 7325 7325 7325
|
||||
30090 Addressable 1 0.0% 1515 1515 1515
|
||||
10089 Unknown 1 0.0% 1097 1097 1097
|
||||
13196 Unknown 1 0.0% 656 656 656
|
||||
39050 Addressable 1 0.0% 1843 1843 1843
|
||||
10005 Unknown 1 0.0% 694 694 694
|
||||
30554 Addressable 1 0.0% 609 609 609
|
||||
22765 Ephemeral 1 0.0% 431 431 431
|
||||
1078 Unknown 1 0.0% 13949 13949 13949
|
||||
22740 Ephemeral 1 0.0% 3194 3194 3194
|
||||
38111 Addressable 1 0.0% 747 747 747
|
||||
4747 Unknown 1 0.0% 721 721 721
|
||||
10019 Unknown 1 0.0% 536 536 536
|
||||
22333 Ephemeral 1 0.0% 443 443 443
|
||||
22318 Ephemeral 1 0.0% 443 443 443
|
||||
23010 Ephemeral 1 0.0% 429 429 429
|
||||
30079 Addressable 1 0.0% 875 875 875
|
||||
22455 Ephemeral 1 0.0% 1840 1840 1840
|
||||
22219 Ephemeral 1 0.0% 443 443 443
|
||||
30787 Addressable 1 0.0% 1370 1370 1370
|
||||
22624 Ephemeral 1 0.0% 3198 3198 3198
|
||||
22750 Ephemeral 1 0.0% 553 553 553
|
||||
22313 Ephemeral 1 0.0% 443 443 443
|
||||
1080 Unknown 1 0.0% 1033 1033 1033
|
||||
11316 Unknown 1 0.0% 725 725 725
|
||||
11317 Unknown 1 0.0% 12051 12051 12051
|
||||
12222 Unknown 1 0.0% 579 579 579
|
||||
22823 Ephemeral 1 0.0% 429 429 429
|
||||
|
||||
=== Raw Relay Response Log ===
|
||||
# Cache-All Feasibility Test - Raw Relay Log
|
||||
# Started: Sun Aug 2 09:32:17 2026
|
||||
# Config: cache_all_test_config.jsonc
|
||||
# Duration: 300 seconds
|
||||
[2026-08-02 09:32:24] [RELAY] wss://relay.primal.net EOSE
|
||||
|
||||
@@ -0,0 +1,207 @@
|
||||
=== Cache-All Feasibility Test Report ===
|
||||
Duration: 0h 2m 0s
|
||||
Config: cache_all_test_config.jsonc
|
||||
|
||||
=== Global Summary ===
|
||||
Total events: 4267
|
||||
Total bytes: 6726611 (6.41 MB)
|
||||
Avg event size: 1576 bytes
|
||||
Max event: 42385 bytes (kind 10002)
|
||||
Unique pubkeys: 1860
|
||||
Relays contacted: 3
|
||||
|
||||
=== Relay Summary ===
|
||||
Relay Events EOSE CLOSED NOTICE Err Disc Status
|
||||
wss://relay.primal.net 1670 1 0 0 0 0 OK
|
||||
wss://nos.lol 1792 0 0 0 0 0 OK
|
||||
wss://relay.damus.io 805 0 0 0 0 0 OK
|
||||
|
||||
=== Kind Distribution ===
|
||||
Kind Name Count % Total Bytes Avg Max
|
||||
21059 Gift wrap (NIP-59) 1199 28.1% 3547818 2959 5314
|
||||
5 Deletion 466 10.9% 204587 439 1064
|
||||
30078 App data 222 5.2% 948782 4274 40337
|
||||
22668 Ephemeral 221 5.2% 94809 429 429
|
||||
20001 Ephemeral (key xchg) 152 3.6% 106536 701 1755
|
||||
4515 Unknown 152 3.6% 260732 1715 8759
|
||||
22734 Ephemeral 108 2.5% 46116 427 427
|
||||
1 Text note 105 2.5% 83026 791 3482
|
||||
21050 Ephemeral 91 2.1% 89206 980 2558
|
||||
24747 Ephemeral 85 2.0% 42775 503 671
|
||||
22850 Ephemeral 77 1.8% 33110 430 430
|
||||
22591 Ephemeral 66 1.5% 53607 812 1222
|
||||
38501 App data (btc) 61 1.4% 45175 741 744
|
||||
10002 Relay list 51 1.2% 63749 1250 42385
|
||||
0 Profile metadata 47 1.1% 33672 716 1611
|
||||
37195 Addressable 44 1.0% 32855 747 771
|
||||
24242 Ephemeral 37 0.9% 21423 579 579
|
||||
25050 Ephemeral 36 0.8% 15972 444 465
|
||||
7 Reaction 36 0.8% 18965 527 646
|
||||
22613 Ephemeral 35 0.8% 26154 747 1134
|
||||
22484 Ephemeral 32 0.7% 29125 910 1163
|
||||
22749 Ephemeral 29 0.7% 12441 429 429
|
||||
24133 Ephemeral 25 0.6% 37446 1498 7334
|
||||
22601 Ephemeral 25 0.6% 10700 428 428
|
||||
22507 Ephemeral 24 0.6% 22582 941 1165
|
||||
1059 Gift wrap seal 23 0.5% 41391 1800 2897
|
||||
22699 Ephemeral 23 0.5% 9844 428 428
|
||||
22676 Ephemeral 23 0.5% 9821 427 427
|
||||
22774 Ephemeral 20 0.5% 8560 428 428
|
||||
22795 Ephemeral 20 0.5% 8580 429 429
|
||||
22655 Ephemeral 20 0.5% 8560 428 428
|
||||
23003 Ephemeral 20 0.5% 8560 428 428
|
||||
30382 Addressable 20 0.5% 9960 498 498
|
||||
29333 Ephemeral 20 0.5% 9840 492 492
|
||||
25555 Ephemeral 18 0.4% 62434 3469 17003
|
||||
11998 Unknown 18 0.4% 8322 462 465
|
||||
31990 App handler info 18 0.4% 16845 936 1465
|
||||
4 Encrypted DM 18 0.4% 28064 1559 17018
|
||||
13194 NWC info 18 0.4% 9252 514 514
|
||||
22689 Ephemeral 17 0.4% 7259 427 427
|
||||
5300 Unknown 17 0.4% 10495 617 701
|
||||
445 Encrypted group msg 17 0.4% 81892 4817 19620
|
||||
20000 Ephemeral 15 0.4% 7045 470 546
|
||||
20387 Ephemeral 14 0.3% 7196 514 514
|
||||
20004 Ephemeral 14 0.3% 7488 535 549
|
||||
7368 Unknown 13 0.3% 13476 1037 1040
|
||||
22456 Ephemeral 13 0.3% 6110 470 470
|
||||
9735 Zap receipt 13 0.3% 26072 2006 2331
|
||||
22551 Ephemeral 13 0.3% 11042 849 1161
|
||||
22760 Ephemeral 13 0.3% 11014 847 1161
|
||||
22658 Ephemeral 13 0.3% 11050 850 1164
|
||||
10100 Unknown 11 0.3% 20684 1880 3825
|
||||
30315 User status 11 0.3% 8899 809 1038
|
||||
20787 Ephemeral 11 0.3% 15458 1405 2474
|
||||
22236 Ephemeral 10 0.2% 7818 782 814
|
||||
22832 Ephemeral 10 0.2% 4286 429 429
|
||||
38502 Addressable 8 0.2% 3080 385 385
|
||||
4004 Unknown 8 0.2% 9352 1169 1169
|
||||
22785 Ephemeral 8 0.2% 3432 429 429
|
||||
3 Follow list 8 0.2% 35850 4481 9845
|
||||
1985 Label 8 0.2% 3792 474 474
|
||||
22584 Ephemeral 8 0.2% 3416 427 427
|
||||
22816 Ephemeral 8 0.2% 3432 429 429
|
||||
22752 Ephemeral 8 0.2% 6212 776 3199
|
||||
6 Repost 7 0.2% 10112 1445 1872
|
||||
443 Unknown 7 0.2% 7780 1111 1116
|
||||
22651 Ephemeral 6 0.1% 2568 428 428
|
||||
1077 Unknown 6 0.1% 3642 607 607
|
||||
26428 Ephemeral 6 0.1% 5254 876 876
|
||||
22616 Ephemeral 6 0.1% 2574 429 429
|
||||
22626 Ephemeral 6 0.1% 2568 428 428
|
||||
22914 Ephemeral 6 0.1% 2580 430 430
|
||||
22614 Ephemeral 6 0.1% 2568 428 428
|
||||
22419 Ephemeral 5 0.1% 2218 444 444
|
||||
22847 Ephemeral 5 0.1% 2155 431 431
|
||||
30088 Addressable 5 0.1% 9317 1863 1871
|
||||
10050 DM relays 5 0.1% 2250 450 450
|
||||
30091 Addressable 5 0.1% 3085 617 629
|
||||
30311 Addressable 5 0.1% 5153 1031 1197
|
||||
23080 Ephemeral 5 0.1% 2155 431 431
|
||||
38225 Addressable 4 0.1% 4077 1019 1036
|
||||
4244 Unknown 4 0.1% 2256 564 564
|
||||
26429 Ephemeral 4 0.1% 1964 491 491
|
||||
3927 Unknown 4 0.1% 2132 533 533
|
||||
22806 Ephemeral 4 0.1% 1712 428 428
|
||||
30000 Follow sets 4 0.1% 9358 2340 2845
|
||||
21617 Ephemeral 4 0.1% 1980 495 495
|
||||
20333 Ephemeral 4 0.1% 3188 797 798
|
||||
22548 Ephemeral 4 0.1% 1720 430 430
|
||||
38503 Addressable 4 0.1% 2212 553 553
|
||||
30515 Addressable 4 0.1% 18496 4624 4624
|
||||
22740 Ephemeral 4 0.1% 1708 427 427
|
||||
22226 Ephemeral 3 0.1% 1331 444 444
|
||||
10011 Unknown 3 0.1% 1375 458 513
|
||||
30089 Chunked data 3 0.1% 6944 2315 3412
|
||||
30023 Long-form article 3 0.1% 19822 6607 7860
|
||||
21060 Ephemeral 3 0.1% 1710 570 570
|
||||
22526 Ephemeral 3 0.1% 1290 430 430
|
||||
22511 Ephemeral 3 0.1% 2383 794 1163
|
||||
22167 Ephemeral 3 0.1% 1331 444 444
|
||||
30213 Addressable 3 0.1% 1866 622 632
|
||||
22748 Ephemeral 3 0.1% 1284 428 428
|
||||
31234 Addressable 3 0.1% 4248 1416 1416
|
||||
22838 Ephemeral 2 0.0% 860 430 430
|
||||
38500 Addressable 2 0.0% 1424 712 713
|
||||
38384 Addressable 2 0.0% 1486 743 743
|
||||
30443 Addressable 2 0.0% 2379 1190 1220
|
||||
20384 Ephemeral 2 0.0% 1278 639 639
|
||||
34237 Addressable 2 0.0% 836 418 418
|
||||
22280 Ephemeral 2 0.0% 887 444 444
|
||||
23194 NWC request 2 0.0% 1020 510 510
|
||||
22320 Ephemeral 2 0.0% 887 444 444
|
||||
30080 Addressable 2 0.0% 1971 986 986
|
||||
22205 Ephemeral 2 0.0% 887 444 444
|
||||
22770 Ephemeral 2 0.0% 862 431 431
|
||||
22305 Ephemeral 2 0.0% 887 444 444
|
||||
22356 Ephemeral 2 0.0% 886 443 443
|
||||
22611 Ephemeral 2 0.0% 852 426 426
|
||||
22217 Ephemeral 2 0.0% 887 444 444
|
||||
22884 Ephemeral 2 0.0% 860 430 430
|
||||
33334 Addressable 2 0.0% 1662 831 831
|
||||
6300 Unknown 2 0.0% 8371 4186 5058
|
||||
22169 Ephemeral 2 0.0% 887 444 444
|
||||
22190 Ephemeral 2 0.0% 887 444 444
|
||||
30079 Addressable 2 0.0% 1750 875 875
|
||||
39101 Addressable 2 0.0% 1066 533 533
|
||||
22345 Ephemeral 2 0.0% 887 444 444
|
||||
22310 Ephemeral 2 0.0% 887 444 444
|
||||
1111 Comment 2 0.0% 2557 1278 1564
|
||||
22235 Ephemeral 2 0.0% 887 444 444
|
||||
38385 Addressable 2 0.0% 2552 1276 1319
|
||||
4747 Unknown 1 0.0% 721 721 721
|
||||
22844 Ephemeral 1 0.0% 428 428 428
|
||||
22807 Ephemeral 1 0.0% 3205 3205 3205
|
||||
30066 Addressable 1 0.0% 675 675 675
|
||||
4245 Unknown 1 0.0% 444 444 444
|
||||
7376 Unknown 1 0.0% 521 521 521
|
||||
22450 Ephemeral 1 0.0% 443 443 443
|
||||
22261 Ephemeral 1 0.0% 443 443 443
|
||||
4243 Unknown 1 0.0% 564 564 564
|
||||
22242 Ephemeral 1 0.0% 443 443 443
|
||||
10063 Unknown 1 0.0% 415 415 415
|
||||
22306 Ephemeral 1 0.0% 443 443 443
|
||||
22174 Ephemeral 1 0.0% 443 443 443
|
||||
22831 Ephemeral 1 0.0% 3182 3182 3182
|
||||
22227 Ephemeral 1 0.0% 443 443 443
|
||||
7375 Unknown 1 0.0% 8629 8629 8629
|
||||
22685 Ephemeral 1 0.0% 553 553 553
|
||||
22299 Ephemeral 1 0.0% 443 443 443
|
||||
22193 Ephemeral 1 0.0% 443 443 443
|
||||
22975 Ephemeral 1 0.0% 3195 3195 3195
|
||||
30380 Addressable 1 0.0% 454 454 454
|
||||
20 Picture 1 0.0% 860 860 860
|
||||
10030 Emoji list 1 0.0% 405 405 405
|
||||
30087 Addressable 1 0.0% 7325 7325 7325
|
||||
30090 Addressable 1 0.0% 1515 1515 1515
|
||||
22220 Ephemeral 1 0.0% 443 443 443
|
||||
39019 Addressable 1 0.0% 961 961 961
|
||||
39015 Addressable 1 0.0% 696 696 696
|
||||
30617 Addressable 1 0.0% 1089 1089 1089
|
||||
30618 Addressable 1 0.0% 733 733 733
|
||||
31991 Addressable 1 0.0% 461 461 461
|
||||
1080 Unknown 1 0.0% 949 949 949
|
||||
3434 Unknown 1 0.0% 705 705 705
|
||||
33333 Addressable 1 0.0% 2346 2346 2346
|
||||
22735 Ephemeral 1 0.0% 430 430 430
|
||||
22415 Ephemeral 1 0.0% 443 443 443
|
||||
21966 Ephemeral 1 0.0% 443 443 443
|
||||
11316 Unknown 1 0.0% 725 725 725
|
||||
11317 Unknown 1 0.0% 12051 12051 12051
|
||||
25195 Ephemeral 1 0.0% 678 678 678
|
||||
25196 Ephemeral 1 0.0% 1362 1362 1362
|
||||
22402 Ephemeral 1 0.0% 443 443 443
|
||||
31510 Addressable 1 0.0% 979 979 979
|
||||
1078 Unknown 1 0.0% 14200 14200 14200
|
||||
38383 Addressable 1 0.0% 685 685 685
|
||||
|
||||
=== Raw Relay Response Log ===
|
||||
# Cache-All Feasibility Test - Raw Relay Log
|
||||
# Started: Sun Aug 2 09:38:02 2026
|
||||
# Config: cache_all_test_config.jsonc
|
||||
# Duration: 120 seconds
|
||||
[2026-08-02 09:38:07] [RELAY] wss://relay.primal.net CONNECTED
|
||||
[2026-08-02 09:38:07] [RELAY] wss://nos.lol CONNECTED
|
||||
[2026-08-02 09:38:07] [RELAY] wss://relay.damus.io CONNECTED
|
||||
[2026-08-02 09:38:08] [RELAY] wss://relay.primal.net EOSE
|
||||
|
||||
@@ -0,0 +1,206 @@
|
||||
=== Cache-All Feasibility Test Report ===
|
||||
Duration: 0h 2m 0s
|
||||
Config: cache_all_test_config.jsonc
|
||||
|
||||
=== Global Summary ===
|
||||
Total events: 5012
|
||||
Total bytes: 8091410 (7.72 MB)
|
||||
Avg event size: 1614 bytes
|
||||
Max event: 52672 bytes (kind 3)
|
||||
Unique pubkeys: 2034
|
||||
Relays contacted: 3
|
||||
|
||||
=== Relay Summary ===
|
||||
Relay Events EOSE CLOSED NOTICE Err Disc Status
|
||||
wss://relay.primal.net 1599 1 0 0 0 0 OK
|
||||
wss://nos.lol 2389 0 0 0 0 0 OK
|
||||
wss://relay.damus.io 1024 0 0 0 0 0 OK
|
||||
|
||||
=== Kind Distribution ===
|
||||
Kind Name Count % Total Bytes Avg Max
|
||||
21059 Gift wrap (NIP-59) 1361 27.2% 4189338 3078 5314
|
||||
5 Deletion 579 11.6% 254363 439 624
|
||||
22668 Ephemeral 265 5.3% 113685 429 429
|
||||
30078 App data 190 3.8% 702178 3696 14343
|
||||
20001 Ephemeral (key xchg) 181 3.6% 108257 598 1489
|
||||
22639 Ephemeral 176 3.5% 136058 773 1228
|
||||
4515 Unknown 168 3.4% 319242 1900 14220
|
||||
24133 Ephemeral 152 3.0% 464764 3058 14162
|
||||
22734 Ephemeral 135 2.7% 57645 427 427
|
||||
31991 Addressable 116 2.3% 53476 461 461
|
||||
21050 Ephemeral 84 1.7% 81900 975 2558
|
||||
1 Text note 80 1.6% 58412 730 1443
|
||||
22795 Ephemeral 76 1.5% 104000 1368 1848
|
||||
22850 Ephemeral 75 1.5% 33353 445 1169
|
||||
38501 App data (btc) 69 1.4% 51105 741 744
|
||||
22842 Ephemeral 55 1.1% 92475 1681 1849
|
||||
10002 Relay list 48 1.0% 19784 412 537
|
||||
0 Profile metadata 47 0.9% 34961 744 1356
|
||||
37195 Addressable 38 0.8% 28214 742 771
|
||||
7 Reaction 38 0.8% 21600 568 779
|
||||
25050 Ephemeral 36 0.7% 15972 444 465
|
||||
24242 Ephemeral 34 0.7% 19686 579 579
|
||||
1059 Gift wrap seal 33 0.7% 58147 1762 3298
|
||||
22484 Ephemeral 32 0.6% 29156 911 1164
|
||||
22507 Ephemeral 28 0.6% 24308 868 1165
|
||||
22613 Ephemeral 25 0.5% 17238 690 691
|
||||
29333 Ephemeral 25 0.5% 12300 492 492
|
||||
22601 Ephemeral 24 0.5% 10272 428 428
|
||||
5300 Unknown 23 0.5% 14096 613 701
|
||||
22751 Ephemeral 23 0.5% 9798 426 426
|
||||
22699 Ephemeral 22 0.4% 9416 428 428
|
||||
11998 Unknown 22 0.4% 10182 463 465
|
||||
22676 Ephemeral 22 0.4% 9394 427 427
|
||||
13194 NWC info 21 0.4% 10617 506 514
|
||||
22774 Ephemeral 20 0.4% 8560 428 428
|
||||
23003 Ephemeral 20 0.4% 8560 428 428
|
||||
22655 Ephemeral 19 0.4% 8132 428 428
|
||||
22543 Ephemeral 19 0.4% 34993 1842 1848
|
||||
22455 Ephemeral 19 0.4% 34943 1839 1844
|
||||
25555 Ephemeral 19 0.4% 94673 4983 17111
|
||||
30443 Addressable 19 0.4% 22379 1178 1260
|
||||
22777 Ephemeral 19 0.4% 16685 878 1651
|
||||
22891 Ephemeral 18 0.4% 33189 1844 1848
|
||||
31990 App handler info 17 0.3% 15825 931 1465
|
||||
20000 Ephemeral 16 0.3% 7206 450 522
|
||||
32123 Addressable 14 0.3% 10528 752 900
|
||||
22456 Ephemeral 13 0.3% 6110 470 470
|
||||
20004 Ephemeral 13 0.3% 6741 519 549
|
||||
22591 Ephemeral 13 0.3% 6348 488 697
|
||||
20787 Ephemeral 12 0.2% 16864 1405 2478
|
||||
4 Encrypted DM 12 0.2% 7972 664 786
|
||||
20387 Ephemeral 12 0.2% 6168 514 514
|
||||
38502 Addressable 12 0.2% 4620 385 385
|
||||
10100 Unknown 11 0.2% 20938 1903 3825
|
||||
20050 Ephemeral 11 0.2% 9711 883 891
|
||||
3 Follow list 10 0.2% 72137 7214 52672
|
||||
9735 Zap receipt 10 0.2% 20833 2083 2143
|
||||
445 Encrypted group msg 10 0.2% 17866 1787 4126
|
||||
22626 Ephemeral 10 0.2% 4280 428 428
|
||||
7368 Unknown 9 0.2% 9343 1038 1041
|
||||
22736 Ephemeral 9 0.2% 3816 424 424
|
||||
1985 Label 8 0.2% 3810 476 483
|
||||
30091 Addressable 8 0.2% 4927 616 629
|
||||
30315 User status 8 0.2% 4522 565 872
|
||||
25055 Ephemeral 8 0.2% 10605 1326 1764
|
||||
22791 Ephemeral 8 0.2% 3416 427 427
|
||||
22816 Ephemeral 8 0.2% 3432 429 429
|
||||
4004 Unknown 8 0.2% 9352 1169 1169
|
||||
30088 Addressable 8 0.2% 14929 1866 1871
|
||||
31234 Addressable 8 0.2% 14048 1756 1756
|
||||
22813 Ephemeral 7 0.1% 2996 428 428
|
||||
22957 Ephemeral 7 0.1% 3010 430 430
|
||||
30089 Chunked data 7 0.1% 45972 6567 27988
|
||||
32678 Addressable 7 0.1% 5704 815 900
|
||||
22832 Ephemeral 6 0.1% 2574 429 429
|
||||
22897 Ephemeral 6 0.1% 2586 431 431
|
||||
22549 Ephemeral 6 0.1% 2574 429 429
|
||||
22702 Ephemeral 6 0.1% 4753 792 2618
|
||||
20333 Ephemeral 6 0.1% 4780 797 798
|
||||
30023 Long-form article 6 0.1% 21101 3517 5056
|
||||
22568 Ephemeral 5 0.1% 2135 427 427
|
||||
38385 Addressable 5 0.1% 6849 1370 1496
|
||||
4244 Unknown 5 0.1% 2820 564 564
|
||||
22717 Ephemeral 5 0.1% 2135 427 427
|
||||
21617 Ephemeral 4 0.1% 1980 495 495
|
||||
38225 Addressable 4 0.1% 4061 1015 1039
|
||||
6 Repost 4 0.1% 8823 2206 3647
|
||||
22333 Ephemeral 4 0.1% 1773 443 444
|
||||
22962 Ephemeral 3 0.1% 1290 430 430
|
||||
33334 Addressable 3 0.1% 2229 743 831
|
||||
1002 Unknown 3 0.1% 2793 931 979
|
||||
22244 Ephemeral 3 0.1% 1330 443 444
|
||||
22907 Ephemeral 3 0.1% 1287 429 429
|
||||
10011 Unknown 3 0.1% 1229 410 431
|
||||
22258 Ephemeral 3 0.1% 1330 443 444
|
||||
22245 Ephemeral 3 0.1% 1331 444 444
|
||||
30618 Addressable 3 0.1% 1755 585 733
|
||||
22296 Ephemeral 3 0.1% 1331 444 444
|
||||
38503 Addressable 3 0.1% 1659 553 553
|
||||
22338 Ephemeral 3 0.1% 1330 443 444
|
||||
22195 Ephemeral 3 0.1% 1331 444 444
|
||||
22342 Ephemeral 3 0.1% 1331 444 444
|
||||
10050 DM relays 3 0.1% 1350 450 450
|
||||
30311 Addressable 3 0.1% 3414 1138 1197
|
||||
32680 Addressable 2 0.0% 1376 688 688
|
||||
30380 Addressable 2 0.0% 908 454 454
|
||||
22611 Ephemeral 2 0.0% 852 426 426
|
||||
4243 Unknown 2 0.0% 1128 564 564
|
||||
22526 Ephemeral 2 0.0% 860 430 430
|
||||
22320 Ephemeral 2 0.0% 887 444 444
|
||||
4245 Unknown 2 0.0% 888 444 444
|
||||
1984 Report 2 0.0% 873 436 446
|
||||
1111 Comment 2 0.0% 3115 1558 1558
|
||||
22311 Ephemeral 2 0.0% 886 443 443
|
||||
22662 Ephemeral 2 0.0% 858 429 429
|
||||
22089 Ephemeral 2 0.0% 886 443 443
|
||||
22221 Ephemeral 2 0.0% 887 444 444
|
||||
22157 Ephemeral 2 0.0% 887 444 444
|
||||
38384 Addressable 2 0.0% 1486 743 743
|
||||
20384 Ephemeral 2 0.0% 1278 639 639
|
||||
30080 Addressable 2 0.0% 1679 840 985
|
||||
39101 Addressable 2 0.0% 1066 533 533
|
||||
6300 Unknown 2 0.0% 11904 5952 6898
|
||||
10003 Bookmarks 2 0.0% 14466 7233 7233
|
||||
30515 Addressable 2 0.0% 9248 4624 4624
|
||||
22829 Ephemeral 2 0.0% 6387 3194 3194
|
||||
22106 Ephemeral 2 0.0% 887 444 444
|
||||
31927 Addressable 2 0.0% 3000 1500 1500
|
||||
31510 Addressable 2 0.0% 1959 980 980
|
||||
3927 Unknown 2 0.0% 1066 533 533
|
||||
1040 Unknown 2 0.0% 2096 1048 1048
|
||||
31000 Addressable 2 0.0% 1204 602 616
|
||||
22201 Ephemeral 2 0.0% 886 443 443
|
||||
22269 Ephemeral 2 0.0% 887 444 444
|
||||
22818 Ephemeral 2 0.0% 852 426 426
|
||||
22364 Ephemeral 2 0.0% 887 444 444
|
||||
25195 Ephemeral 1 0.0% 678 678 678
|
||||
25196 Ephemeral 1 0.0% 1362 1362 1362
|
||||
22283 Ephemeral 1 0.0% 443 443 443
|
||||
10030 Emoji list 1 0.0% 405 405 405
|
||||
22706 Ephemeral 1 0.0% 3192 3192 3192
|
||||
22236 Ephemeral 1 0.0% 737 737 737
|
||||
31339 Addressable 1 0.0% 1470 1470 1470
|
||||
22651 Ephemeral 1 0.0% 428 428 428
|
||||
38500 Addressable 1 0.0% 713 713 713
|
||||
10000 Mute list 1 0.0% 1311 1311 1311
|
||||
31926 Addressable 1 0.0% 1038 1038 1038
|
||||
22757 Ephemeral 1 0.0% 428 428 428
|
||||
39015 Addressable 1 0.0% 696 696 696
|
||||
30617 Addressable 1 0.0% 1089 1089 1089
|
||||
22234 Ephemeral 1 0.0% 443 443 443
|
||||
30815 Addressable 1 0.0% 37534 37534 37534
|
||||
1078 Unknown 1 0.0% 13939 13939 13939
|
||||
39050 Addressable 1 0.0% 1843 1843 1843
|
||||
22281 Ephemeral 1 0.0% 443 443 443
|
||||
30166 Addressable 1 0.0% 808 808 808
|
||||
22772 Ephemeral 1 0.0% 429 429 429
|
||||
22356 Ephemeral 1 0.0% 443 443 443
|
||||
30554 Addressable 1 0.0% 609 609 609
|
||||
38422 Addressable 1 0.0% 20025 20025 20025
|
||||
38000 Addressable 1 0.0% 562 562 562
|
||||
22069 Ephemeral 1 0.0% 443 443 443
|
||||
1050 Unknown 1 0.0% 437 437 437
|
||||
33051 Addressable 1 0.0% 522 522 522
|
||||
39036 Addressable 1 0.0% 1138 1138 1138
|
||||
23194 NWC request 1 0.0% 510 510 510
|
||||
30081 Addressable 1 0.0% 1370 1370 1370
|
||||
22299 Ephemeral 1 0.0% 443 443 443
|
||||
22556 Ephemeral 1 0.0% 427 427 427
|
||||
22302 Ephemeral 1 0.0% 443 443 443
|
||||
39019 Addressable 1 0.0% 961 961 961
|
||||
30000 Follow sets 1 0.0% 823 823 823
|
||||
38383 Addressable 1 0.0% 657 657 657
|
||||
30087 Addressable 1 0.0% 7325 7325 7325
|
||||
30090 Addressable 1 0.0% 1515 1515 1515
|
||||
|
||||
=== Raw Relay Response Log ===
|
||||
# Cache-All Feasibility Test - Raw Relay Log
|
||||
# Started: Sun Aug 2 09:48:55 2026
|
||||
# Config: cache_all_test_config.jsonc
|
||||
# Duration: 120 seconds
|
||||
[2026-08-02 09:49:03] [RELAY] wss://relay.primal.net CONNECTED
|
||||
[2026-08-02 09:49:03] [RELAY] wss://nos.lol CONNECTED
|
||||
[2026-08-02 09:49:03] [RELAY] wss://relay.damus.io CONNECTED
|
||||
[2026-08-02 09:49:03] [RELAY] wss://relay.primal.net EOSE
|
||||
|
||||
@@ -0,0 +1,51 @@
|
||||
=== Cache-All Feasibility Test Report ===
|
||||
Duration: 0h 0m 0s
|
||||
Config: cache_all_test_config.jsonc
|
||||
|
||||
=== Global Summary ===
|
||||
Total events: 0
|
||||
Total bytes: 0 (0.00 MB)
|
||||
Avg event size: 0 bytes
|
||||
Max event: 0 bytes (kind 0)
|
||||
Unique pubkeys: 0
|
||||
Relays contacted: 27
|
||||
|
||||
=== Relay Summary ===
|
||||
Relay Events EOSE CLOSED NOTICE Err Disc Status
|
||||
wss://relay.primal.net 0 0 0 0 0 0 DOWN
|
||||
wss://nos.lol 0 0 0 0 0 0 DOWN
|
||||
wss://relay.damus.io 0 0 0 0 0 0 DOWN
|
||||
wss://relay.ditto.pub 0 0 0 0 0 0 DOWN
|
||||
wss://nostr.land 0 0 0 0 0 0 DOWN
|
||||
wss://nostr.wine 0 0 0 0 0 0 DOWN
|
||||
wss://nostr.oxtr.dev 0 0 0 0 0 0 DOWN
|
||||
wss://spatia-arcana.com/inbox 0 0 0 0 0 0 DOWN
|
||||
wss://eden.nostr.land 0 0 0 0 0 0 DOWN
|
||||
wss://relay.nostr.band 0 0 0 0 0 0 DOWN
|
||||
wss://theforest.nostr1.com 0 0 0 0 0 0 DOWN
|
||||
wss://wot.utxo.one 0 0 0 0 0 0 DOWN
|
||||
wss://premium.primal.net 0 0 0 0 0 0 DOWN
|
||||
wss://nostr.mom 0 0 0 0 0 0 DOWN
|
||||
wss://relay.mostr.pub 0 0 0 0 0 0 DOWN
|
||||
wss://offchain.pub 0 0 0 0 0 0 DOWN
|
||||
wss://relay.divine.video 0 0 0 0 0 0 DOWN
|
||||
wss://relay.nostrplebs.com 0 0 0 0 0 0 DOWN
|
||||
wss://nostr-pub.wellorder.net 0 0 0 0 0 0 DOWN
|
||||
wss://devrelay.azzamo.net 0 0 0 0 0 0 DOWN
|
||||
wss://relay.noderunners.network 0 0 0 0 0 0 DOWN
|
||||
wss://nostr-pub.semisol.dev 0 0 0 0 0 0 DOWN
|
||||
wss://relay.shosho.live 0 0 0 0 0 0 DOWN
|
||||
wss://relay.nostrcheck.me 0 0 0 0 0 0 DOWN
|
||||
wss://relay.nostr.info 0 0 0 0 0 0 DOWN
|
||||
wss://relay.momostr.pink 0 0 0 0 0 0 DOWN
|
||||
wss://bitsat.molonlabe.holdings 0 0 0 0 0 0 DOWN
|
||||
|
||||
=== Kind Distribution ===
|
||||
Kind Name Count % Total Bytes Avg Max
|
||||
|
||||
=== Raw Relay Response Log ===
|
||||
# Cache-All Feasibility Test - Raw Relay Log
|
||||
# Started: Sun Aug 2 10:01:51 2026
|
||||
# Config: cache_all_test_config.jsonc
|
||||
# Duration: 300 seconds
|
||||
|
||||
@@ -0,0 +1,39 @@
|
||||
=== Cache-All Feasibility Test Report ===
|
||||
Duration: 0h 0m 0s
|
||||
Config: cache_all_test_config.jsonc
|
||||
|
||||
=== Global Summary ===
|
||||
Total events: 0
|
||||
Total bytes: 0 (0.00 MB)
|
||||
Avg event size: 0 bytes
|
||||
Max event: 0 bytes (kind 0)
|
||||
Unique pubkeys: 0
|
||||
Relays contacted: 15
|
||||
|
||||
=== Relay Summary ===
|
||||
Relay Events EOSE CLOSED NOTICE Err Disc Status
|
||||
wss://relay.primal.net 0 0 0 0 0 0 DOWN
|
||||
wss://nos.lol 0 0 0 0 0 0 DOWN
|
||||
wss://relay.damus.io 0 0 0 0 0 0 DOWN
|
||||
wss://nostr.land 0 0 0 0 0 0 DOWN
|
||||
wss://relay.ditto.pub 0 0 0 0 0 0 DOWN
|
||||
wss://nostr.oxtr.dev 0 0 0 0 0 0 DOWN
|
||||
wss://pyramid.fiatjaf.com/inbox 0 0 0 0 0 0 DOWN
|
||||
wss://relay.mostr.pub 0 0 0 0 0 0 DOWN
|
||||
wss://relay.divine.video 0 0 0 0 0 0 DOWN
|
||||
wss://nostr.wine 0 0 0 0 0 0 DOWN
|
||||
wss://theforest.nostr1.com 0 0 0 0 0 0 DOWN
|
||||
wss://relay.nostrplebs.com 0 0 0 0 0 0 DOWN
|
||||
wss://relay.shosho.live 0 0 0 0 0 0 DOWN
|
||||
wss://relay.nostr.band 0 0 0 0 0 0 DOWN
|
||||
wss://relay.nostr.info 0 0 0 0 0 0 DOWN
|
||||
|
||||
=== Kind Distribution ===
|
||||
Kind Name Count % Total Bytes Avg Max
|
||||
|
||||
=== Raw Relay Response Log ===
|
||||
# Cache-All Feasibility Test - Raw Relay Log
|
||||
# Started: Sun Aug 2 10:10:55 2026
|
||||
# Config: cache_all_test_config.jsonc
|
||||
# Duration: 300 seconds
|
||||
|
||||
@@ -0,0 +1,35 @@
|
||||
=== Cache-All Feasibility Test Report ===
|
||||
Duration: 0h 0m 0s
|
||||
Config: cache_all_test_config.jsonc
|
||||
|
||||
=== Global Summary ===
|
||||
Total events: 0
|
||||
Total bytes: 0 (0.00 MB)
|
||||
Avg event size: 0 bytes
|
||||
Max event: 0 bytes (kind 0)
|
||||
Unique pubkeys: 0
|
||||
Relays contacted: 11
|
||||
|
||||
=== Relay Summary ===
|
||||
Relay Events EOSE CLOSED NOTICE Err Disc Status
|
||||
wss://relay.primal.net 0 0 0 0 0 0 DOWN
|
||||
wss://nos.lol 0 0 0 0 0 0 DOWN
|
||||
wss://relay.damus.io 0 0 0 0 0 0 DOWN
|
||||
wss://relay.ditto.pub 0 0 0 0 0 0 DOWN
|
||||
wss://nostr.bitcoiner.social 0 0 0 0 0 0 DOWN
|
||||
wss://nostr.land 0 0 0 0 0 0 DOWN
|
||||
wss://pyramid.fiatjaf.com/inbox 0 0 0 0 0 0 DOWN
|
||||
wss://relay.divine.video 0 0 0 0 0 0 DOWN
|
||||
wss://relay.nostrplebs.com 0 0 0 0 0 0 DOWN
|
||||
wss://eden.nostr.land 0 0 0 0 0 0 DOWN
|
||||
wss://relay.shosho.live 0 0 0 0 0 0 DOWN
|
||||
|
||||
=== Kind Distribution ===
|
||||
Kind Name Count % Total Bytes Avg Max
|
||||
|
||||
=== Raw Relay Response Log ===
|
||||
# Cache-All Feasibility Test - Raw Relay Log
|
||||
# Started: Sun Aug 2 10:17:20 2026
|
||||
# Config: cache_all_test_config.jsonc
|
||||
# Duration: 30 seconds
|
||||
|
||||
@@ -0,0 +1,197 @@
|
||||
=== Cache-All Feasibility Test Report ===
|
||||
Duration: 0h 1m 54s
|
||||
|
||||
=== Global Summary ===
|
||||
Total events: 4719
|
||||
Total bytes: 6608416 (6.30 MB)
|
||||
Avg event size: 1400 bytes
|
||||
Max event: 44372 bytes (kind 30089)
|
||||
Unique pubkeys: 1333
|
||||
Relays: 15
|
||||
|
||||
=== Relay Summary ===
|
||||
Relay Events EOSE CLOSED NOTICE Err Disc Status
|
||||
wss://laantungir.net 0 0 0 0 0 0 DOWN
|
||||
wss://nos.lol 804 0 0 0 0 3 OK
|
||||
wss://nostr-pub.wellorder.net 83 0 0 0 0 0 OK
|
||||
wss://nostr.mom 175 0 0 0 0 0 OK
|
||||
wss://nostr.oxtr.dev 108 0 0 0 0 0 OK
|
||||
wss://offchain.pub 627 0 0 0 0 0 OK
|
||||
wss://premium.primal.net 1 0 0 0 0 0 OK
|
||||
wss://relay.damus.io 0 0 0 0 0 0 DOWN
|
||||
wss://relay.ditto.pub 721 0 0 0 0 0 OK
|
||||
wss://relay.divine.video 3 0 0 0 0 0 OK
|
||||
wss://relay.momostr.pink 86 0 0 0 0 0 OK
|
||||
wss://relay.mostr.pub 836 0 0 0 0 0 OK
|
||||
wss://relay.nostrplebs.com 4 0 0 0 0 0 OK
|
||||
wss://relay.primal.net 1239 0 0 0 0 0 OK
|
||||
wss://theforest.nostr1.com 32 0 0 0 0 0 OK
|
||||
|
||||
=== Kind Distribution ===
|
||||
Kind Name Count % Total Bytes Avg Max
|
||||
21059 Gift wrap (NIP-59) 675 14.3% 2192938 3249 5314
|
||||
30382 Addressable 563 11.9% 255591 454 498
|
||||
5 Deletion 341 7.2% 153667 451 1404
|
||||
22639 Ephemeral 231 4.9% 178011 771 1230
|
||||
22551 Ephemeral 182 3.9% 78260 430 430
|
||||
20001 Ephemeral 143 3.0% 70427 492 1206
|
||||
30078 App data 141 3.0% 1361122 9653 44169
|
||||
0 Profile metadata 135 2.9% 119793 887 3483
|
||||
22734 Ephemeral 122 2.6% 52094 427 427
|
||||
24747 Ephemeral 101 2.1% 59352 588 594
|
||||
1 Text note 90 1.9% 92140 1024 4709
|
||||
22668 Ephemeral 88 1.9% 37752 429 429
|
||||
22850 Ephemeral 83 1.8% 35690 430 430
|
||||
22870 Ephemeral 76 1.6% 77061 1014 2202
|
||||
22951 Ephemeral 75 1.6% 77282 1030 2204
|
||||
10002 Relay list 75 1.6% 202196 2696 42385
|
||||
22912 Ephemeral 74 1.6% 31672 428 428
|
||||
38501 Addressable 65 1.4% 48152 741 744
|
||||
24133 Ephemeral 63 1.3% 72262 1147 2898
|
||||
6 Repost 50 1.1% 40985 820 3346
|
||||
37195 Addressable 48 1.0% 36225 755 771
|
||||
21050 Ephemeral 48 1.0% 46800 975 2558
|
||||
4515 Unknown 46 1.0% 81638 1775 6028
|
||||
25555 Ephemeral 45 1.0% 209551 4657 16603
|
||||
7 Reaction 40 0.8% 22486 562 805
|
||||
22917 Ephemeral 39 0.8% 35435 909 1166
|
||||
22699 Ephemeral 39 0.8% 26723 685 1166
|
||||
22690 Ephemeral 39 0.8% 16770 430 430
|
||||
22918 Ephemeral 38 0.8% 36470 960 1507
|
||||
22832 Ephemeral 37 0.8% 16128 436 446
|
||||
25050 Ephemeral 35 0.7% 15507 443 465
|
||||
30383 Addressable 35 0.7% 18766 536 541
|
||||
22713 Ephemeral 34 0.7% 14570 429 430
|
||||
22698 Ephemeral 34 0.7% 31371 923 1674
|
||||
22601 Ephemeral 28 0.6% 11984 428 428
|
||||
22655 Ephemeral 28 0.6% 11984 428 428
|
||||
1059 Gift wrap seal 23 0.5% 46912 2040 5285
|
||||
22751 Ephemeral 21 0.4% 8946 426 426
|
||||
22676 Ephemeral 21 0.4% 8967 427 427
|
||||
29333 Ephemeral 20 0.4% 9840 492 492
|
||||
5300 Unknown 20 0.4% 11959 598 630
|
||||
22743 Ephemeral 19 0.4% 8132 428 428
|
||||
22603 Ephemeral 19 0.4% 8094 426 426
|
||||
22693 Ephemeral 19 0.4% 8113 427 427
|
||||
22774 Ephemeral 19 0.4% 8132 428 428
|
||||
22808 Ephemeral 19 0.4% 8151 429 429
|
||||
22575 Ephemeral 19 0.4% 8075 425 425
|
||||
23003 Ephemeral 19 0.4% 8132 428 428
|
||||
22949 Ephemeral 19 0.4% 8151 429 429
|
||||
23334 Ephemeral 19 0.4% 8189 431 431
|
||||
24242 Ephemeral 17 0.4% 9843 579 579
|
||||
22816 Ephemeral 16 0.3% 6864 429 429
|
||||
20787 Ephemeral 16 0.3% 25100 1569 2478
|
||||
13194 NWC info 15 0.3% 7574 505 514
|
||||
38502 Addressable 14 0.3% 5390 385 385
|
||||
22236 Ephemeral 14 0.3% 11214 801 814
|
||||
22613 Ephemeral 13 0.3% 8977 691 694
|
||||
30088 Addressable 12 0.3% 22340 1862 1871
|
||||
22484 Ephemeral 12 0.3% 10948 912 1165
|
||||
30091 Addressable 12 0.3% 7385 615 629
|
||||
20004 Ephemeral 11 0.2% 5643 513 549
|
||||
31990 App handler info 11 0.2% 8711 792 1465
|
||||
445 Encrypted group msg 10 0.2% 17972 1797 4126
|
||||
22795 Ephemeral 9 0.2% 3861 429 429
|
||||
22507 Ephemeral 9 0.2% 8480 942 1165
|
||||
22922 Ephemeral 9 0.2% 3870 430 430
|
||||
24421 Ephemeral 9 0.2% 4644 516 516
|
||||
22830 Ephemeral 9 0.2% 7317 813 1168
|
||||
20000 Ephemeral 9 0.2% 3854 428 484
|
||||
22955 Ephemeral 9 0.2% 3852 428 428
|
||||
22793 Ephemeral 9 0.2% 3843 427 427
|
||||
30315 User status 8 0.2% 4604 576 926
|
||||
20387 Ephemeral 8 0.2% 4112 514 514
|
||||
7368 Unknown 8 0.2% 8309 1039 1041
|
||||
4004 Unknown 8 0.2% 9352 1169 1169
|
||||
443 Unknown 8 0.2% 8928 1116 1116
|
||||
11998 Unknown 7 0.1% 3255 465 465
|
||||
10100 Unknown 7 0.1% 11851 1693 3825
|
||||
22456 Ephemeral 7 0.1% 3290 470 470
|
||||
30089 Chunked data 7 0.1% 157322 22475 44372
|
||||
22737 Ephemeral 7 0.1% 4669 667 707
|
||||
23337 Ephemeral 7 0.1% 3557 508 509
|
||||
30515 Addressable 7 0.1% 18032 2576 2576
|
||||
30311 Addressable 6 0.1% 5818 970 1197
|
||||
1985 Unknown 6 0.1% 2860 477 482
|
||||
22859 Ephemeral 5 0.1% 8606 1721 2195
|
||||
4 Encrypted DM 5 0.1% 3222 644 722
|
||||
10011 Unknown 5 0.1% 2027 405 431
|
||||
22764 Ephemeral 4 0.1% 1712 428 428
|
||||
22777 Ephemeral 4 0.1% 2790 698 698
|
||||
4244 Unknown 4 0.1% 2256 564 564
|
||||
30023 Long-form article 4 0.1% 22789 5697 6817
|
||||
9735 Zap receipt 4 0.1% 7033 1758 1805
|
||||
20333 Ephemeral 4 0.1% 3188 797 798
|
||||
3 Follow list 3 0.1% 26232 8744 14166
|
||||
38503 Addressable 3 0.1% 1655 552 552
|
||||
10050 DM relays 3 0.1% 1411 470 511
|
||||
21617 Ephemeral 3 0.1% 1485 495 495
|
||||
1984 Report 3 0.1% 1986 662 662
|
||||
3927 Unknown 3 0.1% 1599 533 533
|
||||
3434 Unknown 3 0.1% 1907 636 665
|
||||
22514 Ephemeral 2 0.0% 856 428 428
|
||||
33334 Addressable 2 0.0% 1662 831 831
|
||||
38500 Addressable 2 0.0% 1424 712 713
|
||||
22526 Ephemeral 2 0.0% 860 430 430
|
||||
30380 Addressable 2 0.0% 908 454 454
|
||||
23194 NWC request 2 0.0% 1020 510 510
|
||||
23042 Ephemeral 2 0.0% 858 429 429
|
||||
38385 Addressable 2 0.0% 2692 1346 1478
|
||||
30443 Addressable 2 0.0% 2369 1184 1219
|
||||
22747 Ephemeral 2 0.0% 2064 1032 1288
|
||||
4245 Unknown 2 0.0% 888 444 444
|
||||
1111 Comment 2 0.0% 1936 968 981
|
||||
38383 Addressable 2 0.0% 1439 720 720
|
||||
4243 Unknown 2 0.0% 1128 564 564
|
||||
38225 Addressable 1 0.0% 978 978 978
|
||||
30618 Addressable 1 0.0% 733 733 733
|
||||
31510 Addressable 1 0.0% 981 981 981
|
||||
30617 Addressable 1 0.0% 1089 1089 1089
|
||||
1077 Unknown 1 0.0% 607 607 607
|
||||
20201 Ephemeral 1 0.0% 491 491 491
|
||||
20200 Ephemeral 1 0.0% 491 491 491
|
||||
1078 Unknown 1 0.0% 14173 14173 14173
|
||||
6300 Unknown 1 0.0% 3698 3698 3698
|
||||
11316 Unknown 1 0.0% 791 791 791
|
||||
11317 Unknown 1 0.0% 2873 2873 2873
|
||||
17 Unknown 1 0.0% 610 610 610
|
||||
23059 Ephemeral 1 0.0% 429 429 429
|
||||
22806 Ephemeral 1 0.0% 1520 1520 1520
|
||||
22120 Ephemeral 1 0.0% 1127 1127 1127
|
||||
13196 Unknown 1 0.0% 656 656 656
|
||||
24913 Ephemeral 1 0.0% 431 431 431
|
||||
12222 Unknown 1 0.0% 579 579 579
|
||||
1040 Unknown 1 0.0% 1048 1048 1048
|
||||
22119 Ephemeral 1 0.0% 845 845 845
|
||||
10312 Unknown 1 0.0% 472 472 472
|
||||
3079 Unknown 1 0.0% 909 909 909
|
||||
30000 Addressable 1 0.0% 594 594 594
|
||||
|
||||
=== Raw Relay Response Log ===
|
||||
# Cache-All Feasibility Test - Raw Relay Log
|
||||
# Started: Sun Aug 2 10:25:47 2026
|
||||
# Config: cache_all_test_config.jsonc
|
||||
# Duration: 120 seconds
|
||||
[2026-08-02 10:26:23] [RELAY] wss://laantungir.net STATUS: ?
|
||||
[2026-08-02 10:26:23] [RELAY] wss://nos.lol STATUS: connected
|
||||
[2026-08-02 10:26:23] [RELAY] wss://nostr-pub.wellorder.net STATUS: connected
|
||||
[2026-08-02 10:26:23] [RELAY] wss://nostr.mom STATUS: connected
|
||||
[2026-08-02 10:26:23] [RELAY] wss://nostr.oxtr.dev STATUS: connected
|
||||
[2026-08-02 10:26:23] [RELAY] wss://offchain.pub STATUS: connected
|
||||
[2026-08-02 10:26:23] [RELAY] wss://premium.primal.net STATUS: connected
|
||||
[2026-08-02 10:26:23] [RELAY] wss://relay.damus.io STATUS: ?
|
||||
[2026-08-02 10:26:23] [RELAY] wss://relay.ditto.pub STATUS: connected
|
||||
[2026-08-02 10:26:23] [RELAY] wss://relay.divine.video STATUS: connected
|
||||
[2026-08-02 10:26:23] [RELAY] wss://relay.momostr.pink STATUS: connected
|
||||
[2026-08-02 10:26:23] [RELAY] wss://relay.mostr.pub STATUS: connected
|
||||
[2026-08-02 10:26:23] [RELAY] wss://relay.nostrplebs.com STATUS: connected
|
||||
[2026-08-02 10:26:23] [RELAY] wss://relay.primal.net STATUS: connected
|
||||
[2026-08-02 10:26:23] [RELAY] wss://theforest.nostr1.com STATUS: connected
|
||||
[2026-08-02 10:26:59] [RELAY] wss://nos.lol DISCONNECTED:
|
||||
[2026-08-02 10:26:59] [RELAY] wss://nos.lol CONNECTED
|
||||
[2026-08-02 10:27:59] [RELAY] wss://nos.lol DISCONNECTED:
|
||||
[2026-08-02 10:27:59] [RELAY] wss://nos.lol CONNECTED
|
||||
[2026-08-02 10:28:09] [RELAY] wss://nos.lol DISCONNECTED: Connection state transitioned to 2 during poll
|
||||
[2026-08-02 10:28:10] [RELAY] wss://nos.lol CONNECTED
|
||||
|
||||
@@ -0,0 +1,257 @@
|
||||
=== Cache-All Feasibility Test Report ===
|
||||
Duration: 0h 5m 0s
|
||||
Config: cache_all_test_config.jsonc
|
||||
|
||||
=== Global Summary ===
|
||||
Total events: 14714
|
||||
Total bytes: 20163747 (19.23 MB)
|
||||
Avg event size: 1370 bytes
|
||||
Max event: 51791 bytes (kind 30078)
|
||||
Unique pubkeys: 3435
|
||||
Relays contacted: 24
|
||||
|
||||
=== Relay Summary ===
|
||||
Relay Events EOSE CLOSED NOTICE Err Disc Status
|
||||
wss://relay.primal.net 2820 0 0 0 0 2 OK
|
||||
wss://nos.lol 2964 0 0 0 0 3 OK
|
||||
wss://relay.damus.io 1999 0 0 0 0 0 OK
|
||||
wss://relay.ditto.pub 2049 0 0 0 0 0 OK
|
||||
wss://nostr.land 0 0 0 0 0 0 DOWN
|
||||
wss://nostr.wine 0 0 0 0 0 0 DOWN
|
||||
wss://nostr.oxtr.dev 599 0 0 0 0 1 OK
|
||||
wss://spatia-arcana.com/inbox 0 0 0 0 0 0 DOWN
|
||||
wss://nostrelites.org 0 0 0 0 0 0 DOWN
|
||||
wss://offchain.pub 1431 0 0 0 0 0 OK
|
||||
wss://relay.nostr.band 0 0 0 0 0 0 DOWN
|
||||
wss://premium.primal.net 7 0 0 0 0 0 OK
|
||||
wss://nostr.mom 412 0 0 0 0 0 OK
|
||||
wss://relay.mostr.pub 2134 0 0 0 0 1 OK
|
||||
wss://relay.divine.video 14 0 0 0 0 0 OK
|
||||
wss://relay.nostrplebs.com 4 0 0 0 0 0 OK
|
||||
wss://eden.nostr.land 0 0 0 0 0 0 DOWN
|
||||
wss://theforest.nostr1.com 67 0 0 0 0 0 OK
|
||||
wss://nostr-pub.wellorder.net 214 0 0 0 0 0 OK
|
||||
wss://devrelay.azzamo.net 0 0 0 0 0 0 DOWN
|
||||
wss://relay.noderunners.network 0 0 0 0 0 0 OK
|
||||
wss://relay.shosho.live 0 0 0 0 0 0 DOWN
|
||||
wss://relay.nostrcheck.me 0 0 0 0 0 0 DOWN
|
||||
wss://basspistol.org 0 0 0 0 0 0 DOWN
|
||||
|
||||
=== Kind Distribution ===
|
||||
Kind Name Count % Total Bytes Avg Max
|
||||
21059 Gift wrap (NIP-59) 2477 16.8% 8220486 3319 19622
|
||||
30382 Addressable 1558 10.6% 708564 455 498
|
||||
5 Deletion 1219 8.3% 542263 445 1404
|
||||
22639 Ephemeral 607 4.1% 467729 771 1230
|
||||
20001 Ephemeral (key xchg) 519 3.5% 251716 485 1431
|
||||
22551 Ephemeral 479 3.3% 205970 430 430
|
||||
30078 App data 432 2.9% 3024405 7001 51791
|
||||
24747 Ephemeral 317 2.2% 188378 594 650
|
||||
22734 Ephemeral 315 2.1% 134505 427 427
|
||||
22668 Ephemeral 307 2.1% 131703 429 429
|
||||
1 Text note 307 2.1% 270378 881 3665
|
||||
0 Profile metadata 300 2.0% 260832 869 9187
|
||||
22850 Ephemeral 242 1.6% 104060 430 430
|
||||
38501 App data (btc) 241 1.6% 178603 741 744
|
||||
22912 Ephemeral 238 1.6% 101864 428 428
|
||||
4515 Unknown 225 1.5% 376537 1673 6028
|
||||
10002 Relay list 211 1.4% 309808 1468 42385
|
||||
24133 Ephemeral 193 1.3% 237962 1233 14162
|
||||
22951 Ephemeral 179 1.2% 170939 955 2204
|
||||
22870 Ephemeral 172 1.2% 165571 963 2202
|
||||
25555 Ephemeral 157 1.1% 776467 4946 16603
|
||||
37195 Addressable 142 1.0% 107593 758 869
|
||||
21050 Ephemeral 141 1.0% 136906 971 2558
|
||||
6 Repost 139 0.9% 113883 819 4053
|
||||
7 Reaction 116 0.8% 65547 565 786
|
||||
22832 Ephemeral 112 0.8% 48745 435 446
|
||||
22690 Ephemeral 109 0.7% 46870 430 430
|
||||
30383 Addressable 100 0.7% 53571 536 543
|
||||
22713 Ephemeral 98 0.7% 41994 429 430
|
||||
22601 Ephemeral 93 0.6% 39804 428 428
|
||||
25050 Ephemeral 87 0.6% 38343 441 465
|
||||
1059 Gift wrap seal 84 0.6% 158090 1882 5285
|
||||
22699 Ephemeral 83 0.6% 55625 670 1872
|
||||
22655 Ephemeral 80 0.5% 34240 428 428
|
||||
22917 Ephemeral 75 0.5% 67279 897 1166
|
||||
22676 Ephemeral 72 0.5% 30744 427 427
|
||||
29333 Ephemeral 70 0.5% 34440 492 492
|
||||
22918 Ephemeral 67 0.5% 65746 981 1876
|
||||
20787 Ephemeral 62 0.4% 84460 1362 2478
|
||||
22456 Ephemeral 61 0.4% 29310 480 790
|
||||
22808 Ephemeral 59 0.4% 25296 429 429
|
||||
24242 Ephemeral 57 0.4% 33003 579 579
|
||||
22816 Ephemeral 56 0.4% 24024 429 429
|
||||
22603 Ephemeral 55 0.4% 23430 426 426
|
||||
22743 Ephemeral 55 0.4% 23540 428 428
|
||||
22693 Ephemeral 54 0.4% 23058 427 427
|
||||
22575 Ephemeral 54 0.4% 22950 425 425
|
||||
23334 Ephemeral 53 0.4% 22843 431 431
|
||||
13194 NWC info 52 0.4% 26592 511 514
|
||||
22751 Ephemeral 51 0.3% 21726 426 426
|
||||
22949 Ephemeral 50 0.3% 21450 429 429
|
||||
11998 Unknown 50 0.3% 23202 464 465
|
||||
24421 Ephemeral 48 0.3% 24795 517 525
|
||||
22236 Ephemeral 47 0.3% 37103 789 814
|
||||
22484 Ephemeral 47 0.3% 42919 913 1165
|
||||
3927 Unknown 45 0.3% 23985 533 533
|
||||
23003 Ephemeral 45 0.3% 19260 428 428
|
||||
22774 Ephemeral 45 0.3% 19260 428 428
|
||||
31990 App handler info 44 0.3% 40657 924 1465
|
||||
5300 Unknown 43 0.3% 25958 604 701
|
||||
20387 Ephemeral 40 0.3% 20560 514 514
|
||||
20000 Ephemeral 38 0.3% 15672 412 487
|
||||
38502 Addressable 38 0.3% 14630 385 385
|
||||
22507 Ephemeral 38 0.3% 34749 914 1167
|
||||
445 Encrypted group msg 37 0.3% 62402 1687 4130
|
||||
22698 Ephemeral 34 0.2% 31371 923 1674
|
||||
4 Encrypted DM 33 0.2% 44743 1356 17018
|
||||
30315 User status 31 0.2% 20374 657 1166
|
||||
1985 Label 31 0.2% 28905 932 4831
|
||||
22859 Ephemeral 31 0.2% 30700 990 2195
|
||||
22613 Ephemeral 31 0.2% 21415 691 694
|
||||
20004 Ephemeral 29 0.2% 15525 535 549
|
||||
7368 Unknown 27 0.2% 28042 1039 1041
|
||||
30091 Addressable 27 0.2% 16620 616 629
|
||||
30088 Addressable 27 0.2% 50292 1863 1871
|
||||
22598 Ephemeral 27 0.2% 23198 859 1162
|
||||
22955 Ephemeral 25 0.2% 10700 428 428
|
||||
4004 Unknown 25 0.2% 29225 1169 1169
|
||||
22793 Ephemeral 25 0.2% 10675 427 427
|
||||
22922 Ephemeral 25 0.2% 10750 430 430
|
||||
22795 Ephemeral 25 0.2% 10725 429 429
|
||||
10100 Unknown 24 0.2% 39530 1647 3825
|
||||
22764 Ephemeral 22 0.1% 9416 428 428
|
||||
30089 Chunked data 18 0.1% 260436 14469 44372
|
||||
30311 Addressable 18 0.1% 18058 1003 1197
|
||||
20333 Ephemeral 18 0.1% 14340 797 798
|
||||
443 Unknown 18 0.1% 20088 1116 1116
|
||||
38383 Addressable 18 0.1% 13557 753 972
|
||||
22777 Ephemeral 16 0.1% 12435 777 1159
|
||||
30023 Long-form article 16 0.1% 92998 5812 8050
|
||||
4244 Unknown 15 0.1% 8460 564 564
|
||||
30515 Addressable 14 0.1% 36064 2576 2576
|
||||
22967 Ephemeral 13 0.1% 5603 431 431
|
||||
10011 Unknown 13 0.1% 5283 406 431
|
||||
3 Follow list 12 0.1% 97388 8116 24970
|
||||
38503 Addressable 12 0.1% 6624 552 553
|
||||
1077 Unknown 12 0.1% 7284 607 607
|
||||
22550 Ephemeral 12 0.1% 5112 426 426
|
||||
9735 Zap receipt 12 0.1% 21551 1796 1963
|
||||
22591 Ephemeral 11 0.1% 4686 426 426
|
||||
22830 Ephemeral 11 0.1% 8707 792 1168
|
||||
23337 Ephemeral 11 0.1% 5589 508 509
|
||||
38385 Addressable 9 0.1% 12290 1366 1478
|
||||
10050 DM relays 9 0.1% 4160 462 511
|
||||
39101 Addressable 8 0.1% 4264 533 533
|
||||
31510 Addressable 8 0.1% 7834 979 982
|
||||
1111 Comment 8 0.1% 9909 1239 1706
|
||||
1002 Unknown 7 0.0% 6647 950 1009
|
||||
22737 Ephemeral 7 0.0% 4669 667 707
|
||||
33334 Addressable 6 0.0% 4986 831 831
|
||||
38384 Addressable 6 0.0% 4458 743 743
|
||||
20384 Ephemeral 6 0.0% 3834 639 639
|
||||
22526 Ephemeral 6 0.0% 2580 430 430
|
||||
30443 Addressable 6 0.0% 7288 1215 1260
|
||||
3434 Unknown 6 0.0% 3902 650 665
|
||||
21617 Ephemeral 6 0.0% 2970 495 495
|
||||
38500 Addressable 6 0.0% 4272 712 713
|
||||
30380 Addressable 6 0.0% 2724 454 454
|
||||
22514 Ephemeral 5 0.0% 2140 428 428
|
||||
4245 Unknown 5 0.0% 2220 444 444
|
||||
4243 Unknown 5 0.0% 2820 564 564
|
||||
6300 Unknown 5 0.0% 19347 3869 4596
|
||||
30000 Follow sets 5 0.0% 3005 601 823
|
||||
22611 Ephemeral 5 0.0% 2130 426 426
|
||||
38225 Addressable 5 0.0% 4929 986 993
|
||||
23042 Ephemeral 5 0.0% 2145 429 429
|
||||
14 Unknown 4 0.0% 5446 1362 1550
|
||||
23059 Ephemeral 4 0.0% 2853 713 1162
|
||||
3079 Unknown 4 0.0% 3636 909 909
|
||||
1984 Report 4 0.0% 2648 662 662
|
||||
23194 NWC request 4 0.0% 2040 510 510
|
||||
21060 Ephemeral 4 0.0% 2280 570 570
|
||||
30080 Addressable 4 0.0% 3763 941 986
|
||||
31234 Addressable 4 0.0% 4512 1128 1856
|
||||
10003 Bookmarks 3 0.0% 10518 3506 3506
|
||||
1632 Unknown 3 0.0% 2187 729 729
|
||||
22120 Ephemeral 3 0.0% 3229 1076 1127
|
||||
1000 Unknown 3 0.0% 5178 1726 1734
|
||||
22119 Ephemeral 3 0.0% 2537 846 846
|
||||
11317 Unknown 2 0.0% 5746 2873 2873
|
||||
11316 Unknown 2 0.0% 1582 791 791
|
||||
30617 Addressable 2 0.0% 2178 1089 1089
|
||||
30618 Addressable 2 0.0% 1466 733 733
|
||||
17 External reaction 2 0.0% 1220 610 610
|
||||
31991 Addressable 2 0.0% 922 461 461
|
||||
24913 Ephemeral 2 0.0% 862 431 431
|
||||
31985 Addressable 2 0.0% 1267 634 667
|
||||
1060 Gift wrap (alt) 2 0.0% 2268 1134 1134
|
||||
22806 Ephemeral 2 0.0% 3040 1520 1520
|
||||
31339 Addressable 2 0.0% 2940 1470 1470
|
||||
30090 Addressable 2 0.0% 3030 1515 1515
|
||||
10000 Mute list 2 0.0% 1963 982 1034
|
||||
30087 Addressable 2 0.0% 14650 7325 7325
|
||||
10312 Unknown 2 0.0% 963 482 491
|
||||
30815 Addressable 2 0.0% 75068 37534 37534
|
||||
20200 Ephemeral 2 0.0% 982 491 491
|
||||
20201 Ephemeral 2 0.0% 982 491 491
|
||||
22747 Ephemeral 2 0.0% 2064 1032 1288
|
||||
30787 Addressable 1 0.0% 1370 1370 1370
|
||||
1078 Unknown 1 0.0% 14173 14173 14173
|
||||
13196 Unknown 1 0.0% 656 656 656
|
||||
7403 Unknown 1 0.0% 491 491 491
|
||||
15129 Unknown 1 0.0% 455 455 455
|
||||
12222 Unknown 1 0.0% 579 579 579
|
||||
10030 Emoji list 1 0.0% 405 405 405
|
||||
38111 Addressable 1 0.0% 748 748 748
|
||||
15750 Unknown 1 0.0% 616 616 616
|
||||
30421 Addressable 1 0.0% 995 995 995
|
||||
33333 Addressable 1 0.0% 2346 2346 2346
|
||||
30079 Addressable 1 0.0% 875 875 875
|
||||
39019 Addressable 1 0.0% 961 961 961
|
||||
39015 Addressable 1 0.0% 696 696 696
|
||||
5555 Unknown 1 0.0% 732 732 732
|
||||
34235 Addressable 1 0.0% 1071 1071 1071
|
||||
1040 Unknown 1 0.0% 1048 1048 1048
|
||||
31000 Addressable 1 0.0% 616 616 616
|
||||
10063 Unknown 1 0.0% 627 627 627
|
||||
30554 Addressable 1 0.0% 609 609 609
|
||||
25195 Ephemeral 1 0.0% 678 678 678
|
||||
25196 Ephemeral 1 0.0% 1362 1362 1362
|
||||
30213 Addressable 1 0.0% 632 632 632
|
||||
|
||||
=== Raw Relay Response Log ===
|
||||
# Cache-All Feasibility Test - Raw Relay Log
|
||||
# Started: Sun Aug 2 10:18:44 2026
|
||||
# Config: cache_all_test_config.jsonc
|
||||
# Duration: 300 seconds
|
||||
[2026-08-02 10:25:43] [RELAY] wss://relay.primal.net CONNECTED
|
||||
[2026-08-02 10:25:43] [RELAY] wss://nos.lol CONNECTED
|
||||
[2026-08-02 10:25:43] [RELAY] wss://relay.damus.io CONNECTED
|
||||
[2026-08-02 10:25:43] [RELAY] wss://relay.ditto.pub CONNECTED
|
||||
[2026-08-02 10:25:43] [RELAY] wss://nostr.oxtr.dev CONNECTED
|
||||
[2026-08-02 10:25:43] [RELAY] wss://offchain.pub CONNECTED
|
||||
[2026-08-02 10:25:43] [RELAY] wss://premium.primal.net CONNECTED
|
||||
[2026-08-02 10:25:43] [RELAY] wss://nostr.mom CONNECTED
|
||||
[2026-08-02 10:25:43] [RELAY] wss://relay.mostr.pub CONNECTED
|
||||
[2026-08-02 10:25:43] [RELAY] wss://relay.divine.video CONNECTED
|
||||
[2026-08-02 10:25:43] [RELAY] wss://relay.nostrplebs.com CONNECTED
|
||||
[2026-08-02 10:25:43] [RELAY] wss://theforest.nostr1.com CONNECTED
|
||||
[2026-08-02 10:25:43] [RELAY] wss://nostr-pub.wellorder.net CONNECTED
|
||||
[2026-08-02 10:25:43] [RELAY] wss://relay.noderunners.network CONNECTED
|
||||
[2026-08-02 10:26:30] [RELAY] wss://relay.primal.net DISCONNECTED: Connection state transitioned to 2 during poll
|
||||
[2026-08-02 10:26:30] [RELAY] wss://relay.primal.net CONNECTED
|
||||
[2026-08-02 10:27:00] [RELAY] wss://nos.lol DISCONNECTED:
|
||||
[2026-08-02 10:27:00] [RELAY] wss://nos.lol CONNECTED
|
||||
[2026-08-02 10:28:30] [RELAY] wss://nos.lol DISCONNECTED:
|
||||
[2026-08-02 10:28:30] [RELAY] wss://nos.lol CONNECTED
|
||||
[2026-08-02 10:28:55] [RELAY] wss://relay.primal.net DISCONNECTED:
|
||||
[2026-08-02 10:28:55] [RELAY] wss://relay.primal.net CONNECTED
|
||||
[2026-08-02 10:29:49] [RELAY] wss://relay.mostr.pub DISCONNECTED: Connection state transitioned to 2 during poll
|
||||
[2026-08-02 10:29:50] [RELAY] wss://relay.mostr.pub CONNECTED
|
||||
[2026-08-02 10:29:50] [RELAY] wss://nostr.oxtr.dev DISCONNECTED: Connection state transitioned to 2 during poll
|
||||
[2026-08-02 10:29:51] [RELAY] wss://nostr.oxtr.dev CONNECTED
|
||||
[2026-08-02 10:30:00] [RELAY] wss://nos.lol DISCONNECTED:
|
||||
[2026-08-02 10:30:00] [RELAY] wss://nos.lol CONNECTED
|
||||
|
||||
@@ -0,0 +1,167 @@
|
||||
=== Cache-All Feasibility Test Report ===
|
||||
Duration: 0h 0m 32s
|
||||
|
||||
=== Global Summary ===
|
||||
Total events: 1485
|
||||
Total bytes: 1812166 (1.73 MB)
|
||||
Avg event size: 1220 bytes
|
||||
Max event: 44546 bytes (kind 31234)
|
||||
Unique pubkeys: 511
|
||||
Relays: 15
|
||||
|
||||
=== Relay Summary ===
|
||||
Relay Events EOSE CLOSED NOTICE Err Disc Status
|
||||
wss://laantungir.net 0 0 0 0 0 0 DOWN
|
||||
wss://nos.lol 247 0 0 0 0 0 OK
|
||||
wss://nostr-pub.wellorder.net 37 0 0 0 0 0 OK
|
||||
wss://nostr.mom 38 0 0 0 0 0 OK
|
||||
wss://nostr.oxtr.dev 36 0 0 0 0 0 OK
|
||||
wss://offchain.pub 113 0 0 0 0 0 OK
|
||||
wss://premium.primal.net 1 0 0 0 0 0 OK
|
||||
wss://relay.damus.io 194 0 0 0 0 0 OK
|
||||
wss://relay.ditto.pub 277 0 0 0 0 1 OK
|
||||
wss://relay.divine.video 2 0 0 0 0 0 OK
|
||||
wss://relay.momostr.pink 27 0 0 0 0 0 OK
|
||||
wss://relay.mostr.pub 148 0 0 0 0 0 OK
|
||||
wss://relay.nostrplebs.com 0 0 0 0 0 0 OK
|
||||
wss://relay.primal.net 360 0 0 0 0 0 OK
|
||||
wss://theforest.nostr1.com 5 0 0 0 0 0 OK
|
||||
|
||||
=== Kind Distribution ===
|
||||
Kind Name Count % Total Bytes Avg Max
|
||||
21059 Gift wrap (NIP-59) 184 12.4% 623532 3389 5314
|
||||
22591 Ephemeral 139 9.4% 107560 774 1223
|
||||
30382 Addressable 119 8.0% 53663 451 458
|
||||
30383 Addressable 119 8.0% 53605 450 536
|
||||
5 Deletion 91 6.1% 39950 439 624
|
||||
30078 App data 54 3.6% 179695 3328 14343
|
||||
20001 Ephemeral 49 3.3% 35635 727 1871
|
||||
0 Profile metadata 48 3.2% 39906 831 1468
|
||||
22668 Ephemeral 48 3.2% 20592 429 429
|
||||
1 Text note 45 3.0% 38547 857 2413
|
||||
22734 Ephemeral 26 1.8% 11102 427 427
|
||||
4515 Unknown 26 1.8% 38218 1470 2956
|
||||
10002 Relay list 25 1.7% 11707 468 565
|
||||
22850 Ephemeral 24 1.6% 10320 430 430
|
||||
7 Reaction 24 1.6% 13528 564 780
|
||||
22551 Ephemeral 24 1.6% 10320 430 430
|
||||
31991 Addressable 20 1.3% 9220 461 461
|
||||
38501 Addressable 18 1.2% 13341 741 744
|
||||
22663 Ephemeral 17 1.1% 7276 428 428
|
||||
25555 Ephemeral 15 1.0% 90493 6033 16887
|
||||
22912 Ephemeral 13 0.9% 5564 428 428
|
||||
1059 Gift wrap seal 13 0.9% 23775 1829 1883
|
||||
22832 Ephemeral 12 0.8% 5233 436 446
|
||||
22690 Ephemeral 11 0.7% 4730 430 430
|
||||
22545 Ephemeral 11 0.7% 4697 427 427
|
||||
25050 Ephemeral 10 0.7% 4394 439 465
|
||||
37195 Addressable 10 0.7% 7494 749 771
|
||||
22601 Ephemeral 10 0.7% 4280 428 428
|
||||
22795 Ephemeral 10 0.7% 11639 1164 1487
|
||||
22891 Ephemeral 9 0.6% 13331 1481 1490
|
||||
22655 Ephemeral 9 0.6% 3852 428 428
|
||||
22911 Ephemeral 9 0.6% 13328 1481 1487
|
||||
24133 Ephemeral 9 0.6% 8250 917 1534
|
||||
13194 NWC info 8 0.5% 4112 514 514
|
||||
22647 Ephemeral 8 0.5% 3416 427 427
|
||||
22695 Ephemeral 7 0.5% 10339 1477 1481
|
||||
22653 Ephemeral 7 0.5% 10368 1481 1487
|
||||
22455 Ephemeral 7 0.5% 10339 1477 1485
|
||||
22543 Ephemeral 7 0.5% 10354 1479 1487
|
||||
30315 User status 7 0.5% 2714 388 398
|
||||
22676 Ephemeral 6 0.4% 2562 427 427
|
||||
22575 Ephemeral 6 0.4% 2550 425 425
|
||||
22689 Ephemeral 6 0.4% 8851 1475 1484
|
||||
22913 Ephemeral 6 0.4% 2586 431 431
|
||||
22774 Ephemeral 6 0.4% 2568 428 428
|
||||
24242 Ephemeral 6 0.4% 3474 579 579
|
||||
22808 Ephemeral 6 0.4% 2574 429 429
|
||||
22842 Ephemeral 6 0.4% 8891 1482 1488
|
||||
22603 Ephemeral 5 0.3% 2130 426 426
|
||||
6 Repost 5 0.3% 10814 2163 7298
|
||||
31990 App handler info 5 0.3% 4305 861 1321
|
||||
22384 Ephemeral 5 0.3% 2130 426 426
|
||||
22699 Ephemeral 5 0.3% 2140 428 428
|
||||
22613 Ephemeral 5 0.3% 3443 689 691
|
||||
38502 Addressable 5 0.3% 1925 385 385
|
||||
23003 Ephemeral 5 0.3% 2140 428 428
|
||||
22743 Ephemeral 5 0.3% 2140 428 428
|
||||
29333 Ephemeral 5 0.3% 2460 492 492
|
||||
20004 Ephemeral 4 0.3% 1800 450 549
|
||||
4 Encrypted DM 4 0.3% 3072 768 826
|
||||
20387 Ephemeral 4 0.3% 2056 514 514
|
||||
22816 Ephemeral 4 0.3% 1716 429 429
|
||||
20000 Ephemeral 4 0.3% 1872 468 628
|
||||
22934 Ephemeral 3 0.2% 5535 1845 1846
|
||||
1985 Unknown 2 0.1% 948 474 474
|
||||
31234 Addressable 2 0.1% 89092 44546 44546
|
||||
10777 Unknown 2 0.1% 976 488 488
|
||||
4004 Unknown 2 0.1% 2338 1169 1169
|
||||
9735 Zap receipt 2 0.1% 3926 1963 2135
|
||||
1000 Unknown 2 0.1% 3415 1708 1712
|
||||
25195 Ephemeral 2 0.1% 1356 678 678
|
||||
30311 Addressable 2 0.1% 2210 1105 1198
|
||||
25196 Ephemeral 2 0.1% 3576 1788 2214
|
||||
1040 Unknown 2 0.1% 1920 960 960
|
||||
38383 Addressable 2 0.1% 1532 766 815
|
||||
30515 Addressable 2 0.1% 5152 2576 2576
|
||||
30091 Addressable 2 0.1% 1221 610 611
|
||||
30088 Addressable 2 0.1% 3717 1858 1859
|
||||
21617 Ephemeral 1 0.1% 494 494 494
|
||||
30380 Addressable 1 0.1% 454 454 454
|
||||
22611 Ephemeral 1 0.1% 426 426 426
|
||||
30079 Addressable 1 0.1% 875 875 875
|
||||
22767 Ephemeral 1 0.1% 429 429 429
|
||||
38500 Addressable 1 0.1% 711 711 711
|
||||
30312 Addressable 1 0.1% 461 461 461
|
||||
7368 Unknown 1 0.1% 1039 1039 1039
|
||||
22967 Ephemeral 1 0.1% 431 431 431
|
||||
39101 Addressable 1 0.1% 533 533 533
|
||||
445 Encrypted group msg 1 0.1% 4130 4130 4130
|
||||
10000 Mute list 1 0.1% 1722 1722 1722
|
||||
30617 Addressable 1 0.1% 1089 1089 1089
|
||||
22526 Ephemeral 1 0.1% 430 430 430
|
||||
20787 Ephemeral 1 0.1% 926 926 926
|
||||
443 Unknown 1 0.1% 800 800 800
|
||||
16 Generic repost 1 0.1% 780 780 780
|
||||
10011 Unknown 1 0.1% 397 397 397
|
||||
22679 Ephemeral 1 0.1% 693 693 693
|
||||
23042 Ephemeral 1 0.1% 429 429 429
|
||||
22514 Ephemeral 1 0.1% 428 428 428
|
||||
30023 Long-form article 1 0.1% 8164 8164 8164
|
||||
5300 Unknown 1 0.1% 630 630 630
|
||||
22605 Ephemeral 1 0.1% 692 692 692
|
||||
34237 Addressable 1 0.1% 418 418 418
|
||||
30618 Addressable 1 0.1% 733 733 733
|
||||
38421 Addressable 1 0.1% 1069 1069 1069
|
||||
10100 Unknown 1 0.1% 1036 1036 1036
|
||||
30080 Addressable 1 0.1% 925 925 925
|
||||
38385 Addressable 1 0.1% 1214 1214 1214
|
||||
38225 Addressable 1 0.1% 1012 1012 1012
|
||||
11998 Unknown 1 0.1% 465 465 465
|
||||
22236 Ephemeral 1 0.1% 747 747 747
|
||||
22823 Ephemeral 1 0.1% 1852 1852 1852
|
||||
|
||||
=== Raw Relay Response Log ===
|
||||
# Cache-All Feasibility Test - Raw Relay Log
|
||||
# Started: Sun Aug 2 11:20:28 2026
|
||||
# Config: cache_all_test_config.jsonc
|
||||
# Duration: 86400 seconds
|
||||
[2026-08-02 11:21:06] [RELAY] wss://laantungir.net STATUS: ?
|
||||
[2026-08-02 11:21:06] [RELAY] wss://nos.lol STATUS: connected
|
||||
[2026-08-02 11:21:06] [RELAY] wss://nostr-pub.wellorder.net STATUS: connected
|
||||
[2026-08-02 11:21:06] [RELAY] wss://nostr.mom STATUS: connected
|
||||
[2026-08-02 11:21:06] [RELAY] wss://nostr.oxtr.dev STATUS: connected
|
||||
[2026-08-02 11:21:06] [RELAY] wss://offchain.pub STATUS: connected
|
||||
[2026-08-02 11:21:06] [RELAY] wss://premium.primal.net STATUS: connected
|
||||
[2026-08-02 11:21:06] [RELAY] wss://relay.damus.io STATUS: connected
|
||||
[2026-08-02 11:21:06] [RELAY] wss://relay.ditto.pub STATUS: connected
|
||||
[2026-08-02 11:21:06] [RELAY] wss://relay.divine.video STATUS: connected
|
||||
[2026-08-02 11:21:06] [RELAY] wss://relay.momostr.pink STATUS: connected
|
||||
[2026-08-02 11:21:06] [RELAY] wss://relay.mostr.pub STATUS: connected
|
||||
[2026-08-02 11:21:06] [RELAY] wss://relay.nostrplebs.com STATUS: connected
|
||||
[2026-08-02 11:21:06] [RELAY] wss://relay.primal.net STATUS: connected
|
||||
[2026-08-02 11:21:06] [RELAY] wss://theforest.nostr1.com STATUS: connected
|
||||
[2026-08-02 11:21:26] [RELAY] wss://relay.ditto.pub DISCONNECTED: Connection state transitioned to 2 during poll
|
||||
[2026-08-02 11:21:26] [RELAY] wss://relay.ditto.pub CONNECTED
|
||||
|
||||
@@ -0,0 +1,423 @@
|
||||
=== Cache-All Feasibility Test Report ===
|
||||
Duration: 0h 40m 5s
|
||||
|
||||
=== Global Summary ===
|
||||
Total events: 40082
|
||||
Total bytes: 52985157 (50.53 MB)
|
||||
Avg event size: 1322 bytes
|
||||
Max event: 58662 bytes (kind 3)
|
||||
Unique pubkeys: 7202
|
||||
Relays: 15
|
||||
|
||||
=== Relay Summary ===
|
||||
Relay Events EOSE CLOSED NOTICE Err Disc Status
|
||||
wss://laantungir.net 0 0 0 0 0 0 DOWN
|
||||
wss://nos.lol 7469 0 0 0 0 11 OK
|
||||
wss://nostr-pub.wellorder.net 697 0 0 0 0 0 OK
|
||||
wss://nostr.mom 1389 0 0 0 0 0 OK
|
||||
wss://nostr.oxtr.dev 1009 0 0 0 0 0 OK
|
||||
wss://offchain.pub 4338 0 0 0 0 0 OK
|
||||
wss://premium.primal.net 226 0 0 0 0 36 OK
|
||||
wss://relay.damus.io 4929 0 0 0 0 6 OK
|
||||
wss://relay.ditto.pub 5951 0 0 0 0 0 OK
|
||||
wss://relay.divine.video 127 0 0 0 0 0 OK
|
||||
wss://relay.momostr.pink 857 0 0 0 0 0 OK
|
||||
wss://relay.mostr.pub 4182 0 0 0 0 1 OK
|
||||
wss://relay.nostrplebs.com 23 0 0 0 0 1 OK
|
||||
wss://relay.primal.net 8596 0 0 0 0 10 OK
|
||||
wss://theforest.nostr1.com 289 0 0 0 0 0 OK
|
||||
|
||||
=== Kind Distribution ===
|
||||
Kind Name Count % Total Bytes Avg Max
|
||||
21059 Gift wrap (NIP-59) 5631 14.0% 18980562 3371 5314
|
||||
30382 Addressable 4179 10.4% 1900908 455 483
|
||||
22591 Ephemeral 3320 8.3% 2581724 778 1814
|
||||
5 Deletion 2848 7.1% 1264487 444 1659
|
||||
20001 Ephemeral 1602 4.0% 1333680 833 5870
|
||||
1 Text note 1556 3.9% 1359052 873 2843
|
||||
30078 App data 1118 2.8% 4202383 3759 52067
|
||||
22668 Ephemeral 1014 2.5% 435006 429 429
|
||||
24133 Ephemeral 965 2.4% 2468722 2558 19622
|
||||
0 Profile metadata 959 2.4% 865512 903 6506
|
||||
7 Reaction 766 1.9% 465618 608 1403
|
||||
22551 Ephemeral 703 1.8% 305982 435 1819
|
||||
22734 Ephemeral 684 1.7% 292068 427 427
|
||||
38501 Addressable 583 1.5% 432057 741 744
|
||||
22912 Ephemeral 582 1.5% 249096 428 428
|
||||
10002 Relay list 579 1.4% 898767 1552 42385
|
||||
22850 Ephemeral 543 1.4% 233490 430 430
|
||||
37195 Addressable 436 1.1% 329238 755 934
|
||||
25555 Ephemeral 407 1.0% 2047337 5030 16903
|
||||
30383 Addressable 379 0.9% 197360 521 544
|
||||
22832 Ephemeral 342 0.9% 149404 437 446
|
||||
22690 Ephemeral 309 0.8% 132870 430 430
|
||||
22651 Ephemeral 305 0.8% 130235 427 427
|
||||
22236 Ephemeral 301 0.8% 226221 752 815
|
||||
6 Repost 299 0.7% 301866 1010 9866
|
||||
4515 Unknown 291 0.7% 533897 1835 16952
|
||||
22601 Ephemeral 252 0.6% 107856 428 428
|
||||
25050 Ephemeral 233 0.6% 102329 439 465
|
||||
31991 Addressable 229 0.6% 105569 461 461
|
||||
22655 Ephemeral 218 0.5% 93304 428 428
|
||||
29333 Ephemeral 215 0.5% 105780 492 492
|
||||
22795 Ephemeral 188 0.5% 214828 1143 1847
|
||||
22676 Ephemeral 188 0.5% 80276 427 427
|
||||
22808 Ephemeral 178 0.4% 84072 472 1253
|
||||
22384 Ephemeral 175 0.4% 74550 426 426
|
||||
31990 App handler info 167 0.4% 183247 1097 6861
|
||||
22913 Ephemeral 160 0.4% 68960 431 431
|
||||
13194 NWC info 156 0.4% 80184 514 514
|
||||
22603 Ephemeral 155 0.4% 66030 426 426
|
||||
22743 Ephemeral 155 0.4% 66340 428 428
|
||||
22575 Ephemeral 154 0.4% 65450 425 425
|
||||
20000 Ephemeral 151 0.4% 67354 446 1198
|
||||
7368 Unknown 149 0.4% 154743 1039 1059
|
||||
23049 Ephemeral 147 0.4% 63210 430 430
|
||||
24242 Ephemeral 144 0.4% 83376 579 579
|
||||
11998 Unknown 142 0.4% 65790 463 465
|
||||
445 Encrypted group msg 140 0.3% 293740 2098 5194
|
||||
22456 Ephemeral 131 0.3% 63614 486 790
|
||||
20787 Ephemeral 131 0.3% 179206 1368 2478
|
||||
20387 Ephemeral 128 0.3% 65792 514 514
|
||||
22911 Ephemeral 125 0.3% 190126 1521 1849
|
||||
22653 Ephemeral 124 0.3% 188585 1521 1848
|
||||
22455 Ephemeral 124 0.3% 188540 1520 1844
|
||||
22695 Ephemeral 124 0.3% 188335 1519 1850
|
||||
22891 Ephemeral 122 0.3% 185731 1522 1850
|
||||
1059 Gift wrap seal 122 0.3% 235480 1930 5285
|
||||
22543 Ephemeral 122 0.3% 185791 1523 1846
|
||||
22689 Ephemeral 119 0.3% 181177 1522 1845
|
||||
22816 Ephemeral 118 0.3% 50622 429 429
|
||||
22774 Ephemeral 115 0.3% 49220 428 428
|
||||
23003 Ephemeral 113 0.3% 48364 428 428
|
||||
22842 Ephemeral 111 0.3% 169484 1527 1848
|
||||
443 Unknown 111 0.3% 163453 1473 22480
|
||||
23337 Ephemeral 108 0.3% 57242 530 531
|
||||
30315 User status 107 0.3% 66269 619 1166
|
||||
22699 Ephemeral 106 0.3% 48256 455 1505
|
||||
1985 Unknown 104 0.3% 63816 614 4833
|
||||
22663 Ephemeral 101 0.3% 43228 428 428
|
||||
38502 Addressable 101 0.3% 38885 385 385
|
||||
23004 Ephemeral 100 0.2% 43100 431 431
|
||||
4004 Unknown 100 0.2% 116900 1169 1169
|
||||
3 Follow list 96 0.2% 1944563 20256 58662
|
||||
4 Encrypted DM 95 0.2% 95818 1009 17018
|
||||
9735 Zap receipt 94 0.2% 183437 1951 2436
|
||||
22647 Ephemeral 83 0.2% 35441 427 427
|
||||
31234 Addressable 81 0.2% 177493 2191 44546
|
||||
5300 Unknown 80 0.2% 48788 610 744
|
||||
23334 Ephemeral 75 0.2% 33681 449 454
|
||||
10100 Unknown 74 0.2% 110084 1488 3826
|
||||
22613 Ephemeral 74 0.2% 53289 720 1814
|
||||
20004 Ephemeral 71 0.2% 37593 529 549
|
||||
22631 Ephemeral 67 0.2% 61813 923 1822
|
||||
20333 Ephemeral 67 0.2% 53378 797 798
|
||||
22657 Ephemeral 67 0.2% 53820 803 1279
|
||||
10050 DM relays 64 0.2% 27983 437 536
|
||||
22545 Ephemeral 61 0.2% 26047 427 427
|
||||
30023 Long-form article 56 0.1% 369281 6594 16772
|
||||
30311 Addressable 55 0.1% 56530 1028 1198
|
||||
1111 Comment 51 0.1% 72307 1418 2352
|
||||
30166 Addressable 49 0.1% 26188 534 808
|
||||
4244 Unknown 41 0.1% 23124 564 564
|
||||
30088 Addressable 41 0.1% 76377 1863 1871
|
||||
30091 Addressable 40 0.1% 24624 616 629
|
||||
38503 Addressable 40 0.1% 22081 552 553
|
||||
22782 Ephemeral 40 0.1% 36524 913 1167
|
||||
22611 Ephemeral 38 0.1% 16263 428 429
|
||||
22605 Ephemeral 36 0.1% 42806 1189 1849
|
||||
22767 Ephemeral 35 0.1% 15015 429 429
|
||||
22967 Ephemeral 34 0.1% 14654 431 431
|
||||
38383 Addressable 33 0.1% 28002 849 3207
|
||||
10011 Unknown 32 0.1% 13152 411 431
|
||||
8108 Unknown 30 0.1% 39052 1302 1574
|
||||
22623 Ephemeral 30 0.1% 24536 818 1283
|
||||
30089 Chunked data 29 0.1% 370012 12759 44372
|
||||
30515 Addressable 29 0.1% 74704 2576 2576
|
||||
10777 Unknown 26 0.1% 12688 488 488
|
||||
38385 Addressable 26 0.1% 34815 1339 1496
|
||||
22679 Ephemeral 24 0.1% 28787 1199 1852
|
||||
25195 Ephemeral 24 0.1% 14928 622 678
|
||||
21060 Ephemeral 23 0.1% 13110 570 570
|
||||
22738 Ephemeral 23 0.1% 18515 805 1252
|
||||
30380 Addressable 23 0.1% 10442 454 454
|
||||
33334 Addressable 22 0.1% 18282 831 831
|
||||
22547 Ephemeral 22 0.1% 20278 922 1164
|
||||
21617 Ephemeral 21 0.1% 10544 502 517
|
||||
33301 Addressable 20 0.0% 35736 1787 2162
|
||||
38500 Addressable 19 0.0% 13531 712 713
|
||||
38384 Addressable 19 0.0% 14115 743 743
|
||||
22526 Ephemeral 19 0.0% 8170 430 430
|
||||
6300 Unknown 19 0.0% 64041 3371 6898
|
||||
30443 Addressable 19 0.0% 22604 1190 1260
|
||||
22919 Ephemeral 18 0.0% 32466 1804 1849
|
||||
22724 Ephemeral 18 0.0% 13222 735 1253
|
||||
22789 Ephemeral 17 0.0% 28521 1678 3267
|
||||
1002 Unknown 17 0.0% 16010 942 981
|
||||
3434 Unknown 17 0.0% 11585 681 705
|
||||
22507 Ephemeral 16 0.0% 9927 620 1163
|
||||
20384 Ephemeral 16 0.0% 10223 639 639
|
||||
30080 Addressable 16 0.0% 15048 940 987
|
||||
22672 Ephemeral 16 0.0% 24987 1562 1847
|
||||
22844 Ephemeral 15 0.0% 6435 429 429
|
||||
4245 Unknown 15 0.0% 6660 444 444
|
||||
4243 Unknown 15 0.0% 8460 564 564
|
||||
30009 Addressable 15 0.0% 6949 463 479
|
||||
22514 Ephemeral 14 0.0% 5992 428 428
|
||||
14 Unknown 14 0.0% 15322 1094 1551
|
||||
3927 Unknown 14 0.0% 7484 535 544
|
||||
23042 Ephemeral 14 0.0% 6006 429 429
|
||||
10000 Mute list 14 0.0% 32097 2293 8671
|
||||
30618 Addressable 13 0.0% 25947 1996 8739
|
||||
1040 Unknown 13 0.0% 13272 1021 1048
|
||||
31510 Addressable 13 0.0% 12731 979 982
|
||||
30617 Addressable 12 0.0% 13112 1093 1146
|
||||
25196 Ephemeral 12 0.0% 19580 1632 2214
|
||||
38225 Addressable 12 0.0% 11742 978 1006
|
||||
39101 Addressable 11 0.0% 5863 533 533
|
||||
26428 Ephemeral 10 0.0% 8765 876 877
|
||||
30213 Addressable 10 0.0% 6224 622 632
|
||||
26429 Ephemeral 10 0.0% 4910 491 491
|
||||
30000 Addressable 9 0.0% 17509 1945 5660
|
||||
22639 Ephemeral 9 0.0% 3852 428 428
|
||||
31339 Addressable 9 0.0% 13230 1470 1470
|
||||
30312 Addressable 8 0.0% 3555 444 461
|
||||
9321 Unknown 7 0.0% 16541 2363 2363
|
||||
7403 Unknown 7 0.0% 3435 491 491
|
||||
1010 Unknown 7 0.0% 5098 728 748
|
||||
16 Generic repost 7 0.0% 5460 780 780
|
||||
7375 Unknown 7 0.0% 8120 1160 1160
|
||||
22839 Ephemeral 7 0.0% 2996 428 428
|
||||
7376 Unknown 7 0.0% 5817 831 831
|
||||
3079 Unknown 6 0.0% 5454 909 909
|
||||
22658 Ephemeral 6 0.0% 6269 1045 1813
|
||||
30090 Addressable 5 0.0% 7575 1515 1515
|
||||
34236 Addressable 5 0.0% 61577 12315 21112
|
||||
22120 Ephemeral 5 0.0% 5493 1099 1133
|
||||
22119 Ephemeral 5 0.0% 4227 845 846
|
||||
23194 NWC request 5 0.0% 2554 511 534
|
||||
1984 Report 5 0.0% 2714 543 662
|
||||
31000 Addressable 5 0.0% 3024 605 616
|
||||
1078 Unknown 5 0.0% 70534 14107 14226
|
||||
10003 Bookmarks 5 0.0% 15698 3140 4954
|
||||
1000 Unknown 4 0.0% 6474 1618 1782
|
||||
30087 Addressable 4 0.0% 29300 7325 7325
|
||||
38111 Addressable 4 0.0% 2996 749 752
|
||||
25055 Ephemeral 4 0.0% 6286 1572 1788
|
||||
30421 Addressable 4 0.0% 4079 1020 1028
|
||||
30079 Addressable 4 0.0% 3500 875 875
|
||||
30815 Addressable 4 0.0% 150136 37534 37534
|
||||
13302 Unknown 4 0.0% 30097 7524 22303
|
||||
22865 Ephemeral 4 0.0% 2785 696 699
|
||||
10012 Unknown 3 0.0% 1388 463 622
|
||||
39015 Addressable 3 0.0% 2088 696 696
|
||||
30787 Addressable 3 0.0% 4118 1373 1374
|
||||
10001 Pinned notes 3 0.0% 1758 586 586
|
||||
15129 Unknown 3 0.0% 1365 455 455
|
||||
37779 Addressable 3 0.0% 1569 523 523
|
||||
8 Unknown 3 0.0% 1527 509 509
|
||||
30003 Addressable 3 0.0% 1167 389 389
|
||||
31512 Addressable 3 0.0% 10234 3411 3414
|
||||
39050 Addressable 3 0.0% 5529 1843 1843
|
||||
31237 Addressable 3 0.0% 2439 813 821
|
||||
30554 Addressable 3 0.0% 1827 609 609
|
||||
22778 Ephemeral 3 0.0% 4059 1353 1847
|
||||
30402 Addressable 3 0.0% 2036 679 680
|
||||
10063 Unknown 3 0.0% 1639 546 627
|
||||
1631 Unknown 2 0.0% 2620 1310 1310
|
||||
1315 Unknown 2 0.0% 990 495 495
|
||||
22760 Ephemeral 2 0.0% 3624 1812 1814
|
||||
30495 Addressable 2 0.0% 4074 2037 2037
|
||||
10051 Unknown 2 0.0% 878 439 439
|
||||
13196 Unknown 2 0.0% 1312 656 656
|
||||
38421 Addressable 2 0.0% 2140 1070 1070
|
||||
23333 Ephemeral 2 0.0% 1636 818 818
|
||||
2333 Unknown 2 0.0% 1812 906 906
|
||||
24913 Ephemeral 2 0.0% 1164 582 582
|
||||
22882 Ephemeral 2 0.0% 2000 1000 1164
|
||||
22617 Ephemeral 2 0.0% 852 426 426
|
||||
22729 Ephemeral 2 0.0% 1860 930 930
|
||||
22733 Ephemeral 2 0.0% 3330 1665 1848
|
||||
23013 Ephemeral 2 0.0% 2965 1482 1485
|
||||
9 Unknown 2 0.0% 4085 2042 2157
|
||||
31986 Addressable 2 0.0% 1182 591 591
|
||||
1063 File metadata 1 0.0% 909 909 909
|
||||
1060 Unknown 1 0.0% 1207 1207 1207
|
||||
10312 Unknown 1 0.0% 472 472 472
|
||||
37368 Addressable 1 0.0% 1236 1236 1236
|
||||
15750 Unknown 1 0.0% 626 626 626
|
||||
22598 Ephemeral 1 0.0% 1666 1666 1666
|
||||
17375 Unknown 1 0.0% 606 606 606
|
||||
22496 Ephemeral 1 0.0% 1518 1518 1518
|
||||
20200 Ephemeral 1 0.0% 491 491 491
|
||||
39019 Addressable 1 0.0% 961 961 961
|
||||
34238 Addressable 1 0.0% 920 920 920
|
||||
22732 Ephemeral 1 0.0% 1334 1334 1334
|
||||
20201 Ephemeral 1 0.0% 491 491 491
|
||||
12222 Unknown 1 0.0% 579 579 579
|
||||
31337 Addressable 1 0.0% 818 818 818
|
||||
23071 Ephemeral 1 0.0% 1910 1910 1910
|
||||
33333 Addressable 1 0.0% 2346 2346 2346
|
||||
20 Picture 1 0.0% 445 445 445
|
||||
1808 Unknown 1 0.0% 683 683 683
|
||||
30113 Addressable 1 0.0% 770 770 770
|
||||
34235 Addressable 1 0.0% 1501 1501 1501
|
||||
10377 Unknown 1 0.0% 664 664 664
|
||||
11111 Unknown 1 0.0% 382 382 382
|
||||
10133 Unknown 1 0.0% 499 499 499
|
||||
30081 Addressable 1 0.0% 1370 1370 1370
|
||||
10009 Unknown 1 0.0% 422 422 422
|
||||
30005 Addressable 1 0.0% 9671 9671 9671
|
||||
10443 Unknown 1 0.0% 676 676 676
|
||||
|
||||
=== Raw Relay Response Log ===
|
||||
# Cache-All Feasibility Test - Raw Relay Log
|
||||
# Started: Sun Aug 2 11:21:56 2026
|
||||
# Config: cache_all_test_config.jsonc
|
||||
# Duration: 86400 seconds
|
||||
[2026-08-02 11:22:33] [RELAY] wss://laantungir.net STATUS: ?
|
||||
[2026-08-02 11:22:33] [RELAY] wss://nos.lol STATUS: connected
|
||||
[2026-08-02 11:22:33] [RELAY] wss://nostr-pub.wellorder.net STATUS: connected
|
||||
[2026-08-02 11:22:33] [RELAY] wss://nostr.mom STATUS: connected
|
||||
[2026-08-02 11:22:33] [RELAY] wss://nostr.oxtr.dev STATUS: connected
|
||||
[2026-08-02 11:22:33] [RELAY] wss://offchain.pub STATUS: connected
|
||||
[2026-08-02 11:22:33] [RELAY] wss://premium.primal.net STATUS: connected
|
||||
[2026-08-02 11:22:33] [RELAY] wss://relay.damus.io STATUS: connected
|
||||
[2026-08-02 11:22:33] [RELAY] wss://relay.ditto.pub STATUS: connected
|
||||
[2026-08-02 11:22:33] [RELAY] wss://relay.divine.video STATUS: connected
|
||||
[2026-08-02 11:22:33] [RELAY] wss://relay.momostr.pink STATUS: connected
|
||||
[2026-08-02 11:22:33] [RELAY] wss://relay.mostr.pub STATUS: connected
|
||||
[2026-08-02 11:22:33] [RELAY] wss://relay.nostrplebs.com STATUS: connected
|
||||
[2026-08-02 11:22:33] [RELAY] wss://relay.primal.net STATUS: connected
|
||||
[2026-08-02 11:22:33] [RELAY] wss://theforest.nostr1.com STATUS: connected
|
||||
[2026-08-02 11:23:06] [RELAY] wss://premium.primal.net DISCONNECTED: Connection state transitioned to 2 during poll
|
||||
[2026-08-02 11:23:06] [RELAY] wss://premium.primal.net CONNECTED
|
||||
[2026-08-02 11:23:07] [RELAY] wss://premium.primal.net DISCONNECTED: Connection state transitioned to 2 during poll
|
||||
[2026-08-02 11:23:08] [RELAY] wss://premium.primal.net CONNECTED
|
||||
[2026-08-02 11:23:08] [RELAY] wss://premium.primal.net DISCONNECTED: Connection state transitioned to 2 during poll
|
||||
[2026-08-02 11:23:09] [RELAY] wss://premium.primal.net CONNECTED
|
||||
[2026-08-02 11:23:38] [RELAY] wss://nos.lol DISCONNECTED:
|
||||
[2026-08-02 11:23:38] [RELAY] wss://nos.lol CONNECTED
|
||||
[2026-08-02 11:23:45] [RELAY] wss://relay.primal.net DISCONNECTED:
|
||||
[2026-08-02 11:23:45] [RELAY] wss://relay.primal.net CONNECTED
|
||||
[2026-08-02 11:24:08] [RELAY] wss://nos.lol DISCONNECTED:
|
||||
[2026-08-02 11:24:08] [RELAY] wss://nos.lol CONNECTED
|
||||
[2026-08-02 11:26:10] [RELAY] wss://premium.primal.net DISCONNECTED: Connection state transitioned to 2 during poll
|
||||
[2026-08-02 11:26:10] [RELAY] wss://premium.primal.net CONNECTED
|
||||
[2026-08-02 11:26:14] [RELAY] wss://premium.primal.net DISCONNECTED: Connection state transitioned to 2 during poll
|
||||
[2026-08-02 11:26:15] [RELAY] wss://premium.primal.net CONNECTED
|
||||
[2026-08-02 11:26:15] [RELAY] wss://relay.primal.net DISCONNECTED:
|
||||
[2026-08-02 11:26:15] [RELAY] wss://relay.primal.net CONNECTED
|
||||
[2026-08-02 11:26:28] [RELAY] wss://premium.primal.net DISCONNECTED: Connection state transitioned to 2 during poll
|
||||
[2026-08-02 11:26:29] [RELAY] wss://premium.primal.net CONNECTED
|
||||
[2026-08-02 11:26:38] [RELAY] wss://nos.lol DISCONNECTED:
|
||||
[2026-08-02 11:26:38] [RELAY] wss://nos.lol CONNECTED
|
||||
[2026-08-02 11:26:43] [RELAY] wss://premium.primal.net DISCONNECTED: Connection state transitioned to 2 during poll
|
||||
[2026-08-02 11:26:43] [RELAY] wss://premium.primal.net CONNECTED
|
||||
[2026-08-02 11:26:44] [RELAY] wss://premium.primal.net DISCONNECTED: Connection state transitioned to 2 during poll
|
||||
[2026-08-02 11:26:45] [RELAY] wss://premium.primal.net CONNECTED
|
||||
[2026-08-02 11:26:47] [RELAY] wss://premium.primal.net DISCONNECTED: Connection state transitioned to 2 during poll
|
||||
[2026-08-02 11:26:48] [RELAY] wss://premium.primal.net CONNECTED
|
||||
[2026-08-02 11:26:49] [RELAY] wss://premium.primal.net DISCONNECTED: Connection state transitioned to 2 during poll
|
||||
[2026-08-02 11:26:50] [RELAY] wss://premium.primal.net CONNECTED
|
||||
[2026-08-02 11:26:53] [RELAY] wss://premium.primal.net DISCONNECTED: Connection state transitioned to 2 during poll
|
||||
[2026-08-02 11:26:53] [RELAY] wss://premium.primal.net CONNECTED
|
||||
[2026-08-02 11:27:17] [RELAY] wss://nos.lol DISCONNECTED: Connection state transitioned to 2 during poll
|
||||
[2026-08-02 11:27:17] [RELAY] wss://nos.lol CONNECTED
|
||||
[2026-08-02 11:27:31] [RELAY] wss://relay.mostr.pub DISCONNECTED: Connection state transitioned to 2 during poll
|
||||
[2026-08-02 11:27:32] [RELAY] wss://relay.mostr.pub CONNECTED
|
||||
[2026-08-02 11:27:58] [RELAY] wss://nos.lol DISCONNECTED: Connection state transitioned to 2 during poll
|
||||
[2026-08-02 11:27:58] [RELAY] wss://nos.lol CONNECTED
|
||||
[2026-08-02 11:28:10] [RELAY] wss://premium.primal.net DISCONNECTED: Connection state transitioned to 2 during poll
|
||||
[2026-08-02 11:28:11] [RELAY] wss://premium.primal.net CONNECTED
|
||||
[2026-08-02 11:28:12] [RELAY] wss://premium.primal.net DISCONNECTED: Connection state transitioned to 2 during poll
|
||||
[2026-08-02 11:28:12] [RELAY] wss://premium.primal.net CONNECTED
|
||||
[2026-08-02 11:28:15] [RELAY] wss://relay.primal.net DISCONNECTED:
|
||||
[2026-08-02 11:28:15] [RELAY] wss://relay.primal.net CONNECTED
|
||||
[2026-08-02 11:28:15] [RELAY] wss://premium.primal.net DISCONNECTED: Connection state transitioned to 2 during poll
|
||||
[2026-08-02 11:28:16] [RELAY] wss://premium.primal.net CONNECTED
|
||||
[2026-08-02 11:28:17] [RELAY] wss://premium.primal.net DISCONNECTED: Connection state transitioned to 2 during poll
|
||||
[2026-08-02 11:28:18] [RELAY] wss://premium.primal.net CONNECTED
|
||||
[2026-08-02 11:28:20] [RELAY] wss://premium.primal.net DISCONNECTED: Connection state transitioned to 2 during poll
|
||||
[2026-08-02 11:28:20] [RELAY] wss://premium.primal.net CONNECTED
|
||||
[2026-08-02 11:28:22] [RELAY] wss://premium.primal.net DISCONNECTED: Connection state transitioned to 2 during poll
|
||||
[2026-08-02 11:28:22] [RELAY] wss://premium.primal.net CONNECTED
|
||||
[2026-08-02 11:28:24] [RELAY] wss://premium.primal.net DISCONNECTED: Connection state transitioned to 2 during poll
|
||||
[2026-08-02 11:28:25] [RELAY] wss://premium.primal.net CONNECTED
|
||||
[2026-08-02 11:28:44] [RELAY] wss://premium.primal.net DISCONNECTED: Connection state transitioned to 2 during poll
|
||||
[2026-08-02 11:28:45] [RELAY] wss://premium.primal.net CONNECTED
|
||||
[2026-08-02 11:28:45] [RELAY] wss://relay.primal.net DISCONNECTED:
|
||||
[2026-08-02 11:28:45] [RELAY] wss://relay.primal.net CONNECTED
|
||||
[2026-08-02 11:28:46] [RELAY] wss://premium.primal.net DISCONNECTED: Connection state transitioned to 2 during poll
|
||||
[2026-08-02 11:28:47] [RELAY] wss://premium.primal.net CONNECTED
|
||||
[2026-08-02 11:28:51] [RELAY] wss://premium.primal.net DISCONNECTED: Connection state transitioned to 2 during poll
|
||||
[2026-08-02 11:28:51] [RELAY] wss://premium.primal.net CONNECTED
|
||||
[2026-08-02 11:28:56] [RELAY] wss://premium.primal.net DISCONNECTED: Connection state transitioned to 2 during poll
|
||||
[2026-08-02 11:28:56] [RELAY] wss://premium.primal.net CONNECTED
|
||||
[2026-08-02 11:29:28] [RELAY] wss://nos.lol DISCONNECTED:
|
||||
[2026-08-02 11:29:28] [RELAY] wss://nos.lol CONNECTED
|
||||
[2026-08-02 11:29:59] [RELAY] wss://premium.primal.net DISCONNECTED: Connection state transitioned to 2 during poll
|
||||
[2026-08-02 11:30:00] [RELAY] wss://premium.primal.net CONNECTED
|
||||
[2026-08-02 11:30:01] [RELAY] wss://premium.primal.net DISCONNECTED: Connection state transitioned to 2 during poll
|
||||
[2026-08-02 11:30:01] [RELAY] wss://premium.primal.net CONNECTED
|
||||
[2026-08-02 11:30:02] [RELAY] wss://premium.primal.net DISCONNECTED: Connection state transitioned to 2 during poll
|
||||
[2026-08-02 11:30:03] [RELAY] wss://premium.primal.net CONNECTED
|
||||
[2026-08-02 11:30:03] [RELAY] wss://premium.primal.net DISCONNECTED: Connection state transitioned to 2 during poll
|
||||
[2026-08-02 11:30:04] [RELAY] wss://premium.primal.net CONNECTED
|
||||
[2026-08-02 11:30:06] [RELAY] wss://premium.primal.net DISCONNECTED: Connection state transitioned to 2 during poll
|
||||
[2026-08-02 11:30:07] [RELAY] wss://premium.primal.net CONNECTED
|
||||
[2026-08-02 11:30:07] [RELAY] wss://premium.primal.net DISCONNECTED: Connection state transitioned to 2 during poll
|
||||
[2026-08-02 11:30:08] [RELAY] wss://premium.primal.net CONNECTED
|
||||
[2026-08-02 11:30:10] [RELAY] wss://premium.primal.net DISCONNECTED: Connection state transitioned to 2 during poll
|
||||
[2026-08-02 11:30:11] [RELAY] wss://premium.primal.net CONNECTED
|
||||
[2026-08-02 11:30:14] [RELAY] wss://premium.primal.net DISCONNECTED: Connection state transitioned to 2 during poll
|
||||
[2026-08-02 11:30:15] [RELAY] wss://premium.primal.net CONNECTED
|
||||
[2026-08-02 11:30:17] [RELAY] wss://premium.primal.net DISCONNECTED: Connection state transitioned to 2 during poll
|
||||
[2026-08-02 11:30:18] [RELAY] wss://premium.primal.net CONNECTED
|
||||
[2026-08-02 11:30:18] [RELAY] wss://premium.primal.net DISCONNECTED: Connection state transitioned to 2 during poll
|
||||
[2026-08-02 11:30:19] [RELAY] wss://premium.primal.net CONNECTED
|
||||
[2026-08-02 11:30:19] [RELAY] wss://relay.primal.net DISCONNECTED:
|
||||
[2026-08-02 11:30:19] [RELAY] wss://relay.primal.net CONNECTED
|
||||
[2026-08-02 11:30:20] [RELAY] wss://premium.primal.net DISCONNECTED: Connection state transitioned to 2 during poll
|
||||
[2026-08-02 11:30:20] [RELAY] wss://premium.primal.net CONNECTED
|
||||
[2026-08-02 11:30:22] [RELAY] wss://premium.primal.net DISCONNECTED: Connection state transitioned to 2 during poll
|
||||
[2026-08-02 11:30:23] [RELAY] wss://premium.primal.net CONNECTED
|
||||
[2026-08-02 11:30:25] [RELAY] wss://premium.primal.net DISCONNECTED: Connection state transitioned to 2 during poll
|
||||
[2026-08-02 11:30:26] [RELAY] wss://premium.primal.net CONNECTED
|
||||
[2026-08-02 11:30:58] [RELAY] wss://nos.lol DISCONNECTED:
|
||||
[2026-08-02 11:30:58] [RELAY] wss://nos.lol CONNECTED
|
||||
[2026-08-02 11:31:19] [RELAY] wss://relay.primal.net DISCONNECTED:
|
||||
[2026-08-02 11:31:19] [RELAY] wss://relay.primal.net CONNECTED
|
||||
[2026-08-02 11:31:28] [RELAY] wss://nos.lol DISCONNECTED:
|
||||
[2026-08-02 11:31:28] [RELAY] wss://nos.lol CONNECTED
|
||||
[2026-08-02 11:32:19] [RELAY] wss://relay.primal.net DISCONNECTED:
|
||||
[2026-08-02 11:32:19] [RELAY] wss://relay.primal.net CONNECTED
|
||||
[2026-08-02 11:32:28] [RELAY] wss://nos.lol DISCONNECTED:
|
||||
[2026-08-02 11:32:28] [RELAY] wss://nos.lol CONNECTED
|
||||
[2026-08-02 11:32:46] [RELAY] wss://relay.damus.io DISCONNECTED: Connection state transitioned to 2 during poll
|
||||
[2026-08-02 11:32:52] [RELAY] wss://relay.damus.io CONNECTED
|
||||
[2026-08-02 11:33:03] [RELAY] wss://relay.damus.io DISCONNECTED: Failed to create WebSocket client for relay wss://relay.damus.io
|
||||
[2026-08-02 11:33:13] [RELAY] wss://relay.damus.io CONNECTED
|
||||
[2026-08-02 11:33:19] [RELAY] wss://relay.primal.net DISCONNECTED:
|
||||
[2026-08-02 11:33:19] [RELAY] wss://relay.primal.net CONNECTED
|
||||
[2026-08-02 11:33:54] [RELAY] wss://relay.damus.io DISCONNECTED: Failed to create WebSocket client for relay wss://relay.damus.io
|
||||
[2026-08-02 11:33:54] [RELAY] wss://relay.damus.io CONNECTED
|
||||
[2026-08-02 11:34:12] [RELAY] wss://nos.lol DISCONNECTED:
|
||||
[2026-08-02 11:34:12] [RELAY] wss://nos.lol CONNECTED
|
||||
[2026-08-02 11:34:24] [RELAY] wss://relay.damus.io DISCONNECTED:
|
||||
[2026-08-02 11:34:24] [RELAY] wss://relay.damus.io CONNECTED
|
||||
[2026-08-02 11:35:13] [RELAY] wss://nos.lol DISCONNECTED: Connection state transitioned to 2 during poll
|
||||
[2026-08-02 11:35:13] [RELAY] wss://nos.lol CONNECTED
|
||||
[2026-08-02 11:35:24] [RELAY] wss://relay.damus.io DISCONNECTED:
|
||||
[2026-08-02 11:35:24] [RELAY] wss://relay.damus.io CONNECTED
|
||||
[2026-08-02 11:36:18] [RELAY] wss://relay.damus.io DISCONNECTED: Failed to create WebSocket client for relay wss://relay.damus.io
|
||||
[2026-08-02 11:36:19] [RELAY] wss://relay.primal.net DISCONNECTED:
|
||||
[2026-08-02 11:36:19] [RELAY] wss://relay.primal.net CONNECTED
|
||||
[2026-08-02 11:36:28] [RELAY] wss://relay.damus.io CONNECTED
|
||||
[2026-08-02 11:36:49] [RELAY] wss://relay.primal.net DISCONNECTED:
|
||||
[2026-08-02 11:36:49] [RELAY] wss://relay.primal.net CONNECTED
|
||||
[2026-08-02 11:37:14] [RELAY] wss://relay.nostrplebs.com DISCONNECTED:
|
||||
[2026-08-02 11:37:14] [RELAY] wss://relay.nostrplebs.com CONNECTED
|
||||
[2026-08-02 11:37:19] [RELAY] wss://premium.primal.net DISCONNECTED:
|
||||
[2026-08-02 11:37:19] [RELAY] wss://premium.primal.net CONNECTED
|
||||
|
||||
@@ -0,0 +1,646 @@
|
||||
=== Cache-All Feasibility Test Report ===
|
||||
Duration: 0h 58m 5s
|
||||
|
||||
=== Global Summary ===
|
||||
Total events: 140345
|
||||
Total bytes: 182488517 (174.03 MB)
|
||||
Avg event size: 1300 bytes
|
||||
Max event: 62825 bytes (kind 1)
|
||||
Unique pubkeys: 26918
|
||||
Relays: 15
|
||||
|
||||
=== Relay Summary ===
|
||||
Relay Events EOSE CLOSED NOTICE Err Disc Status
|
||||
wss://laantungir.net 0 0 0 0 0 0 DOWN
|
||||
wss://nos.lol 25038 0 0 0 0 54 OK
|
||||
wss://nostr-pub.wellorder.net 3608 0 0 0 0 0 OK
|
||||
wss://nostr.mom 8692 0 0 0 0 0 OK
|
||||
wss://nostr.oxtr.dev 4360 0 0 0 0 7 OK
|
||||
wss://offchain.pub 17857 0 0 0 0 0 OK
|
||||
wss://premium.primal.net 171 0 0 0 0 26 OK
|
||||
wss://relay.damus.io 21539 0 0 0 0 0 OK
|
||||
wss://relay.ditto.pub 22251 0 0 0 0 7 OK
|
||||
wss://relay.divine.video 281 0 0 0 0 0 OK
|
||||
wss://relay.momostr.pink 1812 0 0 0 0 7 OK
|
||||
wss://relay.mostr.pub 20917 0 0 0 0 10 OK
|
||||
wss://relay.nostrplebs.com 23 0 0 0 0 0 OK
|
||||
wss://relay.primal.net 12945 0 0 0 0 57 OK
|
||||
wss://theforest.nostr1.com 851 0 0 0 0 0 OK
|
||||
|
||||
=== Kind Distribution ===
|
||||
Kind Name Count % Total Bytes Avg Max
|
||||
21059 Gift wrap (NIP-59) 22589 16.1% 76886982 3404 22354
|
||||
30382 Addressable 15147 10.8% 6854204 453 484
|
||||
5 Deletion 10634 7.6% 4652532 438 955
|
||||
20001 Ephemeral 4553 3.2% 2990229 657 26578
|
||||
22591 Ephemeral 4464 3.2% 3384073 758 1230
|
||||
1 Text note 4307 3.1% 4175360 969 62825
|
||||
22668 Ephemeral 4214 3.0% 1807801 429 429
|
||||
22466 Ephemeral 3541 2.5% 1519089 429 429
|
||||
30383 Addressable 3125 2.2% 1507650 482 550
|
||||
0 Profile metadata 2878 2.1% 2533064 880 9187
|
||||
22551 Ephemeral 2857 2.0% 1233111 432 1160
|
||||
30078 App data 2566 1.8% 8335901 3249 55090
|
||||
38501 Addressable 2349 1.7% 1740867 741 744
|
||||
22912 Ephemeral 1869 1.3% 802701 429 3197
|
||||
22684 Ephemeral 1859 1.3% 803991 432 3193
|
||||
22734 Ephemeral 1629 1.2% 695583 427 427
|
||||
10002 Relay list 1604 1.1% 4950855 3087 42385
|
||||
7 Reaction 1435 1.0% 847949 591 1287
|
||||
29333 Ephemeral 1408 1.0% 690797 491 492
|
||||
24133 Ephemeral 1375 1.0% 1890802 1375 38738
|
||||
37195 Addressable 1338 1.0% 1004351 751 934
|
||||
25555 Ephemeral 1181 0.8% 5929927 5021 17075
|
||||
22690 Ephemeral 1081 0.8% 467584 433 3184
|
||||
22601 Ephemeral 990 0.7% 423742 428 429
|
||||
22850 Ephemeral 947 0.7% 407208 430 430
|
||||
4515 Unknown 868 0.6% 1923082 2216 55180
|
||||
23334 Ephemeral 859 0.6% 374353 436 439
|
||||
22655 Ephemeral 821 0.6% 351388 428 428
|
||||
6 Repost 811 0.6% 771135 951 10128
|
||||
22795 Ephemeral 778 0.6% 1060284 1363 3201
|
||||
4 Encrypted DM 767 0.5% 725743 946 19618
|
||||
22720 Ephemeral 749 0.5% 1079163 1441 3249
|
||||
22876 Ephemeral 724 0.5% 308478 426 431
|
||||
22676 Ephemeral 696 0.5% 297193 427 428
|
||||
22913 Ephemeral 678 0.5% 294988 435 3201
|
||||
22689 Ephemeral 663 0.5% 1094513 1651 5926
|
||||
22927 Ephemeral 607 0.4% 1017238 1676 1876
|
||||
22236 Ephemeral 595 0.4% 446548 751 814
|
||||
22911 Ephemeral 569 0.4% 951997 1673 1880
|
||||
22943 Ephemeral 563 0.4% 249401 443 1658
|
||||
22603 Ephemeral 543 0.4% 231317 426 427
|
||||
22743 Ephemeral 542 0.4% 231978 428 430
|
||||
22695 Ephemeral 538 0.4% 871272 1619 1850
|
||||
1059 Gift wrap seal 535 0.4% 2557163 4780 55121
|
||||
22842 Ephemeral 528 0.4% 882417 1671 1853
|
||||
24242 Ephemeral 527 0.4% 305133 579 579
|
||||
13194 NWC info 505 0.4% 259258 513 514
|
||||
22730 Ephemeral 474 0.3% 418919 884 1517
|
||||
11998 Unknown 449 0.3% 208257 464 465
|
||||
23337 Ephemeral 446 0.3% 252660 567 586
|
||||
7368 Unknown 443 0.3% 459822 1038 1059
|
||||
22816 Ephemeral 410 0.3% 183597 448 3196
|
||||
30315 User status 406 0.3% 280885 692 1166
|
||||
22456 Ephemeral 403 0.3% 196962 489 790
|
||||
22815 Ephemeral 386 0.3% 620350 1607 3199
|
||||
20387 Ephemeral 368 0.3% 189152 514 514
|
||||
20000 Ephemeral 351 0.3% 237048 675 17065
|
||||
5300 Unknown 350 0.2% 213715 611 701
|
||||
22774 Ephemeral 349 0.2% 149372 428 428
|
||||
31990 App handler info 343 0.2% 389821 1137 6861
|
||||
3 Follow list 325 0.2% 4492770 13824 58982
|
||||
23003 Ephemeral 317 0.2% 135676 428 428
|
||||
38502 Addressable 295 0.2% 113575 385 385
|
||||
1985 Unknown 287 0.2% 189598 661 4834
|
||||
22807 Ephemeral 279 0.2% 119596 429 430
|
||||
25050 Ephemeral 272 0.2% 113448 417 1362
|
||||
4004 Unknown 270 0.2% 315630 1169 1169
|
||||
20004 Ephemeral 233 0.2% 124155 533 549
|
||||
35000 Addressable 208 0.1% 160992 774 774
|
||||
22613 Ephemeral 208 0.1% 143395 689 1134
|
||||
22592 Ephemeral 201 0.1% 93351 464 3193
|
||||
20333 Ephemeral 197 0.1% 156942 797 798
|
||||
31950 Addressable 196 0.1% 170818 872 937
|
||||
22632 Ephemeral 195 0.1% 85266 437 3204
|
||||
9735 Zap receipt 193 0.1% 370520 1920 4167
|
||||
10100 Unknown 188 0.1% 279911 1489 3826
|
||||
30311 Addressable 187 0.1% 202343 1082 1197
|
||||
24913 Ephemeral 179 0.1% 79157 442 582
|
||||
23004 Ephemeral 179 0.1% 77149 431 431
|
||||
22854 Ephemeral 174 0.1% 137235 789 1660
|
||||
30384 Addressable 166 0.1% 85437 515 556
|
||||
22891 Ephemeral 164 0.1% 235679 1437 3243
|
||||
10050 DM relays 160 0.1% 72634 454 592
|
||||
30023 Long-form article 144 0.1% 954406 6628 13594
|
||||
6300 Unknown 144 0.1% 880738 6116 17462
|
||||
445 Encrypted group msg 140 0.1% 350204 2501 4134
|
||||
10000 Mute list 136 0.1% 274284 2017 27742
|
||||
22693 Ephemeral 130 0.1% 101515 781 2619
|
||||
30166 Addressable 128 0.1% 66754 522 808
|
||||
4244 Unknown 127 0.1% 71628 564 564
|
||||
38503 Addressable 125 0.1% 68916 551 552
|
||||
20787 Ephemeral 124 0.1% 181428 1463 2478
|
||||
22455 Ephemeral 112 0.1% 183137 1635 1847
|
||||
22616 Ephemeral 111 0.1% 98460 887 3453
|
||||
22543 Ephemeral 107 0.1% 172800 1615 1849
|
||||
22885 Ephemeral 106 0.1% 102539 967 3524
|
||||
22672 Ephemeral 104 0.1% 174090 1674 1849
|
||||
22717 Ephemeral 99 0.1% 120874 1221 1849
|
||||
22929 Ephemeral 90 0.1% 88203 980 1517
|
||||
10777 Unknown 89 0.1% 43507 489 489
|
||||
22829 Ephemeral 89 0.1% 43243 486 3200
|
||||
30088 Addressable 87 0.1% 162094 1863 1871
|
||||
30091 Addressable 85 0.1% 52311 615 629
|
||||
21584 Ephemeral 83 0.1% 36413 439 439
|
||||
38385 Addressable 82 0.1% 111350 1358 1496
|
||||
22864 Ephemeral 82 0.1% 56300 687 1223
|
||||
39101 Addressable 81 0.1% 43173 533 533
|
||||
22751 Ephemeral 81 0.1% 73608 909 4083
|
||||
1111 Comment 79 0.1% 93490 1183 2457
|
||||
3927 Unknown 78 0.1% 41585 533 544
|
||||
10011 Unknown 77 0.1% 33123 430 431
|
||||
21060 Ephemeral 74 0.1% 42180 570 570
|
||||
21617 Ephemeral 73 0.1% 36119 495 495
|
||||
33334 Addressable 70 0.0% 58170 831 831
|
||||
30380 Addressable 66 0.0% 29964 454 454
|
||||
38383 Addressable 66 0.0% 59966 909 3211
|
||||
38384 Addressable 62 0.0% 46066 743 743
|
||||
38500 Addressable 60 0.0% 42716 712 713
|
||||
20384 Ephemeral 59 0.0% 37701 639 639
|
||||
30089 Chunked data 53 0.0% 614992 11604 44372
|
||||
1002 Unknown 53 0.0% 48203 909 1011
|
||||
22840 Ephemeral 52 0.0% 22285 429 430
|
||||
23066 Ephemeral 50 0.0% 43751 875 1165
|
||||
22526 Ephemeral 50 0.0% 21469 429 430
|
||||
22405 Ephemeral 47 0.0% 20886 444 445
|
||||
23042 Ephemeral 44 0.0% 18876 429 429
|
||||
22514 Ephemeral 44 0.0% 18832 428 428
|
||||
22748 Ephemeral 44 0.0% 18874 429 429
|
||||
31510 Addressable 43 0.0% 42075 978 982
|
||||
3079 Unknown 42 0.0% 38178 909 909
|
||||
4243 Unknown 42 0.0% 23688 564 564
|
||||
22862 Ephemeral 41 0.0% 17578 429 429
|
||||
22475 Ephemeral 40 0.0% 43786 1095 3923
|
||||
22721 Ephemeral 40 0.0% 23480 587 1842
|
||||
22674 Ephemeral 39 0.0% 17992 461 1661
|
||||
4245 Unknown 39 0.0% 17316 444 444
|
||||
30080 Addressable 39 0.0% 37674 966 1011
|
||||
30443 Addressable 38 0.0% 46231 1217 1547
|
||||
30515 Addressable 38 0.0% 201552 5304 5304
|
||||
22212 Ephemeral 37 0.0% 16440 444 445
|
||||
10003 Bookmarks 37 0.0% 420277 11359 56461
|
||||
38225 Addressable 35 0.0% 33592 960 1021
|
||||
30815 Addressable 34 0.0% 1276156 37534 37534
|
||||
1984 Report 34 0.0% 22174 652 667
|
||||
22753 Ephemeral 33 0.0% 40204 1218 3766
|
||||
30618 Addressable 32 0.0% 45089 1409 8804
|
||||
1040 Unknown 32 0.0% 36596 1144 5164
|
||||
3434 Unknown 30 0.0% 20382 679 705
|
||||
7000 Unknown 28 0.0% 21752 777 822
|
||||
30385 Addressable 28 0.0% 22344 798 981
|
||||
33301 Addressable 27 0.0% 45586 1688 2162
|
||||
16 Generic repost 27 0.0% 21778 807 1604
|
||||
22119 Ephemeral 25 0.0% 21137 845 846
|
||||
22120 Ephemeral 25 0.0% 27207 1088 1128
|
||||
24421 Ephemeral 24 0.0% 12384 516 516
|
||||
22525 Ephemeral 24 0.0% 42802 1783 4259
|
||||
22756 Ephemeral 24 0.0% 32806 1367 3198
|
||||
31124 Addressable 23 0.0% 28396 1235 1445
|
||||
22733 Ephemeral 23 0.0% 15376 669 1224
|
||||
30617 Addressable 23 0.0% 25047 1089 1089
|
||||
22649 Ephemeral 22 0.0% 9459 430 430
|
||||
22680 Ephemeral 21 0.0% 14310 681 3193
|
||||
22874 Ephemeral 21 0.0% 24675 1175 1850
|
||||
31339 Addressable 21 0.0% 30870 1470 1470
|
||||
30000 Addressable 19 0.0% 16519 869 3185
|
||||
22688 Ephemeral 19 0.0% 18248 960 3195
|
||||
31991 Addressable 19 0.0% 8759 461 461
|
||||
39842 Addressable 18 0.0% 19919 1107 1385
|
||||
10312 Unknown 18 0.0% 9219 512 559
|
||||
7403 Unknown 17 0.0% 8336 490 491
|
||||
30280 Addressable 17 0.0% 8721 513 513
|
||||
14 Unknown 16 0.0% 17438 1090 1531
|
||||
31000 Addressable 16 0.0% 9716 607 616
|
||||
22645 Ephemeral 16 0.0% 9285 580 1838
|
||||
2333 Unknown 15 0.0% 10074 672 722
|
||||
34236 Addressable 15 0.0% 211139 14076 26491
|
||||
30079 Addressable 15 0.0% 47271 3151 4574
|
||||
23333 Ephemeral 15 0.0% 8754 584 634
|
||||
23194 NWC request 15 0.0% 8952 597 1086
|
||||
22778 Ephemeral 15 0.0% 6421 428 429
|
||||
38111 Addressable 14 0.0% 10495 750 752
|
||||
22747 Ephemeral 13 0.0% 8895 684 1657
|
||||
25000 Ephemeral 13 0.0% 23498 1808 2214
|
||||
22506 Ephemeral 13 0.0% 23855 1835 1841
|
||||
1000 Unknown 13 0.0% 21880 1683 1790
|
||||
26428 Ephemeral 12 0.0% 10516 876 877
|
||||
23195 NWC response 12 0.0% 9184 765 1183
|
||||
1078 Unknown 12 0.0% 169653 14138 14241
|
||||
30554 Addressable 12 0.0% 7292 608 608
|
||||
22361 Ephemeral 11 0.0% 4708 428 428
|
||||
30421 Addressable 11 0.0% 11427 1039 1066
|
||||
30085 Addressable 11 0.0% 7227 657 659
|
||||
10063 Unknown 11 0.0% 5982 544 627
|
||||
22402 Ephemeral 11 0.0% 4683 426 443
|
||||
39015 Addressable 11 0.0% 7656 696 696
|
||||
11125 Unknown 10 0.0% 10262 1026 1916
|
||||
30113 Addressable 10 0.0% 6987 699 770
|
||||
33051 Addressable 10 0.0% 5206 521 522
|
||||
30087 Addressable 9 0.0% 65925 7325 7325
|
||||
30213 Addressable 9 0.0% 5662 629 637
|
||||
1018 Unknown 8 0.0% 4500 562 677
|
||||
30090 Addressable 8 0.0% 12120 1515 1515
|
||||
1050 Unknown 8 0.0% 3496 437 437
|
||||
22619 Ephemeral 8 0.0% 11165 1396 1842
|
||||
10051 Unknown 7 0.0% 3205 458 489
|
||||
26429 Ephemeral 7 0.0% 3437 491 491
|
||||
38421 Addressable 7 0.0% 7485 1069 1070
|
||||
39019 Addressable 6 0.0% 5766 961 961
|
||||
9842 Unknown 6 0.0% 6742 1124 1260
|
||||
20200 Ephemeral 6 0.0% 2946 491 491
|
||||
25742 Ephemeral 6 0.0% 11756 1959 7334
|
||||
30081 Addressable 6 0.0% 8220 1370 1370
|
||||
20 Picture 6 0.0% 4558 760 852
|
||||
20201 Ephemeral 6 0.0% 2946 491 491
|
||||
22722 Ephemeral 5 0.0% 7756 1551 1660
|
||||
7336 Unknown 5 0.0% 3280 656 656
|
||||
22825 Ephemeral 5 0.0% 5660 1132 1848
|
||||
13196 Unknown 5 0.0% 3280 656 656
|
||||
9841 Unknown 5 0.0% 14029 2806 4468
|
||||
23336 Ephemeral 5 0.0% 3285 657 657
|
||||
1063 File metadata 5 0.0% 4593 919 941
|
||||
31344 Addressable 4 0.0% 2500 625 625
|
||||
31986 Addressable 4 0.0% 2372 593 593
|
||||
22432 Ephemeral 4 0.0% 5412 1353 1843
|
||||
31985 Addressable 4 0.0% 2534 634 667
|
||||
10015 Unknown 3 0.0% 11266 3755 4578
|
||||
1010 Unknown 3 0.0% 2505 835 1152
|
||||
37779 Addressable 3 0.0% 1569 523 523
|
||||
21734 Ephemeral 3 0.0% 1131 377 377
|
||||
22671 Ephemeral 3 0.0% 1281 427 427
|
||||
31343 Addressable 2 0.0% 53115 26558 45456
|
||||
16767 Unknown 2 0.0% 1974 987 987
|
||||
1058 Unknown 2 0.0% 1186 593 593
|
||||
22724 Ephemeral 2 0.0% 2103 1052 1674
|
||||
30005 Addressable 2 0.0% 11351 5676 9817
|
||||
21724 Ephemeral 2 0.0% 754 377 377
|
||||
20177 Ephemeral 2 0.0% 851 426 426
|
||||
2003 Unknown 2 0.0% 8711 4356 7015
|
||||
30003 Addressable 2 0.0% 778 389 389
|
||||
25582 Ephemeral 2 0.0% 4500 2250 3690
|
||||
38422 Addressable 2 0.0% 60198 30099 30212
|
||||
22387 Ephemeral 2 0.0% 887 444 444
|
||||
1618 Unknown 1 0.0% 2168 2168 2168
|
||||
10001 Pinned notes 1 0.0% 710 710 710
|
||||
30758 Addressable 1 0.0% 436 436 436
|
||||
32267 Addressable 1 0.0% 1693 1693 1693
|
||||
1069 Unknown 1 0.0% 757 757 757
|
||||
31345 Addressable 1 0.0% 8666 8666 8666
|
||||
21840 Ephemeral 1 0.0% 377 377 377
|
||||
21764 Ephemeral 1 0.0% 377 377 377
|
||||
31353 Addressable 1 0.0% 737 737 737
|
||||
1808 Unknown 1 0.0% 1696 1696 1696
|
||||
31633 Addressable 1 0.0% 592 592 592
|
||||
30066 Addressable 1 0.0% 675 675 675
|
||||
30063 Addressable 1 0.0% 2891 2891 2891
|
||||
21711 Ephemeral 1 0.0% 377 377 377
|
||||
|
||||
=== Raw Relay Response Log ===
|
||||
# Cache-All Feasibility Test - Raw Relay Log
|
||||
# Started: Sun Aug 2 15:24:51 2026
|
||||
# Config: cache_all_test_config.jsonc
|
||||
# Duration: 86400 seconds
|
||||
[2026-08-02 15:25:27] [RELAY] wss://laantungir.net STATUS: ?
|
||||
[2026-08-02 15:25:27] [RELAY] wss://nos.lol STATUS: connected
|
||||
[2026-08-02 15:25:27] [RELAY] wss://nostr-pub.wellorder.net STATUS: connected
|
||||
[2026-08-02 15:25:27] [RELAY] wss://nostr.mom STATUS: connected
|
||||
[2026-08-02 15:25:27] [RELAY] wss://nostr.oxtr.dev STATUS: connected
|
||||
[2026-08-02 15:25:27] [RELAY] wss://offchain.pub STATUS: connected
|
||||
[2026-08-02 15:25:27] [RELAY] wss://premium.primal.net STATUS: connected
|
||||
[2026-08-02 15:25:27] [RELAY] wss://relay.damus.io STATUS: ?
|
||||
[2026-08-02 15:25:27] [RELAY] wss://relay.ditto.pub STATUS: connected
|
||||
[2026-08-02 15:25:27] [RELAY] wss://relay.divine.video STATUS: connected
|
||||
[2026-08-02 15:25:27] [RELAY] wss://relay.momostr.pink STATUS: connected
|
||||
[2026-08-02 15:25:27] [RELAY] wss://relay.mostr.pub STATUS: connected
|
||||
[2026-08-02 15:25:27] [RELAY] wss://relay.nostrplebs.com STATUS: connected
|
||||
[2026-08-02 15:25:27] [RELAY] wss://relay.primal.net STATUS: connected
|
||||
[2026-08-02 15:25:27] [RELAY] wss://theforest.nostr1.com STATUS: connected
|
||||
[2026-08-02 15:25:39] [RELAY] wss://relay.damus.io CONNECTED
|
||||
[2026-08-02 15:26:24] [RELAY] wss://relay.mostr.pub DISCONNECTED: Connection state transitioned to 2 during poll
|
||||
[2026-08-02 15:26:24] [RELAY] wss://relay.mostr.pub CONNECTED
|
||||
[2026-08-02 15:26:46] [RELAY] wss://nos.lol DISCONNECTED: Connection state transitioned to 2 during poll
|
||||
[2026-08-02 15:26:46] [RELAY] wss://nos.lol CONNECTED
|
||||
[2026-08-02 15:27:10] [RELAY] wss://relay.primal.net DISCONNECTED:
|
||||
[2026-08-02 15:27:10] [RELAY] wss://relay.primal.net CONNECTED
|
||||
[2026-08-02 15:27:40] [RELAY] wss://relay.primal.net DISCONNECTED:
|
||||
[2026-08-02 15:27:40] [RELAY] wss://relay.primal.net CONNECTED
|
||||
[2026-08-02 15:28:10] [RELAY] wss://relay.primal.net DISCONNECTED:
|
||||
[2026-08-02 15:28:10] [RELAY] wss://relay.primal.net CONNECTED
|
||||
[2026-08-02 15:28:40] [RELAY] wss://relay.primal.net DISCONNECTED:
|
||||
[2026-08-02 15:28:40] [RELAY] wss://relay.primal.net CONNECTED
|
||||
[2026-08-02 15:28:46] [RELAY] wss://nos.lol DISCONNECTED:
|
||||
[2026-08-02 15:28:46] [RELAY] wss://nos.lol CONNECTED
|
||||
[2026-08-02 15:29:16] [RELAY] wss://nos.lol DISCONNECTED:
|
||||
[2026-08-02 15:29:16] [RELAY] wss://nos.lol CONNECTED
|
||||
[2026-08-02 15:29:40] [RELAY] wss://relay.primal.net DISCONNECTED:
|
||||
[2026-08-02 15:29:40] [RELAY] wss://relay.primal.net CONNECTED
|
||||
[2026-08-02 15:30:10] [RELAY] wss://relay.primal.net DISCONNECTED:
|
||||
[2026-08-02 15:30:10] [RELAY] wss://relay.primal.net CONNECTED
|
||||
[2026-08-02 15:30:16] [RELAY] wss://nos.lol DISCONNECTED:
|
||||
[2026-08-02 15:30:16] [RELAY] wss://nos.lol CONNECTED
|
||||
[2026-08-02 15:31:10] [RELAY] wss://relay.primal.net DISCONNECTED:
|
||||
[2026-08-02 15:31:10] [RELAY] wss://relay.primal.net CONNECTED
|
||||
[2026-08-02 15:31:40] [RELAY] wss://relay.primal.net DISCONNECTED:
|
||||
[2026-08-02 15:31:40] [RELAY] wss://relay.primal.net CONNECTED
|
||||
[2026-08-02 15:32:10] [RELAY] wss://relay.primal.net DISCONNECTED:
|
||||
[2026-08-02 15:32:10] [RELAY] wss://relay.primal.net CONNECTED
|
||||
[2026-08-02 15:32:37] [RELAY] wss://nos.lol DISCONNECTED: Connection state transitioned to 2 during poll
|
||||
[2026-08-02 15:32:38] [RELAY] wss://nos.lol CONNECTED
|
||||
[2026-08-02 15:33:19] [RELAY] wss://nos.lol DISCONNECTED: Connection state transitioned to 2 during poll
|
||||
[2026-08-02 15:33:19] [RELAY] wss://nos.lol CONNECTED
|
||||
[2026-08-02 15:33:40] [RELAY] wss://relay.primal.net DISCONNECTED:
|
||||
[2026-08-02 15:33:40] [RELAY] wss://relay.primal.net CONNECTED
|
||||
[2026-08-02 15:33:49] [RELAY] wss://nos.lol DISCONNECTED:
|
||||
[2026-08-02 15:33:49] [RELAY] wss://nos.lol CONNECTED
|
||||
[2026-08-02 15:34:10] [RELAY] wss://relay.primal.net DISCONNECTED:
|
||||
[2026-08-02 15:34:10] [RELAY] wss://relay.primal.net CONNECTED
|
||||
[2026-08-02 15:34:40] [RELAY] wss://relay.primal.net DISCONNECTED:
|
||||
[2026-08-02 15:34:40] [RELAY] wss://relay.primal.net CONNECTED
|
||||
[2026-08-02 15:35:10] [RELAY] wss://relay.primal.net DISCONNECTED:
|
||||
[2026-08-02 15:35:10] [RELAY] wss://relay.primal.net CONNECTED
|
||||
[2026-08-02 15:35:11] [RELAY] wss://nos.lol DISCONNECTED: Connection state transitioned to 2 during poll
|
||||
[2026-08-02 15:35:11] [RELAY] wss://nos.lol CONNECTED
|
||||
[2026-08-02 15:35:12] [RELAY] wss://relay.mostr.pub DISCONNECTED: Connection state transitioned to 2 during poll
|
||||
[2026-08-02 15:35:13] [RELAY] wss://relay.mostr.pub CONNECTED
|
||||
[2026-08-02 15:35:40] [RELAY] wss://relay.primal.net DISCONNECTED:
|
||||
[2026-08-02 15:35:40] [RELAY] wss://relay.primal.net CONNECTED
|
||||
[2026-08-02 15:35:41] [RELAY] wss://nos.lol DISCONNECTED:
|
||||
[2026-08-02 15:35:41] [RELAY] wss://nos.lol CONNECTED
|
||||
[2026-08-02 15:35:54] [RELAY] wss://nostr.oxtr.dev DISCONNECTED: Connection state transitioned to 2 during poll
|
||||
[2026-08-02 15:35:55] [RELAY] wss://nostr.oxtr.dev CONNECTED
|
||||
[2026-08-02 15:37:10] [RELAY] wss://relay.primal.net DISCONNECTED:
|
||||
[2026-08-02 15:37:10] [RELAY] wss://relay.primal.net CONNECTED
|
||||
[2026-08-02 15:37:40] [RELAY] wss://relay.primal.net DISCONNECTED:
|
||||
[2026-08-02 15:37:40] [RELAY] wss://relay.primal.net CONNECTED
|
||||
[2026-08-02 15:38:11] [RELAY] wss://nos.lol DISCONNECTED:
|
||||
[2026-08-02 15:38:11] [RELAY] wss://nos.lol CONNECTED
|
||||
[2026-08-02 15:38:34] [RELAY] wss://relay.mostr.pub DISCONNECTED: Connection state transitioned to 2 during poll
|
||||
[2026-08-02 15:38:35] [RELAY] wss://relay.mostr.pub CONNECTED
|
||||
[2026-08-02 15:39:10] [RELAY] wss://relay.primal.net DISCONNECTED:
|
||||
[2026-08-02 15:39:10] [RELAY] wss://relay.primal.net CONNECTED
|
||||
[2026-08-02 15:39:17] [RELAY] wss://nos.lol DISCONNECTED: Connection state transitioned to 2 during poll
|
||||
[2026-08-02 15:39:18] [RELAY] wss://nos.lol CONNECTED
|
||||
[2026-08-02 15:39:32] [RELAY] wss://relay.momostr.pink DISCONNECTED: Connection state transitioned to 2 during poll
|
||||
[2026-08-02 15:39:32] [RELAY] wss://relay.momostr.pink CONNECTED
|
||||
[2026-08-02 15:39:34] [RELAY] wss://relay.momostr.pink DISCONNECTED: Connection state transitioned to 2 during poll
|
||||
[2026-08-02 15:39:34] [RELAY] wss://relay.momostr.pink CONNECTED
|
||||
[2026-08-02 15:39:59] [RELAY] wss://nos.lol DISCONNECTED: Connection state transitioned to 2 during poll
|
||||
[2026-08-02 15:39:59] [RELAY] wss://nos.lol CONNECTED
|
||||
[2026-08-02 15:40:07] [RELAY] wss://relay.momostr.pink DISCONNECTED: Connection state transitioned to 2 during poll
|
||||
[2026-08-02 15:40:07] [RELAY] wss://relay.momostr.pink CONNECTED
|
||||
[2026-08-02 15:40:10] [RELAY] wss://relay.primal.net DISCONNECTED:
|
||||
[2026-08-02 15:40:10] [RELAY] wss://relay.primal.net CONNECTED
|
||||
[2026-08-02 15:40:40] [RELAY] wss://relay.momostr.pink DISCONNECTED: Connection state transitioned to 2 during poll
|
||||
[2026-08-02 15:40:41] [RELAY] wss://relay.momostr.pink CONNECTED
|
||||
[2026-08-02 15:41:29] [RELAY] wss://nos.lol DISCONNECTED:
|
||||
[2026-08-02 15:41:29] [RELAY] wss://nos.lol CONNECTED
|
||||
[2026-08-02 15:41:39] [RELAY] wss://nos.lol DISCONNECTED: Connection state transitioned to 2 during poll
|
||||
[2026-08-02 15:41:40] [RELAY] wss://nos.lol CONNECTED
|
||||
[2026-08-02 15:41:40] [RELAY] wss://relay.primal.net DISCONNECTED:
|
||||
[2026-08-02 15:41:40] [RELAY] wss://relay.primal.net CONNECTED
|
||||
[2026-08-02 15:42:10] [RELAY] wss://relay.primal.net DISCONNECTED:
|
||||
[2026-08-02 15:42:10] [RELAY] wss://relay.primal.net CONNECTED
|
||||
[2026-08-02 15:42:51] [RELAY] wss://nos.lol DISCONNECTED:
|
||||
[2026-08-02 15:42:51] [RELAY] wss://nos.lol CONNECTED
|
||||
[2026-08-02 15:44:41] [RELAY] wss://nos.lol DISCONNECTED: Connection state transitioned to 2 during poll
|
||||
[2026-08-02 15:44:41] [RELAY] wss://nos.lol CONNECTED
|
||||
[2026-08-02 15:45:00] [RELAY] wss://relay.momostr.pink DISCONNECTED: Connection state transitioned to 2 during poll
|
||||
[2026-08-02 15:45:01] [RELAY] wss://relay.momostr.pink CONNECTED
|
||||
[2026-08-02 15:45:07] [RELAY] wss://relay.ditto.pub DISCONNECTED:
|
||||
[2026-08-02 15:45:07] [RELAY] wss://relay.ditto.pub CONNECTED
|
||||
[2026-08-02 15:45:10] [RELAY] wss://relay.primal.net DISCONNECTED:
|
||||
[2026-08-02 15:45:10] [RELAY] wss://relay.primal.net CONNECTED
|
||||
[2026-08-02 15:45:26] [RELAY] wss://nos.lol DISCONNECTED: Connection state transitioned to 2 during poll
|
||||
[2026-08-02 15:45:27] [RELAY] wss://nos.lol CONNECTED
|
||||
[2026-08-02 15:45:37] [RELAY] wss://relay.ditto.pub DISCONNECTED:
|
||||
[2026-08-02 15:45:37] [RELAY] wss://relay.ditto.pub CONNECTED
|
||||
[2026-08-02 15:46:07] [RELAY] wss://relay.ditto.pub DISCONNECTED:
|
||||
[2026-08-02 15:46:07] [RELAY] wss://relay.ditto.pub CONNECTED
|
||||
[2026-08-02 15:46:08] [RELAY] wss://nos.lol DISCONNECTED: Connection state transitioned to 2 during poll
|
||||
[2026-08-02 15:46:08] [RELAY] wss://nos.lol CONNECTED
|
||||
[2026-08-02 15:46:10] [RELAY] wss://relay.primal.net DISCONNECTED:
|
||||
[2026-08-02 15:46:10] [RELAY] wss://relay.primal.net CONNECTED
|
||||
[2026-08-02 15:46:37] [RELAY] wss://relay.ditto.pub DISCONNECTED:
|
||||
[2026-08-02 15:46:37] [RELAY] wss://relay.ditto.pub CONNECTED
|
||||
[2026-08-02 15:46:38] [RELAY] wss://nos.lol DISCONNECTED:
|
||||
[2026-08-02 15:46:38] [RELAY] wss://nos.lol CONNECTED
|
||||
[2026-08-02 15:46:40] [RELAY] wss://relay.primal.net DISCONNECTED:
|
||||
[2026-08-02 15:46:40] [RELAY] wss://relay.primal.net CONNECTED
|
||||
[2026-08-02 15:46:51] [RELAY] wss://relay.primal.net DISCONNECTED: Connection state transitioned to 2 during poll
|
||||
[2026-08-02 15:46:52] [RELAY] wss://relay.primal.net CONNECTED
|
||||
[2026-08-02 15:47:00] [RELAY] wss://nostr.oxtr.dev DISCONNECTED: Connection state transitioned to 2 during poll
|
||||
[2026-08-02 15:47:01] [RELAY] wss://nostr.oxtr.dev CONNECTED
|
||||
[2026-08-02 15:47:01] [RELAY] wss://nostr.oxtr.dev DISCONNECTED: Connection state transitioned to 2 during poll
|
||||
[2026-08-02 15:47:02] [RELAY] wss://nostr.oxtr.dev CONNECTED
|
||||
[2026-08-02 15:47:07] [RELAY] wss://relay.ditto.pub DISCONNECTED:
|
||||
[2026-08-02 15:47:07] [RELAY] wss://relay.ditto.pub CONNECTED
|
||||
[2026-08-02 15:47:07] [RELAY] wss://nostr.oxtr.dev DISCONNECTED: Connection state transitioned to 2 during poll
|
||||
[2026-08-02 15:47:08] [RELAY] wss://nostr.oxtr.dev CONNECTED
|
||||
[2026-08-02 15:47:08] [RELAY] wss://nostr.oxtr.dev DISCONNECTED: Connection state transitioned to 2 during poll
|
||||
[2026-08-02 15:47:09] [RELAY] wss://nostr.oxtr.dev CONNECTED
|
||||
[2026-08-02 15:47:17] [RELAY] wss://nos.lol DISCONNECTED: Connection state transitioned to 2 during poll
|
||||
[2026-08-02 15:47:18] [RELAY] wss://nos.lol CONNECTED
|
||||
[2026-08-02 15:47:18] [RELAY] wss://nos.lol DISCONNECTED: Connection state transitioned to 2 during poll
|
||||
[2026-08-02 15:47:19] [RELAY] wss://nos.lol CONNECTED
|
||||
[2026-08-02 15:47:33] [RELAY] wss://relay.primal.net DISCONNECTED: Connection state transitioned to 2 during poll
|
||||
[2026-08-02 15:47:33] [RELAY] wss://relay.primal.net CONNECTED
|
||||
[2026-08-02 15:48:33] [RELAY] wss://relay.primal.net DISCONNECTED:
|
||||
[2026-08-02 15:48:33] [RELAY] wss://relay.primal.net CONNECTED
|
||||
[2026-08-02 15:48:41] [RELAY] wss://relay.momostr.pink DISCONNECTED: Connection state transitioned to 2 during poll
|
||||
[2026-08-02 15:48:42] [RELAY] wss://relay.momostr.pink CONNECTED
|
||||
[2026-08-02 15:49:03] [RELAY] wss://relay.primal.net DISCONNECTED:
|
||||
[2026-08-02 15:49:03] [RELAY] wss://relay.primal.net CONNECTED
|
||||
[2026-08-02 15:49:33] [RELAY] wss://relay.primal.net DISCONNECTED:
|
||||
[2026-08-02 15:49:33] [RELAY] wss://relay.primal.net CONNECTED
|
||||
[2026-08-02 15:49:37] [RELAY] wss://relay.ditto.pub DISCONNECTED:
|
||||
[2026-08-02 15:49:37] [RELAY] wss://relay.ditto.pub CONNECTED
|
||||
[2026-08-02 15:50:02] [RELAY] wss://nos.lol DISCONNECTED:
|
||||
[2026-08-02 15:50:02] [RELAY] wss://nos.lol CONNECTED
|
||||
[2026-08-02 15:50:05] [RELAY] wss://relay.ditto.pub DISCONNECTED: Connection state transitioned to 2 during poll
|
||||
[2026-08-02 15:50:05] [RELAY] wss://relay.ditto.pub CONNECTED
|
||||
[2026-08-02 15:50:33] [RELAY] wss://relay.primal.net DISCONNECTED:
|
||||
[2026-08-02 15:50:33] [RELAY] wss://relay.primal.net CONNECTED
|
||||
[2026-08-02 15:51:18] [RELAY] wss://nos.lol DISCONNECTED: Connection state transitioned to 2 during poll
|
||||
[2026-08-02 15:51:19] [RELAY] wss://nos.lol CONNECTED
|
||||
[2026-08-02 15:51:33] [RELAY] wss://relay.primal.net DISCONNECTED:
|
||||
[2026-08-02 15:51:33] [RELAY] wss://relay.primal.net CONNECTED
|
||||
[2026-08-02 15:52:00] [RELAY] wss://nos.lol DISCONNECTED: Connection state transitioned to 2 during poll
|
||||
[2026-08-02 15:52:00] [RELAY] wss://nos.lol CONNECTED
|
||||
[2026-08-02 15:52:30] [RELAY] wss://nos.lol DISCONNECTED:
|
||||
[2026-08-02 15:52:30] [RELAY] wss://nos.lol CONNECTED
|
||||
[2026-08-02 15:52:33] [RELAY] wss://relay.primal.net DISCONNECTED:
|
||||
[2026-08-02 15:52:33] [RELAY] wss://relay.primal.net CONNECTED
|
||||
[2026-08-02 15:52:33] [RELAY] wss://premium.primal.net DISCONNECTED: Connection state transitioned to 2 during poll
|
||||
[2026-08-02 15:52:34] [RELAY] wss://premium.primal.net CONNECTED
|
||||
[2026-08-02 15:52:34] [RELAY] wss://premium.primal.net DISCONNECTED: Connection state transitioned to 2 during poll
|
||||
[2026-08-02 15:52:35] [RELAY] wss://premium.primal.net CONNECTED
|
||||
[2026-08-02 15:53:00] [RELAY] wss://nos.lol DISCONNECTED:
|
||||
[2026-08-02 15:53:00] [RELAY] wss://nos.lol CONNECTED
|
||||
[2026-08-02 15:53:30] [RELAY] wss://nos.lol DISCONNECTED:
|
||||
[2026-08-02 15:53:30] [RELAY] wss://nos.lol CONNECTED
|
||||
[2026-08-02 15:53:30] [RELAY] wss://nostr.oxtr.dev DISCONNECTED: Connection state transitioned to 2 during poll
|
||||
[2026-08-02 15:53:30] [RELAY] wss://nostr.oxtr.dev CONNECTED
|
||||
[2026-08-02 15:53:33] [RELAY] wss://relay.primal.net DISCONNECTED:
|
||||
[2026-08-02 15:53:33] [RELAY] wss://relay.primal.net CONNECTED
|
||||
[2026-08-02 15:54:19] [RELAY] wss://nos.lol DISCONNECTED: Connection state transitioned to 2 during poll
|
||||
[2026-08-02 15:54:19] [RELAY] wss://nos.lol CONNECTED
|
||||
[2026-08-02 15:54:54] [RELAY] wss://premium.primal.net DISCONNECTED: Connection state transitioned to 2 during poll
|
||||
[2026-08-02 15:54:55] [RELAY] wss://premium.primal.net CONNECTED
|
||||
[2026-08-02 15:54:56] [RELAY] wss://premium.primal.net DISCONNECTED: Connection state transitioned to 2 during poll
|
||||
[2026-08-02 15:54:56] [RELAY] wss://premium.primal.net CONNECTED
|
||||
[2026-08-02 15:54:57] [RELAY] wss://premium.primal.net DISCONNECTED: Connection state transitioned to 2 during poll
|
||||
[2026-08-02 15:54:58] [RELAY] wss://premium.primal.net CONNECTED
|
||||
[2026-08-02 15:54:58] [RELAY] wss://premium.primal.net DISCONNECTED: Connection state transitioned to 2 during poll
|
||||
[2026-08-02 15:54:59] [RELAY] wss://premium.primal.net CONNECTED
|
||||
[2026-08-02 15:55:01] [RELAY] wss://premium.primal.net DISCONNECTED: Connection state transitioned to 2 during poll
|
||||
[2026-08-02 15:55:02] [RELAY] wss://premium.primal.net CONNECTED
|
||||
[2026-08-02 15:55:02] [RELAY] wss://premium.primal.net DISCONNECTED: Connection state transitioned to 2 during poll
|
||||
[2026-08-02 15:55:04] [RELAY] wss://premium.primal.net CONNECTED
|
||||
[2026-08-02 15:55:04] [RELAY] wss://relay.primal.net DISCONNECTED:
|
||||
[2026-08-02 15:55:04] [RELAY] wss://relay.primal.net CONNECTED
|
||||
[2026-08-02 15:55:04] [RELAY] wss://premium.primal.net DISCONNECTED: Connection state transitioned to 2 during poll
|
||||
[2026-08-02 15:55:05] [RELAY] wss://premium.primal.net CONNECTED
|
||||
[2026-08-02 15:55:06] [RELAY] wss://premium.primal.net DISCONNECTED: Connection state transitioned to 2 during poll
|
||||
[2026-08-02 15:55:06] [RELAY] wss://premium.primal.net CONNECTED
|
||||
[2026-08-02 15:55:07] [RELAY] wss://premium.primal.net DISCONNECTED: Connection state transitioned to 2 during poll
|
||||
[2026-08-02 15:55:07] [RELAY] wss://premium.primal.net CONNECTED
|
||||
[2026-08-02 15:55:08] [RELAY] wss://premium.primal.net DISCONNECTED: Connection state transitioned to 2 during poll
|
||||
[2026-08-02 15:55:09] [RELAY] wss://premium.primal.net CONNECTED
|
||||
[2026-08-02 15:55:09] [RELAY] wss://nos.lol DISCONNECTED: Connection state transitioned to 2 during poll
|
||||
[2026-08-02 15:55:09] [RELAY] wss://nos.lol CONNECTED
|
||||
[2026-08-02 15:55:11] [RELAY] wss://nostr.oxtr.dev DISCONNECTED: Connection state transitioned to 2 during poll
|
||||
[2026-08-02 15:55:12] [RELAY] wss://nostr.oxtr.dev CONNECTED
|
||||
[2026-08-02 15:55:33] [RELAY] wss://relay.primal.net DISCONNECTED:
|
||||
[2026-08-02 15:55:33] [RELAY] wss://relay.primal.net CONNECTED
|
||||
[2026-08-02 15:55:36] [RELAY] wss://relay.mostr.pub DISCONNECTED: Connection state transitioned to 2 during poll
|
||||
[2026-08-02 15:55:37] [RELAY] wss://relay.mostr.pub CONNECTED
|
||||
[2026-08-02 15:55:50] [RELAY] wss://nos.lol DISCONNECTED: Connection state transitioned to 2 during poll
|
||||
[2026-08-02 15:55:50] [RELAY] wss://nos.lol CONNECTED
|
||||
[2026-08-02 15:56:09] [RELAY] wss://nos.lol DISCONNECTED: Connection state transitioned to 2 during poll
|
||||
[2026-08-02 15:56:10] [RELAY] wss://nos.lol CONNECTED
|
||||
[2026-08-02 15:56:12] [RELAY] wss://premium.primal.net DISCONNECTED: Connection state transitioned to 2 during poll
|
||||
[2026-08-02 15:56:13] [RELAY] wss://premium.primal.net CONNECTED
|
||||
[2026-08-02 15:57:22] [RELAY] wss://relay.primal.net DISCONNECTED: Connection state transitioned to 2 during poll
|
||||
[2026-08-02 15:57:23] [RELAY] wss://relay.primal.net CONNECTED
|
||||
[2026-08-02 15:58:04] [RELAY] wss://relay.primal.net DISCONNECTED: Connection state transitioned to 2 during poll
|
||||
[2026-08-02 15:58:04] [RELAY] wss://relay.primal.net CONNECTED
|
||||
[2026-08-02 16:00:01] [RELAY] wss://nos.lol DISCONNECTED:
|
||||
[2026-08-02 16:00:01] [RELAY] wss://nos.lol CONNECTED
|
||||
[2026-08-02 16:00:31] [RELAY] wss://nos.lol DISCONNECTED:
|
||||
[2026-08-02 16:00:31] [RELAY] wss://nos.lol CONNECTED
|
||||
[2026-08-02 16:00:54] [RELAY] wss://relay.mostr.pub DISCONNECTED: Connection state transitioned to 2 during poll
|
||||
[2026-08-02 16:00:54] [RELAY] wss://relay.mostr.pub CONNECTED
|
||||
[2026-08-02 16:01:31] [RELAY] wss://nos.lol DISCONNECTED:
|
||||
[2026-08-02 16:01:31] [RELAY] wss://nos.lol CONNECTED
|
||||
[2026-08-02 16:01:48] [RELAY] wss://relay.primal.net DISCONNECTED: Connection state transitioned to 2 during poll
|
||||
[2026-08-02 16:01:48] [RELAY] wss://relay.primal.net CONNECTED
|
||||
[2026-08-02 16:01:55] [RELAY] wss://relay.mostr.pub DISCONNECTED: Connection state transitioned to 2 during poll
|
||||
[2026-08-02 16:01:55] [RELAY] wss://relay.mostr.pub CONNECTED
|
||||
[2026-08-02 16:02:29] [RELAY] wss://relay.primal.net DISCONNECTED: Connection state transitioned to 2 during poll
|
||||
[2026-08-02 16:02:29] [RELAY] wss://relay.primal.net CONNECTED
|
||||
[2026-08-02 16:02:59] [RELAY] wss://relay.primal.net DISCONNECTED:
|
||||
[2026-08-02 16:02:59] [RELAY] wss://relay.primal.net CONNECTED
|
||||
[2026-08-02 16:03:01] [RELAY] wss://nos.lol DISCONNECTED:
|
||||
[2026-08-02 16:03:01] [RELAY] wss://nos.lol CONNECTED
|
||||
[2026-08-02 16:03:29] [RELAY] wss://relay.primal.net DISCONNECTED:
|
||||
[2026-08-02 16:03:29] [RELAY] wss://relay.primal.net CONNECTED
|
||||
[2026-08-02 16:03:31] [RELAY] wss://nos.lol DISCONNECTED:
|
||||
[2026-08-02 16:03:31] [RELAY] wss://nos.lol CONNECTED
|
||||
[2026-08-02 16:03:59] [RELAY] wss://relay.primal.net DISCONNECTED:
|
||||
[2026-08-02 16:03:59] [RELAY] wss://relay.primal.net CONNECTED
|
||||
[2026-08-02 16:04:29] [RELAY] wss://relay.primal.net DISCONNECTED:
|
||||
[2026-08-02 16:04:29] [RELAY] wss://relay.primal.net CONNECTED
|
||||
[2026-08-02 16:04:59] [RELAY] wss://relay.primal.net DISCONNECTED:
|
||||
[2026-08-02 16:04:59] [RELAY] wss://relay.primal.net CONNECTED
|
||||
[2026-08-02 16:05:10] [RELAY] wss://premium.primal.net DISCONNECTED: Connection state transitioned to 2 during poll
|
||||
[2026-08-02 16:05:11] [RELAY] wss://premium.primal.net CONNECTED
|
||||
[2026-08-02 16:05:12] [RELAY] wss://premium.primal.net DISCONNECTED: Connection state transitioned to 2 during poll
|
||||
[2026-08-02 16:05:13] [RELAY] wss://premium.primal.net CONNECTED
|
||||
[2026-08-02 16:05:15] [RELAY] wss://premium.primal.net DISCONNECTED: Connection state transitioned to 2 during poll
|
||||
[2026-08-02 16:05:16] [RELAY] wss://premium.primal.net CONNECTED
|
||||
[2026-08-02 16:05:17] [RELAY] wss://premium.primal.net DISCONNECTED: Connection state transitioned to 2 during poll
|
||||
[2026-08-02 16:05:18] [RELAY] wss://premium.primal.net CONNECTED
|
||||
[2026-08-02 16:05:19] [RELAY] wss://premium.primal.net DISCONNECTED: Connection state transitioned to 2 during poll
|
||||
[2026-08-02 16:05:20] [RELAY] wss://premium.primal.net CONNECTED
|
||||
[2026-08-02 16:05:21] [RELAY] wss://premium.primal.net DISCONNECTED: Connection state transitioned to 2 during poll
|
||||
[2026-08-02 16:05:21] [RELAY] wss://premium.primal.net CONNECTED
|
||||
[2026-08-02 16:05:24] [RELAY] wss://premium.primal.net DISCONNECTED: Connection state transitioned to 2 during poll
|
||||
[2026-08-02 16:05:25] [RELAY] wss://premium.primal.net CONNECTED
|
||||
[2026-08-02 16:05:59] [RELAY] wss://relay.primal.net DISCONNECTED:
|
||||
[2026-08-02 16:05:59] [RELAY] wss://relay.primal.net CONNECTED
|
||||
[2026-08-02 16:06:09] [RELAY] wss://nos.lol DISCONNECTED:
|
||||
[2026-08-02 16:06:09] [RELAY] wss://nos.lol CONNECTED
|
||||
[2026-08-02 16:08:00] [RELAY] wss://relay.primal.net DISCONNECTED: Connection state transitioned to 2 during poll
|
||||
[2026-08-02 16:08:01] [RELAY] wss://relay.primal.net CONNECTED
|
||||
[2026-08-02 16:08:09] [RELAY] wss://nos.lol DISCONNECTED:
|
||||
[2026-08-02 16:08:09] [RELAY] wss://nos.lol CONNECTED
|
||||
[2026-08-02 16:08:42] [RELAY] wss://relay.primal.net DISCONNECTED: Connection state transitioned to 2 during poll
|
||||
[2026-08-02 16:08:42] [RELAY] wss://relay.primal.net CONNECTED
|
||||
[2026-08-02 16:10:20] [RELAY] wss://relay.primal.net DISCONNECTED: Connection state transitioned to 2 during poll
|
||||
[2026-08-02 16:10:21] [RELAY] wss://relay.primal.net CONNECTED
|
||||
[2026-08-02 16:11:09] [RELAY] wss://nos.lol DISCONNECTED:
|
||||
[2026-08-02 16:11:09] [RELAY] wss://nos.lol CONNECTED
|
||||
[2026-08-02 16:11:26] [RELAY] wss://premium.primal.net DISCONNECTED: Connection state transitioned to 2 during poll
|
||||
[2026-08-02 16:11:27] [RELAY] wss://premium.primal.net CONNECTED
|
||||
[2026-08-02 16:11:30] [RELAY] wss://premium.primal.net DISCONNECTED: Connection state transitioned to 2 during poll
|
||||
[2026-08-02 16:11:30] [RELAY] wss://premium.primal.net CONNECTED
|
||||
[2026-08-02 16:11:32] [RELAY] wss://premium.primal.net DISCONNECTED: Connection state transitioned to 2 during poll
|
||||
[2026-08-02 16:11:32] [RELAY] wss://premium.primal.net CONNECTED
|
||||
[2026-08-02 16:11:39] [RELAY] wss://nos.lol DISCONNECTED:
|
||||
[2026-08-02 16:11:39] [RELAY] wss://nos.lol CONNECTED
|
||||
[2026-08-02 16:11:46] [RELAY] wss://nos.lol DISCONNECTED: Connection state transitioned to 2 during poll
|
||||
[2026-08-02 16:11:47] [RELAY] wss://nos.lol CONNECTED
|
||||
[2026-08-02 16:12:58] [RELAY] wss://nos.lol DISCONNECTED:
|
||||
[2026-08-02 16:12:58] [RELAY] wss://nos.lol CONNECTED
|
||||
[2026-08-02 16:13:25] [RELAY] wss://relay.mostr.pub DISCONNECTED:
|
||||
[2026-08-02 16:13:25] [RELAY] wss://relay.mostr.pub CONNECTED
|
||||
[2026-08-02 16:13:32] [RELAY] wss://relay.primal.net DISCONNECTED:
|
||||
[2026-08-02 16:13:32] [RELAY] wss://relay.primal.net CONNECTED
|
||||
[2026-08-02 16:13:58] [RELAY] wss://nos.lol DISCONNECTED:
|
||||
[2026-08-02 16:13:58] [RELAY] wss://nos.lol CONNECTED
|
||||
[2026-08-02 16:14:28] [RELAY] wss://nos.lol DISCONNECTED:
|
||||
[2026-08-02 16:14:28] [RELAY] wss://nos.lol CONNECTED
|
||||
[2026-08-02 16:14:32] [RELAY] wss://relay.primal.net DISCONNECTED:
|
||||
[2026-08-02 16:14:32] [RELAY] wss://relay.primal.net CONNECTED
|
||||
[2026-08-02 16:15:16] [RELAY] wss://nos.lol DISCONNECTED: Connection state transitioned to 2 during poll
|
||||
[2026-08-02 16:15:17] [RELAY] wss://nos.lol CONNECTED
|
||||
[2026-08-02 16:15:23] [RELAY] wss://nos.lol DISCONNECTED: Connection state transitioned to 2 during poll
|
||||
[2026-08-02 16:15:24] [RELAY] wss://nos.lol CONNECTED
|
||||
[2026-08-02 16:15:32] [RELAY] wss://relay.primal.net DISCONNECTED:
|
||||
[2026-08-02 16:15:32] [RELAY] wss://relay.primal.net CONNECTED
|
||||
[2026-08-02 16:15:41] [RELAY] wss://nos.lol DISCONNECTED: Connection state transitioned to 2 during poll
|
||||
[2026-08-02 16:15:42] [RELAY] wss://nos.lol CONNECTED
|
||||
[2026-08-02 16:16:25] [RELAY] wss://premium.primal.net DISCONNECTED: Connection state transitioned to 2 during poll
|
||||
[2026-08-02 16:16:26] [RELAY] wss://premium.primal.net CONNECTED
|
||||
[2026-08-02 16:16:28] [RELAY] wss://premium.primal.net DISCONNECTED: Connection state transitioned to 2 during poll
|
||||
[2026-08-02 16:16:28] [RELAY] wss://premium.primal.net CONNECTED
|
||||
[2026-08-02 16:16:32] [RELAY] wss://relay.primal.net DISCONNECTED:
|
||||
[2026-08-02 16:16:32] [RELAY] wss://relay.primal.net CONNECTED
|
||||
[2026-08-02 16:16:36] [RELAY] wss://relay.momostr.pink DISCONNECTED: Connection state transitioned to 2 during poll
|
||||
[2026-08-02 16:16:36] [RELAY] wss://relay.momostr.pink CONNECTED
|
||||
[2026-08-02 16:17:02] [RELAY] wss://relay.primal.net DISCONNECTED:
|
||||
[2026-08-02 16:17:02] [RELAY] wss://relay.primal.net CONNECTED
|
||||
[2026-08-02 16:17:25] [RELAY] wss://relay.mostr.pub DISCONNECTED:
|
||||
[2026-08-02 16:17:25] [RELAY] wss://relay.mostr.pub CONNECTED
|
||||
[2026-08-02 16:18:02] [RELAY] wss://relay.primal.net DISCONNECTED:
|
||||
[2026-08-02 16:18:02] [RELAY] wss://relay.primal.net CONNECTED
|
||||
[2026-08-02 16:18:08] [RELAY] wss://nos.lol DISCONNECTED: Connection state transitioned to 2 during poll
|
||||
[2026-08-02 16:18:08] [RELAY] wss://nos.lol CONNECTED
|
||||
[2026-08-02 16:18:25] [RELAY] wss://relay.mostr.pub DISCONNECTED:
|
||||
[2026-08-02 16:18:25] [RELAY] wss://relay.mostr.pub CONNECTED
|
||||
[2026-08-02 16:18:49] [RELAY] wss://nos.lol DISCONNECTED: Connection state transitioned to 2 during poll
|
||||
[2026-08-02 16:18:49] [RELAY] wss://nos.lol CONNECTED
|
||||
[2026-08-02 16:18:55] [RELAY] wss://relay.primal.net DISCONNECTED: Connection state transitioned to 2 during poll
|
||||
[2026-08-02 16:18:56] [RELAY] wss://relay.primal.net CONNECTED
|
||||
[2026-08-02 16:19:37] [RELAY] wss://relay.primal.net DISCONNECTED: Connection state transitioned to 2 during poll
|
||||
[2026-08-02 16:19:37] [RELAY] wss://relay.primal.net CONNECTED
|
||||
[2026-08-02 16:19:40] [RELAY] wss://nos.lol DISCONNECTED: Connection state transitioned to 2 during poll
|
||||
[2026-08-02 16:19:40] [RELAY] wss://nos.lol CONNECTED
|
||||
[2026-08-02 16:20:37] [RELAY] wss://relay.primal.net DISCONNECTED:
|
||||
[2026-08-02 16:20:37] [RELAY] wss://relay.primal.net CONNECTED
|
||||
[2026-08-02 16:21:07] [RELAY] wss://relay.primal.net DISCONNECTED:
|
||||
[2026-08-02 16:21:07] [RELAY] wss://relay.primal.net CONNECTED
|
||||
[2026-08-02 16:21:10] [RELAY] wss://nos.lol DISCONNECTED:
|
||||
[2026-08-02 16:21:10] [RELAY] wss://nos.lol CONNECTED
|
||||
[2026-08-02 16:21:14] [RELAY] wss://nos.lol DISCONNECTED: Connection state transitioned to 2 during poll
|
||||
[2026-08-02 16:21:15] [RELAY] wss://nos.lol CONNECTED
|
||||
[2026-08-02 16:21:56] [RELAY] wss://nos.lol DISCONNECTED: Connection state transitioned to 2 during poll
|
||||
[2026-08-02 16:21:56] [RELAY] wss://nos.lol CONNECTED
|
||||
[2026-08-02 16:22:26] [RELAY] wss://nos.lol DISCONNECTED:
|
||||
[2026-08-02 16:22:26] [RELAY] wss://nos.lol CONNECTED
|
||||
[2026-08-02 16:22:55] [RELAY] wss://relay.mostr.pub DISCONNECTED:
|
||||
[2026-08-02 16:22:55] [RELAY] wss://relay.mostr.pub CONNECTED
|
||||
[2026-08-02 16:23:32] [RELAY] wss://premium.primal.net DISCONNECTED: Connection state transitioned to 2 during poll
|
||||
[2026-08-02 16:23:33] [RELAY] wss://premium.primal.net CONNECTED
|
||||
|
||||
@@ -0,0 +1,243 @@
|
||||
=== Cache-All Feasibility Test Report ===
|
||||
Duration: 0h 8m 23s
|
||||
|
||||
=== Global Summary ===
|
||||
Total events: 7884
|
||||
Total bytes: 12205231 (11.64 MB)
|
||||
Avg event size: 1548 bytes
|
||||
Max event: 56750 bytes (kind 3)
|
||||
Unique pubkeys: 2301
|
||||
Relays: 1
|
||||
|
||||
=== Relay Summary ===
|
||||
Relay Events EOSE CLOSED NOTICE Err Disc Status
|
||||
wss://relay.primal.net 7884 0 0 0 0 10 OK
|
||||
|
||||
=== Kind Distribution ===
|
||||
Kind Name Count % Total Bytes Avg Max
|
||||
1059 Gift wrap seal 871 11.0% 1657832 1903 55121
|
||||
21059 Gift wrap (NIP-59) 740 9.4% 2308644 3120 22354
|
||||
30078 App data 622 7.9% 2651879 4263 55090
|
||||
30383 Addressable 520 6.6% 278610 536 548
|
||||
20001 Ephemeral 386 4.9% 403111 1044 2026
|
||||
22734 Ephemeral 357 4.5% 152451 427 428
|
||||
1 Text note 303 3.8% 303990 1003 4648
|
||||
30382 Addressable 288 3.7% 137207 476 484
|
||||
0 Profile metadata 189 2.4% 140594 744 2012
|
||||
29333 Ephemeral 165 2.1% 81180 492 492
|
||||
10002 Relay list 158 2.0% 571188 3615 42385
|
||||
22236 Ephemeral 158 2.0% 120802 765 801
|
||||
5 Deletion 154 2.0% 73847 480 664
|
||||
4515 Unknown 154 2.0% 463562 3010 38797
|
||||
22743 Ephemeral 134 1.7% 57352 428 428
|
||||
7 Reaction 113 1.4% 62452 553 727
|
||||
24133 Ephemeral 102 1.3% 132440 1298 7334
|
||||
22684 Ephemeral 99 1.3% 42669 431 431
|
||||
22850 Ephemeral 94 1.2% 40420 430 430
|
||||
22838 Ephemeral 88 1.1% 37752 429 429
|
||||
22774 Ephemeral 84 1.1% 35952 428 428
|
||||
23003 Ephemeral 84 1.1% 35952 428 428
|
||||
22876 Ephemeral 83 1.1% 35358 426 426
|
||||
22611 Ephemeral 75 1.0% 32175 429 429
|
||||
25555 Ephemeral 69 0.9% 281319 4077 16987
|
||||
4 Encrypted DM 66 0.8% 72028 1091 17018
|
||||
22613 Ephemeral 63 0.8% 43489 690 692
|
||||
25050 Ephemeral 61 0.8% 24461 401 401
|
||||
11998 Unknown 61 0.8% 28269 463 465
|
||||
443 Unknown 49 0.6% 68056 1389 22480
|
||||
30301 Addressable 47 0.6% 53284 1134 1912
|
||||
3927 Unknown 47 0.6% 25051 533 533
|
||||
20387 Ephemeral 44 0.6% 22616 514 514
|
||||
22761 Ephemeral 44 0.6% 18832 428 428
|
||||
13194 NWC info 43 0.5% 22043 513 514
|
||||
20004 Ephemeral 42 0.5% 22266 530 549
|
||||
5300 Unknown 42 0.5% 25437 606 637
|
||||
22546 Ephemeral 39 0.5% 16614 426 426
|
||||
22714 Ephemeral 37 0.5% 15836 428 428
|
||||
30166 Addressable 35 0.4% 17904 512 589
|
||||
9735 Zap receipt 35 0.4% 70344 2010 3538
|
||||
23334 Ephemeral 35 0.4% 15084 431 432
|
||||
1985 Unknown 34 0.4% 16232 477 483
|
||||
22816 Ephemeral 33 0.4% 14157 429 429
|
||||
21050 Ephemeral 33 0.4% 30862 935 1874
|
||||
30315 User status 32 0.4% 21166 661 925
|
||||
445 Encrypted group msg 32 0.4% 120956 3780 9346
|
||||
22698 Ephemeral 32 0.4% 13664 427 427
|
||||
4004 Unknown 32 0.4% 37408 1169 1169
|
||||
38501 Addressable 31 0.4% 23034 743 744
|
||||
31990 App handler info 25 0.3% 9675 387 387
|
||||
10100 Unknown 24 0.3% 27687 1154 1589
|
||||
20333 Ephemeral 24 0.3% 19120 797 798
|
||||
3 Follow list 23 0.3% 328284 14273 56750
|
||||
24913 Ephemeral 22 0.3% 9700 441 493
|
||||
30311 Addressable 21 0.3% 22061 1051 1197
|
||||
6 Repost 21 0.3% 49793 2371 12925
|
||||
10050 DM relays 19 0.2% 8172 430 450
|
||||
22712 Ephemeral 18 0.2% 7704 428 428
|
||||
22808 Ephemeral 17 0.2% 7293 429 429
|
||||
10000 Mute list 16 0.2% 26659 1666 12630
|
||||
4244 Unknown 15 0.2% 8460 564 564
|
||||
23025 Ephemeral 15 0.2% 6465 431 431
|
||||
31234 Addressable 14 0.2% 24051 1718 2268
|
||||
38503 Addressable 13 0.2% 7174 552 552
|
||||
22630 Ephemeral 12 0.2% 11762 980 1654
|
||||
37195 Addressable 12 0.2% 8752 729 934
|
||||
6300 Unknown 12 0.2% 77247 6437 17248
|
||||
10777 Unknown 12 0.2% 5861 488 489
|
||||
30091 Addressable 11 0.1% 6763 615 629
|
||||
20000 Ephemeral 11 0.1% 3806 346 346
|
||||
30515 Addressable 11 0.1% 58344 5304 5304
|
||||
30088 Addressable 11 0.1% 20483 1862 1871
|
||||
22361 Ephemeral 10 0.1% 4439 444 445
|
||||
30280 Addressable 9 0.1% 4617 513 513
|
||||
22902 Ephemeral 9 0.1% 3861 429 429
|
||||
22506 Ephemeral 8 0.1% 3416 427 427
|
||||
7368 Unknown 8 0.1% 8304 1038 1040
|
||||
22645 Ephemeral 8 0.1% 3432 429 429
|
||||
38500 Addressable 8 0.1% 5696 712 713
|
||||
33334 Addressable 8 0.1% 6648 831 831
|
||||
30380 Addressable 8 0.1% 3632 454 454
|
||||
22688 Ephemeral 7 0.1% 2989 427 427
|
||||
22656 Ephemeral 7 0.1% 3017 431 431
|
||||
22316 Ephemeral 7 0.1% 3106 444 444
|
||||
30089 Chunked data 6 0.1% 123676 20613 44372
|
||||
22456 Ephemeral 6 0.1% 3140 523 790
|
||||
22739 Ephemeral 6 0.1% 2580 430 430
|
||||
22882 Ephemeral 6 0.1% 5292 882 1449
|
||||
22862 Ephemeral 6 0.1% 2574 429 429
|
||||
1111 Comment 6 0.1% 7227 1204 1698
|
||||
4245 Unknown 5 0.1% 2220 444 444
|
||||
30512 Addressable 5 0.1% 7504 1501 1506
|
||||
22641 Ephemeral 5 0.1% 2145 429 429
|
||||
22586 Ephemeral 5 0.1% 2135 427 427
|
||||
4243 Unknown 5 0.1% 2820 564 564
|
||||
22835 Ephemeral 5 0.1% 2145 429 429
|
||||
22620 Ephemeral 5 0.1% 2145 429 429
|
||||
22298 Ephemeral 5 0.1% 2218 444 444
|
||||
22852 Ephemeral 5 0.1% 2140 428 428
|
||||
22726 Ephemeral 5 0.1% 2150 430 430
|
||||
22362 Ephemeral 5 0.1% 2218 444 444
|
||||
22772 Ephemeral 5 0.1% 4051 810 1132
|
||||
22805 Ephemeral 4 0.1% 1712 428 428
|
||||
9734 Zap request 4 0.1% 3756 939 1033
|
||||
22200 Ephemeral 4 0.1% 1774 444 444
|
||||
31510 Addressable 4 0.1% 3922 980 982
|
||||
22570 Ephemeral 4 0.1% 1716 429 429
|
||||
25195 Ephemeral 4 0.1% 2712 678 678
|
||||
22752 Ephemeral 3 0.0% 4047 1349 3191
|
||||
31339 Addressable 3 0.0% 4410 1470 1470
|
||||
22949 Ephemeral 3 0.0% 1287 429 429
|
||||
22358 Ephemeral 3 0.0% 1331 444 444
|
||||
22474 Ephemeral 3 0.0% 1330 443 444
|
||||
22185 Ephemeral 3 0.0% 1330 443 444
|
||||
22936 Ephemeral 3 0.0% 1290 430 430
|
||||
25196 Ephemeral 3 0.0% 4938 1646 2214
|
||||
22439 Ephemeral 3 0.0% 1330 443 444
|
||||
22824 Ephemeral 3 0.0% 1281 427 427
|
||||
22270 Ephemeral 3 0.0% 1330 443 444
|
||||
22263 Ephemeral 3 0.0% 1330 443 444
|
||||
22755 Ephemeral 3 0.0% 1284 428 428
|
||||
10051 Unknown 3 0.0% 1317 439 439
|
||||
34775 Addressable 3 0.0% 7599 2533 2561
|
||||
30300 Addressable 3 0.0% 5502 1834 1834
|
||||
22234 Ephemeral 3 0.0% 1330 443 444
|
||||
7403 Unknown 2 0.0% 978 489 489
|
||||
22626 Ephemeral 2 0.0% 1916 958 1486
|
||||
30079 Addressable 2 0.0% 1750 875 875
|
||||
15750 Unknown 2 0.0% 1242 621 626
|
||||
23337 Ephemeral 2 0.0% 1027 514 514
|
||||
30815 Addressable 2 0.0% 75068 37534 37534
|
||||
30213 Addressable 2 0.0% 1264 632 632
|
||||
22716 Ephemeral 2 0.0% 854 427 427
|
||||
22492 Ephemeral 2 0.0% 887 444 444
|
||||
30000 Addressable 2 0.0% 1646 823 823
|
||||
22463 Ephemeral 2 0.0% 887 444 444
|
||||
22304 Ephemeral 2 0.0% 887 444 444
|
||||
10003 Bookmarks 2 0.0% 20016 10008 15003
|
||||
30443 Addressable 2 0.0% 2572 1286 1312
|
||||
22233 Ephemeral 2 0.0% 886 443 443
|
||||
22275 Ephemeral 2 0.0% 887 444 444
|
||||
30087 Addressable 2 0.0% 11238 5619 7325
|
||||
20078 Ephemeral 2 0.0% 1458 729 729
|
||||
22057 Ephemeral 2 0.0% 887 444 444
|
||||
22251 Ephemeral 2 0.0% 887 444 444
|
||||
22181 Ephemeral 2 0.0% 887 444 444
|
||||
22678 Ephemeral 2 0.0% 1388 694 694
|
||||
22747 Ephemeral 2 0.0% 858 429 429
|
||||
22410 Ephemeral 2 0.0% 887 444 444
|
||||
22334 Ephemeral 2 0.0% 887 444 444
|
||||
22249 Ephemeral 2 0.0% 887 444 444
|
||||
22258 Ephemeral 2 0.0% 887 444 444
|
||||
30090 Addressable 2 0.0% 2588 1294 1515
|
||||
10312 Unknown 1 0.0% 472 472 472
|
||||
22853 Ephemeral 1 0.0% 1673 1673 1673
|
||||
22303 Ephemeral 1 0.0% 443 443 443
|
||||
22306 Ephemeral 1 0.0% 443 443 443
|
||||
20200 Ephemeral 1 0.0% 491 491 491
|
||||
22132 Ephemeral 1 0.0% 443 443 443
|
||||
20201 Ephemeral 1 0.0% 491 491 491
|
||||
22245 Ephemeral 1 0.0% 443 443 443
|
||||
22352 Ephemeral 1 0.0% 443 443 443
|
||||
22240 Ephemeral 1 0.0% 443 443 443
|
||||
34236 Addressable 1 0.0% 931 931 931
|
||||
17 Unknown 1 0.0% 610 610 610
|
||||
22286 Ephemeral 1 0.0% 443 443 443
|
||||
13196 Unknown 1 0.0% 656 656 656
|
||||
20242 Ephemeral 1 0.0% 346 346 346
|
||||
7376 Unknown 1 0.0% 670 670 670
|
||||
38385 Addressable 1 0.0% 1350 1350 1350
|
||||
22355 Ephemeral 1 0.0% 443 443 443
|
||||
23333 Ephemeral 1 0.0% 571 571 571
|
||||
22737 Ephemeral 1 0.0% 556 556 556
|
||||
22291 Ephemeral 1 0.0% 443 443 443
|
||||
30421 Addressable 1 0.0% 995 995 995
|
||||
22860 Ephemeral 1 0.0% 553 553 553
|
||||
2333 Unknown 1 0.0% 659 659 659
|
||||
22219 Ephemeral 1 0.0% 443 443 443
|
||||
22382 Ephemeral 1 0.0% 443 443 443
|
||||
23032 Ephemeral 1 0.0% 430 430 430
|
||||
7375 Unknown 1 0.0% 1822 1822 1822
|
||||
22579 Ephemeral 1 0.0% 1670 1670 1670
|
||||
10007 Unknown 1 0.0% 715 715 715
|
||||
10086 Unknown 1 0.0% 715 715 715
|
||||
22729 Ephemeral 1 0.0% 3030 3030 3030
|
||||
22540 Ephemeral 1 0.0% 426 426 426
|
||||
22671 Ephemeral 1 0.0% 3194 3194 3194
|
||||
30618 Addressable 1 0.0% 460 460 460
|
||||
23118 Ephemeral 1 0.0% 430 430 430
|
||||
38421 Addressable 1 0.0% 1069 1069 1069
|
||||
10377 Unknown 1 0.0% 664 664 664
|
||||
11111 Unknown 1 0.0% 382 382 382
|
||||
34550 Community def 1 0.0% 867 867 867
|
||||
22307 Ephemeral 1 0.0% 443 443 443
|
||||
1078 Unknown 1 0.0% 13969 13969 13969
|
||||
|
||||
=== Raw Relay Response Log ===
|
||||
# Cache-All Feasibility Test - Raw Relay Log
|
||||
# Started: Sun Aug 2 16:24:15 2026
|
||||
# Config: cache_all_test_primal.jsonc
|
||||
# Duration: 3600 seconds
|
||||
[2026-08-02 16:24:32] [RELAY] wss://relay.primal.net STATUS: connected
|
||||
[2026-08-02 16:24:33] [RELAY] wss://relay.primal.net DISCONNECTED: Connection state transitioned to 2 during poll
|
||||
[2026-08-02 16:24:34] [RELAY] wss://relay.primal.net CONNECTED
|
||||
[2026-08-02 16:24:37] [RELAY] ? EOSE
|
||||
[2026-08-02 16:28:28] [RELAY] wss://relay.primal.net DISCONNECTED: Connection state transitioned to 2 during poll
|
||||
[2026-08-02 16:28:29] [RELAY] wss://relay.primal.net CONNECTED
|
||||
[2026-08-02 16:29:27] [RELAY] wss://relay.primal.net DISCONNECTED: Connection state transitioned to 2 during poll
|
||||
[2026-08-02 16:29:28] [RELAY] wss://relay.primal.net CONNECTED
|
||||
[2026-08-02 16:29:32] [RELAY] ? EOSE
|
||||
[2026-08-02 16:29:45] [RELAY] wss://relay.primal.net DISCONNECTED: Connection state transitioned to 2 during poll
|
||||
[2026-08-02 16:29:46] [RELAY] wss://relay.primal.net CONNECTED
|
||||
[2026-08-02 16:30:42] [RELAY] wss://relay.primal.net DISCONNECTED: Connection state transitioned to 2 during poll
|
||||
[2026-08-02 16:30:43] [RELAY] wss://relay.primal.net CONNECTED
|
||||
[2026-08-02 16:30:54] [RELAY] wss://relay.primal.net DISCONNECTED: Connection state transitioned to 2 during poll
|
||||
[2026-08-02 16:30:55] [RELAY] wss://relay.primal.net CONNECTED
|
||||
[2026-08-02 16:32:29] [RELAY] wss://relay.primal.net DISCONNECTED: Connection state transitioned to 2 during poll
|
||||
[2026-08-02 16:32:30] [RELAY] wss://relay.primal.net CONNECTED
|
||||
[2026-08-02 16:32:30] [RELAY] wss://relay.primal.net DISCONNECTED: Connection state transitioned to 2 during poll
|
||||
[2026-08-02 16:32:31] [RELAY] wss://relay.primal.net CONNECTED
|
||||
[2026-08-02 16:32:31] [RELAY] wss://relay.primal.net DISCONNECTED: Connection state transitioned to 2 during poll
|
||||
[2026-08-02 16:32:32] [RELAY] wss://relay.primal.net CONNECTED
|
||||
[2026-08-02 16:32:48] [RELAY] wss://relay.primal.net DISCONNECTED: Connection state transitioned to 2 during poll
|
||||
[2026-08-02 16:32:49] [RELAY] wss://relay.primal.net CONNECTED
|
||||
|
||||
@@ -0,0 +1,217 @@
|
||||
=== Cache-All Feasibility Test Report ===
|
||||
Duration: 0h 6m 16s
|
||||
|
||||
=== Global Summary ===
|
||||
Total events: 5992
|
||||
Total bytes: 8743262 (8.34 MB)
|
||||
Avg event size: 1459 bytes
|
||||
Max event: 61894 bytes (kind 3)
|
||||
Unique pubkeys: 1142
|
||||
Relays: 1
|
||||
|
||||
=== Relay Summary ===
|
||||
Relay Events EOSE CLOSED NOTICE Err Disc Status
|
||||
wss://relay.primal.net 5992 0 0 0 0 3 OK
|
||||
|
||||
=== Kind Distribution ===
|
||||
Kind Name Count % Total Bytes Avg Max
|
||||
30078 App data 495 8.3% 2024957 4091 54029
|
||||
21059 Gift wrap (NIP-59) 386 6.4% 1099128 2847 5314
|
||||
4515 Unknown 374 6.2% 781718 2090 14221
|
||||
22591 Ephemeral 371 6.2% 286839 773 1228
|
||||
20001 Ephemeral 271 4.5% 315643 1165 2029
|
||||
22734 Ephemeral 264 4.4% 112728 427 427
|
||||
30382 Addressable 255 4.3% 121375 476 483
|
||||
30383 Addressable 237 4.0% 126938 536 547
|
||||
1 Text note 212 3.5% 211399 997 2011
|
||||
5 Deletion 183 3.1% 91915 502 664
|
||||
22236 Ephemeral 146 2.4% 104252 714 810
|
||||
0 Profile metadata 145 2.4% 103418 713 2012
|
||||
7 Reaction 138 2.3% 79421 576 1036
|
||||
22743 Ephemeral 134 2.2% 57352 428 428
|
||||
1059 Gift wrap seal 132 2.2% 430222 3259 5285
|
||||
29333 Ephemeral 130 2.2% 63960 492 492
|
||||
22611 Ephemeral 117 2.0% 50147 429 429
|
||||
10002 Relay list 114 1.9% 510211 4476 42449
|
||||
23456 Ephemeral 72 1.2% 121616 1689 1874
|
||||
22850 Ephemeral 71 1.2% 30530 430 430
|
||||
22684 Ephemeral 70 1.2% 30170 431 431
|
||||
22838 Ephemeral 63 1.1% 27027 429 429
|
||||
23003 Ephemeral 63 1.1% 26964 428 428
|
||||
22774 Ephemeral 62 1.0% 26536 428 428
|
||||
22876 Ephemeral 61 1.0% 28880 473 3193
|
||||
22583 Ephemeral 61 1.0% 26047 427 427
|
||||
22613 Ephemeral 60 1.0% 43172 720 1133
|
||||
4 Encrypted DM 58 1.0% 61778 1065 17018
|
||||
25555 Ephemeral 56 0.9% 249772 4460 16895
|
||||
25050 Ephemeral 51 0.9% 20451 401 401
|
||||
11998 Unknown 48 0.8% 22272 464 465
|
||||
22728 Ephemeral 48 0.8% 20592 429 429
|
||||
31234 Addressable 33 0.6% 77859 2359 2612
|
||||
13194 NWC info 32 0.5% 16448 514 514
|
||||
20387 Ephemeral 32 0.5% 16448 514 514
|
||||
24133 Ephemeral 32 0.5% 23680 740 2214
|
||||
3 Follow list 31 0.5% 167289 5396 61894
|
||||
4004 Unknown 26 0.4% 30394 1169 1169
|
||||
22816 Ephemeral 26 0.4% 11154 429 429
|
||||
20004 Ephemeral 26 0.4% 13878 534 549
|
||||
30315 User status 26 0.4% 17657 679 872
|
||||
443 Unknown 25 0.4% 43504 1740 22480
|
||||
38501 Addressable 24 0.4% 17819 742 744
|
||||
1985 Unknown 24 0.4% 11435 476 483
|
||||
22882 Ephemeral 23 0.4% 20949 911 1455
|
||||
5300 Unknown 22 0.4% 13434 611 701
|
||||
31990 App handler info 22 0.4% 21777 990 6861
|
||||
22790 Ephemeral 21 0.4% 8988 428 428
|
||||
21050 Ephemeral 19 0.3% 17510 922 1874
|
||||
10100 Unknown 19 0.3% 22108 1164 1589
|
||||
20333 Ephemeral 18 0.3% 14340 797 798
|
||||
30088 Addressable 16 0.3% 29798 1862 1871
|
||||
6 Repost 16 0.3% 28131 1758 3369
|
||||
30091 Addressable 16 0.3% 9842 615 629
|
||||
6300 Unknown 15 0.3% 45643 3043 8157
|
||||
22658 Ephemeral 15 0.3% 11909 794 1161
|
||||
30311 Addressable 15 0.3% 16556 1104 1197
|
||||
445 Encrypted group msg 15 0.3% 45070 3005 4130
|
||||
10777 Unknown 14 0.2% 6840 489 489
|
||||
9735 Zap receipt 14 0.2% 27231 1945 2777
|
||||
4244 Unknown 12 0.2% 6768 564 564
|
||||
22456 Ephemeral 12 0.2% 6808 567 790
|
||||
38503 Addressable 11 0.2% 6070 552 552
|
||||
10050 DM relays 11 0.2% 4882 444 592
|
||||
30515 Addressable 10 0.2% 53040 5304 5304
|
||||
30512 Addressable 10 0.2% 15210 1521 1596
|
||||
30089 Chunked data 10 0.2% 164434 16443 44372
|
||||
10000 Mute list 10 0.2% 16448 1645 4287
|
||||
22809 Ephemeral 9 0.2% 3852 428 428
|
||||
22486 Ephemeral 9 0.2% 3834 426 426
|
||||
22376 Ephemeral 8 0.1% 3550 444 444
|
||||
7368 Unknown 8 0.1% 8294 1037 1040
|
||||
38500 Addressable 8 0.1% 5696 712 713
|
||||
30380 Addressable 7 0.1% 3178 454 454
|
||||
20000 Ephemeral 7 0.1% 2422 346 346
|
||||
22104 Ephemeral 7 0.1% 3105 444 444
|
||||
23025 Ephemeral 7 0.1% 3017 431 431
|
||||
22896 Ephemeral 7 0.1% 3003 429 429
|
||||
33334 Addressable 7 0.1% 5817 831 831
|
||||
22835 Ephemeral 6 0.1% 2574 429 429
|
||||
30443 Addressable 6 0.1% 7297 1216 1260
|
||||
22633 Ephemeral 6 0.1% 6097 1016 1668
|
||||
22392 Ephemeral 6 0.1% 2662 444 444
|
||||
1984 Report 6 0.1% 3180 530 530
|
||||
30064 Addressable 6 0.1% 4438 740 991
|
||||
22715 Ephemeral 6 0.1% 2562 427 427
|
||||
30280 Addressable 6 0.1% 3078 513 513
|
||||
22559 Ephemeral 6 0.1% 2574 429 429
|
||||
22813 Ephemeral 6 0.1% 2562 427 427
|
||||
22635 Ephemeral 6 0.1% 2556 426 426
|
||||
22746 Ephemeral 5 0.1% 2155 431 431
|
||||
22364 Ephemeral 5 0.1% 2135 427 427
|
||||
37195 Addressable 5 0.1% 3664 733 786
|
||||
22571 Ephemeral 5 0.1% 4055 811 1127
|
||||
23004 Ephemeral 5 0.1% 2145 429 429
|
||||
22834 Ephemeral 5 0.1% 4050 810 1126
|
||||
22636 Ephemeral 5 0.1% 3280 656 1164
|
||||
22786 Ephemeral 4 0.1% 1720 430 430
|
||||
25195 Ephemeral 4 0.1% 2712 678 678
|
||||
4243 Unknown 4 0.1% 2256 564 564
|
||||
22168 Ephemeral 4 0.1% 1774 444 444
|
||||
22760 Ephemeral 4 0.1% 2239 560 695
|
||||
22733 Ephemeral 4 0.1% 1696 424 424
|
||||
22878 Ephemeral 3 0.1% 4059 1353 3203
|
||||
22902 Ephemeral 3 0.1% 5023 1674 1675
|
||||
22428 Ephemeral 3 0.1% 1331 444 444
|
||||
25196 Ephemeral 3 0.1% 4938 1646 2214
|
||||
22325 Ephemeral 3 0.1% 1331 444 444
|
||||
4245 Unknown 3 0.1% 1332 444 444
|
||||
22258 Ephemeral 3 0.1% 1331 444 444
|
||||
22625 Ephemeral 3 0.1% 1284 428 428
|
||||
22631 Ephemeral 3 0.1% 1281 427 427
|
||||
22551 Ephemeral 3 0.1% 1816 605 695
|
||||
22763 Ephemeral 3 0.1% 2988 996 1331
|
||||
3927 Unknown 2 0.0% 1066 533 533
|
||||
22186 Ephemeral 2 0.0% 887 444 444
|
||||
30213 Addressable 2 0.0% 1264 632 632
|
||||
22367 Ephemeral 2 0.0% 887 444 444
|
||||
22783 Ephemeral 2 0.0% 1391 696 697
|
||||
22616 Ephemeral 2 0.0% 858 429 429
|
||||
22268 Ephemeral 2 0.0% 887 444 444
|
||||
22279 Ephemeral 2 0.0% 887 444 444
|
||||
22474 Ephemeral 2 0.0% 887 444 444
|
||||
22407 Ephemeral 2 0.0% 887 444 444
|
||||
22729 Ephemeral 2 0.0% 854 427 427
|
||||
22234 Ephemeral 2 0.0% 887 444 444
|
||||
10003 Bookmarks 2 0.0% 18782 9391 15076
|
||||
30815 Addressable 2 0.0% 75068 37534 37534
|
||||
1111 Comment 2 0.0% 1775 888 922
|
||||
30087 Addressable 2 0.0% 13286 6643 7325
|
||||
22256 Ephemeral 2 0.0% 886 443 443
|
||||
22299 Ephemeral 2 0.0% 887 444 444
|
||||
30090 Addressable 2 0.0% 2911 1456 1515
|
||||
22260 Ephemeral 2 0.0% 887 444 444
|
||||
7376 Unknown 2 0.0% 1340 670 670
|
||||
22012 Ephemeral 2 0.0% 887 444 444
|
||||
30618 Addressable 2 0.0% 920 460 460
|
||||
1078 Unknown 2 0.0% 28397 14198 14219
|
||||
22313 Ephemeral 2 0.0% 887 444 444
|
||||
31339 Addressable 2 0.0% 2940 1470 1470
|
||||
15750 Unknown 2 0.0% 1184 592 620
|
||||
20 Picture 2 0.0% 1664 832 834
|
||||
22326 Ephemeral 2 0.0% 887 444 444
|
||||
22841 Ephemeral 1 0.0% 428 428 428
|
||||
22738 Ephemeral 1 0.0% 1668 1668 1668
|
||||
22295 Ephemeral 1 0.0% 443 443 443
|
||||
22296 Ephemeral 1 0.0% 443 443 443
|
||||
31510 Addressable 1 0.0% 979 979 979
|
||||
22691 Ephemeral 1 0.0% 431 431 431
|
||||
22340 Ephemeral 1 0.0% 443 443 443
|
||||
30003 Addressable 1 0.0% 387 387 387
|
||||
22197 Ephemeral 1 0.0% 443 443 443
|
||||
22257 Ephemeral 1 0.0% 443 443 443
|
||||
30079 Addressable 1 0.0% 875 875 875
|
||||
22811 Ephemeral 1 0.0% 3211 3211 3211
|
||||
38385 Addressable 1 0.0% 1350 1350 1350
|
||||
22339 Ephemeral 1 0.0% 443 443 443
|
||||
13196 Unknown 1 0.0% 656 656 656
|
||||
20200 Ephemeral 1 0.0% 491 491 491
|
||||
20201 Ephemeral 1 0.0% 491 491 491
|
||||
22395 Ephemeral 1 0.0% 443 443 443
|
||||
30023 Long-form article 1 0.0% 27062 27062 27062
|
||||
7403 Unknown 1 0.0% 490 490 490
|
||||
22618 Ephemeral 1 0.0% 1668 1668 1668
|
||||
17 Unknown 1 0.0% 593 593 593
|
||||
30000 Addressable 1 0.0% 823 823 823
|
||||
22558 Ephemeral 1 0.0% 428 428 428
|
||||
22143 Ephemeral 1 0.0% 443 443 443
|
||||
22198 Ephemeral 1 0.0% 443 443 443
|
||||
7375 Unknown 1 0.0% 2846 2846 2846
|
||||
22506 Ephemeral 1 0.0% 426 426 426
|
||||
22243 Ephemeral 1 0.0% 443 443 443
|
||||
23086 Ephemeral 1 0.0% 431 431 431
|
||||
22688 Ephemeral 1 0.0% 3201 3201 3201
|
||||
22975 Ephemeral 1 0.0% 429 429 429
|
||||
22270 Ephemeral 1 0.0% 443 443 443
|
||||
22584 Ephemeral 1 0.0% 1675 1675 1675
|
||||
22764 Ephemeral 1 0.0% 551 551 551
|
||||
23071 Ephemeral 1 0.0% 1675 1675 1675
|
||||
22817 Ephemeral 1 0.0% 559 559 559
|
||||
22614 Ephemeral 1 0.0% 3200 3200 3200
|
||||
22330 Ephemeral 1 0.0% 443 443 443
|
||||
22229 Ephemeral 1 0.0% 443 443 443
|
||||
24421 Ephemeral 1 0.0% 525 525 525
|
||||
|
||||
=== Raw Relay Response Log ===
|
||||
# Cache-All Feasibility Test - Raw Relay Log
|
||||
# Started: Sun Aug 2 16:34:39 2026
|
||||
# Config: cache_all_test_primal.jsonc
|
||||
# Duration: 3600 seconds
|
||||
[2026-08-02 16:34:56] [RELAY] wss://relay.primal.net STATUS: connected
|
||||
[2026-08-02 16:34:57] [RELAY] ? EOSE
|
||||
[2026-08-02 16:38:58] [RELAY] wss://relay.primal.net DISCONNECTED: Connection state transitioned to 2 during poll
|
||||
[2026-08-02 16:38:58] [RELAY] wss://relay.primal.net CONNECTED
|
||||
[2026-08-02 16:39:56] [RELAY] ? EOSE
|
||||
[2026-08-02 16:40:16] [RELAY] wss://relay.primal.net DISCONNECTED: Connection state transitioned to 2 during poll
|
||||
[2026-08-02 16:40:17] [RELAY] wss://relay.primal.net CONNECTED
|
||||
[2026-08-02 16:40:17] [RELAY] wss://relay.primal.net DISCONNECTED: Connection state transitioned to 2 during poll
|
||||
[2026-08-02 16:40:18] [RELAY] wss://relay.primal.net CONNECTED
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,921 @@
|
||||
{
|
||||
"duration_seconds": 120,
|
||||
"total_events": 4267,
|
||||
"total_bytes": 6726611,
|
||||
"max_event_bytes": 42385,
|
||||
"max_event_kind": 10002,
|
||||
"unique_pubkeys": 1860,
|
||||
"relay_count": 3,
|
||||
"relays": [{
|
||||
"url": "wss://relay.primal.net",
|
||||
"events": 1670,
|
||||
"eose": 1,
|
||||
"closed": 0,
|
||||
"notice": 0,
|
||||
"errors": 0,
|
||||
"disconnects": 0,
|
||||
"connected": true,
|
||||
"raw_responses": []
|
||||
}, {
|
||||
"url": "wss://nos.lol",
|
||||
"events": 1792,
|
||||
"eose": 0,
|
||||
"closed": 0,
|
||||
"notice": 0,
|
||||
"errors": 0,
|
||||
"disconnects": 0,
|
||||
"connected": true,
|
||||
"raw_responses": []
|
||||
}, {
|
||||
"url": "wss://relay.damus.io",
|
||||
"events": 805,
|
||||
"eose": 0,
|
||||
"closed": 0,
|
||||
"notice": 0,
|
||||
"errors": 0,
|
||||
"disconnects": 0,
|
||||
"connected": true,
|
||||
"raw_responses": []
|
||||
}],
|
||||
"kinds": [{
|
||||
"kind": 21059,
|
||||
"count": 1199,
|
||||
"total_bytes": 3547818,
|
||||
"max_bytes": 5314
|
||||
}, {
|
||||
"kind": 5,
|
||||
"count": 466,
|
||||
"total_bytes": 204587,
|
||||
"max_bytes": 1064
|
||||
}, {
|
||||
"kind": 30078,
|
||||
"count": 222,
|
||||
"total_bytes": 948782,
|
||||
"max_bytes": 40337
|
||||
}, {
|
||||
"kind": 22668,
|
||||
"count": 221,
|
||||
"total_bytes": 94809,
|
||||
"max_bytes": 429
|
||||
}, {
|
||||
"kind": 20001,
|
||||
"count": 152,
|
||||
"total_bytes": 106536,
|
||||
"max_bytes": 1755
|
||||
}, {
|
||||
"kind": 4515,
|
||||
"count": 152,
|
||||
"total_bytes": 260732,
|
||||
"max_bytes": 8759
|
||||
}, {
|
||||
"kind": 22734,
|
||||
"count": 108,
|
||||
"total_bytes": 46116,
|
||||
"max_bytes": 427
|
||||
}, {
|
||||
"kind": 1,
|
||||
"count": 105,
|
||||
"total_bytes": 83026,
|
||||
"max_bytes": 3482
|
||||
}, {
|
||||
"kind": 21050,
|
||||
"count": 91,
|
||||
"total_bytes": 89206,
|
||||
"max_bytes": 2558
|
||||
}, {
|
||||
"kind": 24747,
|
||||
"count": 85,
|
||||
"total_bytes": 42775,
|
||||
"max_bytes": 671
|
||||
}, {
|
||||
"kind": 22850,
|
||||
"count": 77,
|
||||
"total_bytes": 33110,
|
||||
"max_bytes": 430
|
||||
}, {
|
||||
"kind": 22591,
|
||||
"count": 66,
|
||||
"total_bytes": 53607,
|
||||
"max_bytes": 1222
|
||||
}, {
|
||||
"kind": 38501,
|
||||
"count": 61,
|
||||
"total_bytes": 45175,
|
||||
"max_bytes": 744
|
||||
}, {
|
||||
"kind": 10002,
|
||||
"count": 51,
|
||||
"total_bytes": 63749,
|
||||
"max_bytes": 42385
|
||||
}, {
|
||||
"kind": 0,
|
||||
"count": 47,
|
||||
"total_bytes": 33672,
|
||||
"max_bytes": 1611
|
||||
}, {
|
||||
"kind": 37195,
|
||||
"count": 44,
|
||||
"total_bytes": 32855,
|
||||
"max_bytes": 771
|
||||
}, {
|
||||
"kind": 24242,
|
||||
"count": 37,
|
||||
"total_bytes": 21423,
|
||||
"max_bytes": 579
|
||||
}, {
|
||||
"kind": 25050,
|
||||
"count": 36,
|
||||
"total_bytes": 15972,
|
||||
"max_bytes": 465
|
||||
}, {
|
||||
"kind": 7,
|
||||
"count": 36,
|
||||
"total_bytes": 18965,
|
||||
"max_bytes": 646
|
||||
}, {
|
||||
"kind": 22613,
|
||||
"count": 35,
|
||||
"total_bytes": 26154,
|
||||
"max_bytes": 1134
|
||||
}, {
|
||||
"kind": 22484,
|
||||
"count": 32,
|
||||
"total_bytes": 29125,
|
||||
"max_bytes": 1163
|
||||
}, {
|
||||
"kind": 22749,
|
||||
"count": 29,
|
||||
"total_bytes": 12441,
|
||||
"max_bytes": 429
|
||||
}, {
|
||||
"kind": 24133,
|
||||
"count": 25,
|
||||
"total_bytes": 37446,
|
||||
"max_bytes": 7334
|
||||
}, {
|
||||
"kind": 22601,
|
||||
"count": 25,
|
||||
"total_bytes": 10700,
|
||||
"max_bytes": 428
|
||||
}, {
|
||||
"kind": 22507,
|
||||
"count": 24,
|
||||
"total_bytes": 22582,
|
||||
"max_bytes": 1165
|
||||
}, {
|
||||
"kind": 1059,
|
||||
"count": 23,
|
||||
"total_bytes": 41391,
|
||||
"max_bytes": 2897
|
||||
}, {
|
||||
"kind": 22699,
|
||||
"count": 23,
|
||||
"total_bytes": 9844,
|
||||
"max_bytes": 428
|
||||
}, {
|
||||
"kind": 22676,
|
||||
"count": 23,
|
||||
"total_bytes": 9821,
|
||||
"max_bytes": 427
|
||||
}, {
|
||||
"kind": 22774,
|
||||
"count": 20,
|
||||
"total_bytes": 8560,
|
||||
"max_bytes": 428
|
||||
}, {
|
||||
"kind": 22795,
|
||||
"count": 20,
|
||||
"total_bytes": 8580,
|
||||
"max_bytes": 429
|
||||
}, {
|
||||
"kind": 22655,
|
||||
"count": 20,
|
||||
"total_bytes": 8560,
|
||||
"max_bytes": 428
|
||||
}, {
|
||||
"kind": 23003,
|
||||
"count": 20,
|
||||
"total_bytes": 8560,
|
||||
"max_bytes": 428
|
||||
}, {
|
||||
"kind": 30382,
|
||||
"count": 20,
|
||||
"total_bytes": 9960,
|
||||
"max_bytes": 498
|
||||
}, {
|
||||
"kind": 29333,
|
||||
"count": 20,
|
||||
"total_bytes": 9840,
|
||||
"max_bytes": 492
|
||||
}, {
|
||||
"kind": 25555,
|
||||
"count": 18,
|
||||
"total_bytes": 62434,
|
||||
"max_bytes": 17003
|
||||
}, {
|
||||
"kind": 11998,
|
||||
"count": 18,
|
||||
"total_bytes": 8322,
|
||||
"max_bytes": 465
|
||||
}, {
|
||||
"kind": 31990,
|
||||
"count": 18,
|
||||
"total_bytes": 16845,
|
||||
"max_bytes": 1465
|
||||
}, {
|
||||
"kind": 4,
|
||||
"count": 18,
|
||||
"total_bytes": 28064,
|
||||
"max_bytes": 17018
|
||||
}, {
|
||||
"kind": 13194,
|
||||
"count": 18,
|
||||
"total_bytes": 9252,
|
||||
"max_bytes": 514
|
||||
}, {
|
||||
"kind": 22689,
|
||||
"count": 17,
|
||||
"total_bytes": 7259,
|
||||
"max_bytes": 427
|
||||
}, {
|
||||
"kind": 5300,
|
||||
"count": 17,
|
||||
"total_bytes": 10495,
|
||||
"max_bytes": 701
|
||||
}, {
|
||||
"kind": 445,
|
||||
"count": 17,
|
||||
"total_bytes": 81892,
|
||||
"max_bytes": 19620
|
||||
}, {
|
||||
"kind": 20000,
|
||||
"count": 15,
|
||||
"total_bytes": 7045,
|
||||
"max_bytes": 546
|
||||
}, {
|
||||
"kind": 20387,
|
||||
"count": 14,
|
||||
"total_bytes": 7196,
|
||||
"max_bytes": 514
|
||||
}, {
|
||||
"kind": 20004,
|
||||
"count": 14,
|
||||
"total_bytes": 7488,
|
||||
"max_bytes": 549
|
||||
}, {
|
||||
"kind": 7368,
|
||||
"count": 13,
|
||||
"total_bytes": 13476,
|
||||
"max_bytes": 1040
|
||||
}, {
|
||||
"kind": 22456,
|
||||
"count": 13,
|
||||
"total_bytes": 6110,
|
||||
"max_bytes": 470
|
||||
}, {
|
||||
"kind": 9735,
|
||||
"count": 13,
|
||||
"total_bytes": 26072,
|
||||
"max_bytes": 2331
|
||||
}, {
|
||||
"kind": 22551,
|
||||
"count": 13,
|
||||
"total_bytes": 11042,
|
||||
"max_bytes": 1161
|
||||
}, {
|
||||
"kind": 22760,
|
||||
"count": 13,
|
||||
"total_bytes": 11014,
|
||||
"max_bytes": 1161
|
||||
}, {
|
||||
"kind": 22658,
|
||||
"count": 13,
|
||||
"total_bytes": 11050,
|
||||
"max_bytes": 1164
|
||||
}, {
|
||||
"kind": 10100,
|
||||
"count": 11,
|
||||
"total_bytes": 20684,
|
||||
"max_bytes": 3825
|
||||
}, {
|
||||
"kind": 30315,
|
||||
"count": 11,
|
||||
"total_bytes": 8899,
|
||||
"max_bytes": 1038
|
||||
}, {
|
||||
"kind": 20787,
|
||||
"count": 11,
|
||||
"total_bytes": 15458,
|
||||
"max_bytes": 2474
|
||||
}, {
|
||||
"kind": 22236,
|
||||
"count": 10,
|
||||
"total_bytes": 7818,
|
||||
"max_bytes": 814
|
||||
}, {
|
||||
"kind": 22832,
|
||||
"count": 10,
|
||||
"total_bytes": 4286,
|
||||
"max_bytes": 429
|
||||
}, {
|
||||
"kind": 38502,
|
||||
"count": 8,
|
||||
"total_bytes": 3080,
|
||||
"max_bytes": 385
|
||||
}, {
|
||||
"kind": 4004,
|
||||
"count": 8,
|
||||
"total_bytes": 9352,
|
||||
"max_bytes": 1169
|
||||
}, {
|
||||
"kind": 22785,
|
||||
"count": 8,
|
||||
"total_bytes": 3432,
|
||||
"max_bytes": 429
|
||||
}, {
|
||||
"kind": 3,
|
||||
"count": 8,
|
||||
"total_bytes": 35850,
|
||||
"max_bytes": 9845
|
||||
}, {
|
||||
"kind": 1985,
|
||||
"count": 8,
|
||||
"total_bytes": 3792,
|
||||
"max_bytes": 474
|
||||
}, {
|
||||
"kind": 22584,
|
||||
"count": 8,
|
||||
"total_bytes": 3416,
|
||||
"max_bytes": 427
|
||||
}, {
|
||||
"kind": 22816,
|
||||
"count": 8,
|
||||
"total_bytes": 3432,
|
||||
"max_bytes": 429
|
||||
}, {
|
||||
"kind": 22752,
|
||||
"count": 8,
|
||||
"total_bytes": 6212,
|
||||
"max_bytes": 3199
|
||||
}, {
|
||||
"kind": 6,
|
||||
"count": 7,
|
||||
"total_bytes": 10112,
|
||||
"max_bytes": 1872
|
||||
}, {
|
||||
"kind": 443,
|
||||
"count": 7,
|
||||
"total_bytes": 7780,
|
||||
"max_bytes": 1116
|
||||
}, {
|
||||
"kind": 22651,
|
||||
"count": 6,
|
||||
"total_bytes": 2568,
|
||||
"max_bytes": 428
|
||||
}, {
|
||||
"kind": 1077,
|
||||
"count": 6,
|
||||
"total_bytes": 3642,
|
||||
"max_bytes": 607
|
||||
}, {
|
||||
"kind": 26428,
|
||||
"count": 6,
|
||||
"total_bytes": 5254,
|
||||
"max_bytes": 876
|
||||
}, {
|
||||
"kind": 22616,
|
||||
"count": 6,
|
||||
"total_bytes": 2574,
|
||||
"max_bytes": 429
|
||||
}, {
|
||||
"kind": 22626,
|
||||
"count": 6,
|
||||
"total_bytes": 2568,
|
||||
"max_bytes": 428
|
||||
}, {
|
||||
"kind": 22914,
|
||||
"count": 6,
|
||||
"total_bytes": 2580,
|
||||
"max_bytes": 430
|
||||
}, {
|
||||
"kind": 22614,
|
||||
"count": 6,
|
||||
"total_bytes": 2568,
|
||||
"max_bytes": 428
|
||||
}, {
|
||||
"kind": 22419,
|
||||
"count": 5,
|
||||
"total_bytes": 2218,
|
||||
"max_bytes": 444
|
||||
}, {
|
||||
"kind": 22847,
|
||||
"count": 5,
|
||||
"total_bytes": 2155,
|
||||
"max_bytes": 431
|
||||
}, {
|
||||
"kind": 30088,
|
||||
"count": 5,
|
||||
"total_bytes": 9317,
|
||||
"max_bytes": 1871
|
||||
}, {
|
||||
"kind": 10050,
|
||||
"count": 5,
|
||||
"total_bytes": 2250,
|
||||
"max_bytes": 450
|
||||
}, {
|
||||
"kind": 30091,
|
||||
"count": 5,
|
||||
"total_bytes": 3085,
|
||||
"max_bytes": 629
|
||||
}, {
|
||||
"kind": 30311,
|
||||
"count": 5,
|
||||
"total_bytes": 5153,
|
||||
"max_bytes": 1197
|
||||
}, {
|
||||
"kind": 23080,
|
||||
"count": 5,
|
||||
"total_bytes": 2155,
|
||||
"max_bytes": 431
|
||||
}, {
|
||||
"kind": 38225,
|
||||
"count": 4,
|
||||
"total_bytes": 4077,
|
||||
"max_bytes": 1036
|
||||
}, {
|
||||
"kind": 4244,
|
||||
"count": 4,
|
||||
"total_bytes": 2256,
|
||||
"max_bytes": 564
|
||||
}, {
|
||||
"kind": 26429,
|
||||
"count": 4,
|
||||
"total_bytes": 1964,
|
||||
"max_bytes": 491
|
||||
}, {
|
||||
"kind": 3927,
|
||||
"count": 4,
|
||||
"total_bytes": 2132,
|
||||
"max_bytes": 533
|
||||
}, {
|
||||
"kind": 22806,
|
||||
"count": 4,
|
||||
"total_bytes": 1712,
|
||||
"max_bytes": 428
|
||||
}, {
|
||||
"kind": 30000,
|
||||
"count": 4,
|
||||
"total_bytes": 9358,
|
||||
"max_bytes": 2845
|
||||
}, {
|
||||
"kind": 21617,
|
||||
"count": 4,
|
||||
"total_bytes": 1980,
|
||||
"max_bytes": 495
|
||||
}, {
|
||||
"kind": 20333,
|
||||
"count": 4,
|
||||
"total_bytes": 3188,
|
||||
"max_bytes": 798
|
||||
}, {
|
||||
"kind": 22548,
|
||||
"count": 4,
|
||||
"total_bytes": 1720,
|
||||
"max_bytes": 430
|
||||
}, {
|
||||
"kind": 38503,
|
||||
"count": 4,
|
||||
"total_bytes": 2212,
|
||||
"max_bytes": 553
|
||||
}, {
|
||||
"kind": 30515,
|
||||
"count": 4,
|
||||
"total_bytes": 18496,
|
||||
"max_bytes": 4624
|
||||
}, {
|
||||
"kind": 22740,
|
||||
"count": 4,
|
||||
"total_bytes": 1708,
|
||||
"max_bytes": 427
|
||||
}, {
|
||||
"kind": 22226,
|
||||
"count": 3,
|
||||
"total_bytes": 1331,
|
||||
"max_bytes": 444
|
||||
}, {
|
||||
"kind": 10011,
|
||||
"count": 3,
|
||||
"total_bytes": 1375,
|
||||
"max_bytes": 513
|
||||
}, {
|
||||
"kind": 30089,
|
||||
"count": 3,
|
||||
"total_bytes": 6944,
|
||||
"max_bytes": 3412
|
||||
}, {
|
||||
"kind": 30023,
|
||||
"count": 3,
|
||||
"total_bytes": 19822,
|
||||
"max_bytes": 7860
|
||||
}, {
|
||||
"kind": 21060,
|
||||
"count": 3,
|
||||
"total_bytes": 1710,
|
||||
"max_bytes": 570
|
||||
}, {
|
||||
"kind": 22526,
|
||||
"count": 3,
|
||||
"total_bytes": 1290,
|
||||
"max_bytes": 430
|
||||
}, {
|
||||
"kind": 22511,
|
||||
"count": 3,
|
||||
"total_bytes": 2383,
|
||||
"max_bytes": 1163
|
||||
}, {
|
||||
"kind": 22167,
|
||||
"count": 3,
|
||||
"total_bytes": 1331,
|
||||
"max_bytes": 444
|
||||
}, {
|
||||
"kind": 30213,
|
||||
"count": 3,
|
||||
"total_bytes": 1866,
|
||||
"max_bytes": 632
|
||||
}, {
|
||||
"kind": 22748,
|
||||
"count": 3,
|
||||
"total_bytes": 1284,
|
||||
"max_bytes": 428
|
||||
}, {
|
||||
"kind": 31234,
|
||||
"count": 3,
|
||||
"total_bytes": 4248,
|
||||
"max_bytes": 1416
|
||||
}, {
|
||||
"kind": 22838,
|
||||
"count": 2,
|
||||
"total_bytes": 860,
|
||||
"max_bytes": 430
|
||||
}, {
|
||||
"kind": 38500,
|
||||
"count": 2,
|
||||
"total_bytes": 1424,
|
||||
"max_bytes": 713
|
||||
}, {
|
||||
"kind": 38384,
|
||||
"count": 2,
|
||||
"total_bytes": 1486,
|
||||
"max_bytes": 743
|
||||
}, {
|
||||
"kind": 30443,
|
||||
"count": 2,
|
||||
"total_bytes": 2379,
|
||||
"max_bytes": 1220
|
||||
}, {
|
||||
"kind": 20384,
|
||||
"count": 2,
|
||||
"total_bytes": 1278,
|
||||
"max_bytes": 639
|
||||
}, {
|
||||
"kind": 34237,
|
||||
"count": 2,
|
||||
"total_bytes": 836,
|
||||
"max_bytes": 418
|
||||
}, {
|
||||
"kind": 22280,
|
||||
"count": 2,
|
||||
"total_bytes": 887,
|
||||
"max_bytes": 444
|
||||
}, {
|
||||
"kind": 23194,
|
||||
"count": 2,
|
||||
"total_bytes": 1020,
|
||||
"max_bytes": 510
|
||||
}, {
|
||||
"kind": 22320,
|
||||
"count": 2,
|
||||
"total_bytes": 887,
|
||||
"max_bytes": 444
|
||||
}, {
|
||||
"kind": 30080,
|
||||
"count": 2,
|
||||
"total_bytes": 1971,
|
||||
"max_bytes": 986
|
||||
}, {
|
||||
"kind": 22205,
|
||||
"count": 2,
|
||||
"total_bytes": 887,
|
||||
"max_bytes": 444
|
||||
}, {
|
||||
"kind": 22770,
|
||||
"count": 2,
|
||||
"total_bytes": 862,
|
||||
"max_bytes": 431
|
||||
}, {
|
||||
"kind": 22305,
|
||||
"count": 2,
|
||||
"total_bytes": 887,
|
||||
"max_bytes": 444
|
||||
}, {
|
||||
"kind": 22356,
|
||||
"count": 2,
|
||||
"total_bytes": 886,
|
||||
"max_bytes": 443
|
||||
}, {
|
||||
"kind": 22611,
|
||||
"count": 2,
|
||||
"total_bytes": 852,
|
||||
"max_bytes": 426
|
||||
}, {
|
||||
"kind": 22217,
|
||||
"count": 2,
|
||||
"total_bytes": 887,
|
||||
"max_bytes": 444
|
||||
}, {
|
||||
"kind": 22884,
|
||||
"count": 2,
|
||||
"total_bytes": 860,
|
||||
"max_bytes": 430
|
||||
}, {
|
||||
"kind": 33334,
|
||||
"count": 2,
|
||||
"total_bytes": 1662,
|
||||
"max_bytes": 831
|
||||
}, {
|
||||
"kind": 6300,
|
||||
"count": 2,
|
||||
"total_bytes": 8371,
|
||||
"max_bytes": 5058
|
||||
}, {
|
||||
"kind": 22169,
|
||||
"count": 2,
|
||||
"total_bytes": 887,
|
||||
"max_bytes": 444
|
||||
}, {
|
||||
"kind": 22190,
|
||||
"count": 2,
|
||||
"total_bytes": 887,
|
||||
"max_bytes": 444
|
||||
}, {
|
||||
"kind": 30079,
|
||||
"count": 2,
|
||||
"total_bytes": 1750,
|
||||
"max_bytes": 875
|
||||
}, {
|
||||
"kind": 39101,
|
||||
"count": 2,
|
||||
"total_bytes": 1066,
|
||||
"max_bytes": 533
|
||||
}, {
|
||||
"kind": 22345,
|
||||
"count": 2,
|
||||
"total_bytes": 887,
|
||||
"max_bytes": 444
|
||||
}, {
|
||||
"kind": 22310,
|
||||
"count": 2,
|
||||
"total_bytes": 887,
|
||||
"max_bytes": 444
|
||||
}, {
|
||||
"kind": 1111,
|
||||
"count": 2,
|
||||
"total_bytes": 2557,
|
||||
"max_bytes": 1564
|
||||
}, {
|
||||
"kind": 22235,
|
||||
"count": 2,
|
||||
"total_bytes": 887,
|
||||
"max_bytes": 444
|
||||
}, {
|
||||
"kind": 38385,
|
||||
"count": 2,
|
||||
"total_bytes": 2552,
|
||||
"max_bytes": 1319
|
||||
}, {
|
||||
"kind": 4747,
|
||||
"count": 1,
|
||||
"total_bytes": 721,
|
||||
"max_bytes": 721
|
||||
}, {
|
||||
"kind": 22844,
|
||||
"count": 1,
|
||||
"total_bytes": 428,
|
||||
"max_bytes": 428
|
||||
}, {
|
||||
"kind": 22807,
|
||||
"count": 1,
|
||||
"total_bytes": 3205,
|
||||
"max_bytes": 3205
|
||||
}, {
|
||||
"kind": 30066,
|
||||
"count": 1,
|
||||
"total_bytes": 675,
|
||||
"max_bytes": 675
|
||||
}, {
|
||||
"kind": 4245,
|
||||
"count": 1,
|
||||
"total_bytes": 444,
|
||||
"max_bytes": 444
|
||||
}, {
|
||||
"kind": 7376,
|
||||
"count": 1,
|
||||
"total_bytes": 521,
|
||||
"max_bytes": 521
|
||||
}, {
|
||||
"kind": 22450,
|
||||
"count": 1,
|
||||
"total_bytes": 443,
|
||||
"max_bytes": 443
|
||||
}, {
|
||||
"kind": 22261,
|
||||
"count": 1,
|
||||
"total_bytes": 443,
|
||||
"max_bytes": 443
|
||||
}, {
|
||||
"kind": 4243,
|
||||
"count": 1,
|
||||
"total_bytes": 564,
|
||||
"max_bytes": 564
|
||||
}, {
|
||||
"kind": 22242,
|
||||
"count": 1,
|
||||
"total_bytes": 443,
|
||||
"max_bytes": 443
|
||||
}, {
|
||||
"kind": 10063,
|
||||
"count": 1,
|
||||
"total_bytes": 415,
|
||||
"max_bytes": 415
|
||||
}, {
|
||||
"kind": 22306,
|
||||
"count": 1,
|
||||
"total_bytes": 443,
|
||||
"max_bytes": 443
|
||||
}, {
|
||||
"kind": 22174,
|
||||
"count": 1,
|
||||
"total_bytes": 443,
|
||||
"max_bytes": 443
|
||||
}, {
|
||||
"kind": 22831,
|
||||
"count": 1,
|
||||
"total_bytes": 3182,
|
||||
"max_bytes": 3182
|
||||
}, {
|
||||
"kind": 22227,
|
||||
"count": 1,
|
||||
"total_bytes": 443,
|
||||
"max_bytes": 443
|
||||
}, {
|
||||
"kind": 7375,
|
||||
"count": 1,
|
||||
"total_bytes": 8629,
|
||||
"max_bytes": 8629
|
||||
}, {
|
||||
"kind": 22685,
|
||||
"count": 1,
|
||||
"total_bytes": 553,
|
||||
"max_bytes": 553
|
||||
}, {
|
||||
"kind": 22299,
|
||||
"count": 1,
|
||||
"total_bytes": 443,
|
||||
"max_bytes": 443
|
||||
}, {
|
||||
"kind": 22193,
|
||||
"count": 1,
|
||||
"total_bytes": 443,
|
||||
"max_bytes": 443
|
||||
}, {
|
||||
"kind": 22975,
|
||||
"count": 1,
|
||||
"total_bytes": 3195,
|
||||
"max_bytes": 3195
|
||||
}, {
|
||||
"kind": 30380,
|
||||
"count": 1,
|
||||
"total_bytes": 454,
|
||||
"max_bytes": 454
|
||||
}, {
|
||||
"kind": 20,
|
||||
"count": 1,
|
||||
"total_bytes": 860,
|
||||
"max_bytes": 860
|
||||
}, {
|
||||
"kind": 10030,
|
||||
"count": 1,
|
||||
"total_bytes": 405,
|
||||
"max_bytes": 405
|
||||
}, {
|
||||
"kind": 30087,
|
||||
"count": 1,
|
||||
"total_bytes": 7325,
|
||||
"max_bytes": 7325
|
||||
}, {
|
||||
"kind": 30090,
|
||||
"count": 1,
|
||||
"total_bytes": 1515,
|
||||
"max_bytes": 1515
|
||||
}, {
|
||||
"kind": 22220,
|
||||
"count": 1,
|
||||
"total_bytes": 443,
|
||||
"max_bytes": 443
|
||||
}, {
|
||||
"kind": 39019,
|
||||
"count": 1,
|
||||
"total_bytes": 961,
|
||||
"max_bytes": 961
|
||||
}, {
|
||||
"kind": 39015,
|
||||
"count": 1,
|
||||
"total_bytes": 696,
|
||||
"max_bytes": 696
|
||||
}, {
|
||||
"kind": 30617,
|
||||
"count": 1,
|
||||
"total_bytes": 1089,
|
||||
"max_bytes": 1089
|
||||
}, {
|
||||
"kind": 30618,
|
||||
"count": 1,
|
||||
"total_bytes": 733,
|
||||
"max_bytes": 733
|
||||
}, {
|
||||
"kind": 31991,
|
||||
"count": 1,
|
||||
"total_bytes": 461,
|
||||
"max_bytes": 461
|
||||
}, {
|
||||
"kind": 1080,
|
||||
"count": 1,
|
||||
"total_bytes": 949,
|
||||
"max_bytes": 949
|
||||
}, {
|
||||
"kind": 3434,
|
||||
"count": 1,
|
||||
"total_bytes": 705,
|
||||
"max_bytes": 705
|
||||
}, {
|
||||
"kind": 33333,
|
||||
"count": 1,
|
||||
"total_bytes": 2346,
|
||||
"max_bytes": 2346
|
||||
}, {
|
||||
"kind": 22735,
|
||||
"count": 1,
|
||||
"total_bytes": 430,
|
||||
"max_bytes": 430
|
||||
}, {
|
||||
"kind": 22415,
|
||||
"count": 1,
|
||||
"total_bytes": 443,
|
||||
"max_bytes": 443
|
||||
}, {
|
||||
"kind": 21966,
|
||||
"count": 1,
|
||||
"total_bytes": 443,
|
||||
"max_bytes": 443
|
||||
}, {
|
||||
"kind": 11316,
|
||||
"count": 1,
|
||||
"total_bytes": 725,
|
||||
"max_bytes": 725
|
||||
}, {
|
||||
"kind": 11317,
|
||||
"count": 1,
|
||||
"total_bytes": 12051,
|
||||
"max_bytes": 12051
|
||||
}, {
|
||||
"kind": 25195,
|
||||
"count": 1,
|
||||
"total_bytes": 678,
|
||||
"max_bytes": 678
|
||||
}, {
|
||||
"kind": 25196,
|
||||
"count": 1,
|
||||
"total_bytes": 1362,
|
||||
"max_bytes": 1362
|
||||
}, {
|
||||
"kind": 22402,
|
||||
"count": 1,
|
||||
"total_bytes": 443,
|
||||
"max_bytes": 443
|
||||
}, {
|
||||
"kind": 31510,
|
||||
"count": 1,
|
||||
"total_bytes": 979,
|
||||
"max_bytes": 979
|
||||
}, {
|
||||
"kind": 1078,
|
||||
"count": 1,
|
||||
"total_bytes": 14200,
|
||||
"max_bytes": 14200
|
||||
}, {
|
||||
"kind": 38383,
|
||||
"count": 1,
|
||||
"total_bytes": 685,
|
||||
"max_bytes": 685
|
||||
}]
|
||||
}
|
||||
@@ -0,0 +1,916 @@
|
||||
{
|
||||
"duration_seconds": 120,
|
||||
"total_events": 5012,
|
||||
"total_bytes": 8091410,
|
||||
"max_event_bytes": 52672,
|
||||
"max_event_kind": 3,
|
||||
"unique_pubkeys": 2034,
|
||||
"relay_count": 3,
|
||||
"relays": [{
|
||||
"url": "wss://relay.primal.net",
|
||||
"events": 1599,
|
||||
"eose": 1,
|
||||
"closed": 0,
|
||||
"notice": 0,
|
||||
"errors": 0,
|
||||
"disconnects": 0,
|
||||
"connected": true,
|
||||
"raw_responses": []
|
||||
}, {
|
||||
"url": "wss://nos.lol",
|
||||
"events": 2389,
|
||||
"eose": 0,
|
||||
"closed": 0,
|
||||
"notice": 0,
|
||||
"errors": 0,
|
||||
"disconnects": 0,
|
||||
"connected": true,
|
||||
"raw_responses": []
|
||||
}, {
|
||||
"url": "wss://relay.damus.io",
|
||||
"events": 1024,
|
||||
"eose": 0,
|
||||
"closed": 0,
|
||||
"notice": 0,
|
||||
"errors": 0,
|
||||
"disconnects": 0,
|
||||
"connected": true,
|
||||
"raw_responses": []
|
||||
}],
|
||||
"kinds": [{
|
||||
"kind": 21059,
|
||||
"count": 1361,
|
||||
"total_bytes": 4189338,
|
||||
"max_bytes": 5314
|
||||
}, {
|
||||
"kind": 5,
|
||||
"count": 579,
|
||||
"total_bytes": 254363,
|
||||
"max_bytes": 624
|
||||
}, {
|
||||
"kind": 22668,
|
||||
"count": 265,
|
||||
"total_bytes": 113685,
|
||||
"max_bytes": 429
|
||||
}, {
|
||||
"kind": 30078,
|
||||
"count": 190,
|
||||
"total_bytes": 702178,
|
||||
"max_bytes": 14343
|
||||
}, {
|
||||
"kind": 20001,
|
||||
"count": 181,
|
||||
"total_bytes": 108257,
|
||||
"max_bytes": 1489
|
||||
}, {
|
||||
"kind": 22639,
|
||||
"count": 176,
|
||||
"total_bytes": 136058,
|
||||
"max_bytes": 1228
|
||||
}, {
|
||||
"kind": 4515,
|
||||
"count": 168,
|
||||
"total_bytes": 319242,
|
||||
"max_bytes": 14220
|
||||
}, {
|
||||
"kind": 24133,
|
||||
"count": 152,
|
||||
"total_bytes": 464764,
|
||||
"max_bytes": 14162
|
||||
}, {
|
||||
"kind": 22734,
|
||||
"count": 135,
|
||||
"total_bytes": 57645,
|
||||
"max_bytes": 427
|
||||
}, {
|
||||
"kind": 31991,
|
||||
"count": 116,
|
||||
"total_bytes": 53476,
|
||||
"max_bytes": 461
|
||||
}, {
|
||||
"kind": 21050,
|
||||
"count": 84,
|
||||
"total_bytes": 81900,
|
||||
"max_bytes": 2558
|
||||
}, {
|
||||
"kind": 1,
|
||||
"count": 80,
|
||||
"total_bytes": 58412,
|
||||
"max_bytes": 1443
|
||||
}, {
|
||||
"kind": 22795,
|
||||
"count": 76,
|
||||
"total_bytes": 104000,
|
||||
"max_bytes": 1848
|
||||
}, {
|
||||
"kind": 22850,
|
||||
"count": 75,
|
||||
"total_bytes": 33353,
|
||||
"max_bytes": 1169
|
||||
}, {
|
||||
"kind": 38501,
|
||||
"count": 69,
|
||||
"total_bytes": 51105,
|
||||
"max_bytes": 744
|
||||
}, {
|
||||
"kind": 22842,
|
||||
"count": 55,
|
||||
"total_bytes": 92475,
|
||||
"max_bytes": 1849
|
||||
}, {
|
||||
"kind": 10002,
|
||||
"count": 48,
|
||||
"total_bytes": 19784,
|
||||
"max_bytes": 537
|
||||
}, {
|
||||
"kind": 0,
|
||||
"count": 47,
|
||||
"total_bytes": 34961,
|
||||
"max_bytes": 1356
|
||||
}, {
|
||||
"kind": 37195,
|
||||
"count": 38,
|
||||
"total_bytes": 28214,
|
||||
"max_bytes": 771
|
||||
}, {
|
||||
"kind": 7,
|
||||
"count": 38,
|
||||
"total_bytes": 21600,
|
||||
"max_bytes": 779
|
||||
}, {
|
||||
"kind": 25050,
|
||||
"count": 36,
|
||||
"total_bytes": 15972,
|
||||
"max_bytes": 465
|
||||
}, {
|
||||
"kind": 24242,
|
||||
"count": 34,
|
||||
"total_bytes": 19686,
|
||||
"max_bytes": 579
|
||||
}, {
|
||||
"kind": 1059,
|
||||
"count": 33,
|
||||
"total_bytes": 58147,
|
||||
"max_bytes": 3298
|
||||
}, {
|
||||
"kind": 22484,
|
||||
"count": 32,
|
||||
"total_bytes": 29156,
|
||||
"max_bytes": 1164
|
||||
}, {
|
||||
"kind": 22507,
|
||||
"count": 28,
|
||||
"total_bytes": 24308,
|
||||
"max_bytes": 1165
|
||||
}, {
|
||||
"kind": 22613,
|
||||
"count": 25,
|
||||
"total_bytes": 17238,
|
||||
"max_bytes": 691
|
||||
}, {
|
||||
"kind": 29333,
|
||||
"count": 25,
|
||||
"total_bytes": 12300,
|
||||
"max_bytes": 492
|
||||
}, {
|
||||
"kind": 22601,
|
||||
"count": 24,
|
||||
"total_bytes": 10272,
|
||||
"max_bytes": 428
|
||||
}, {
|
||||
"kind": 5300,
|
||||
"count": 23,
|
||||
"total_bytes": 14096,
|
||||
"max_bytes": 701
|
||||
}, {
|
||||
"kind": 22751,
|
||||
"count": 23,
|
||||
"total_bytes": 9798,
|
||||
"max_bytes": 426
|
||||
}, {
|
||||
"kind": 22699,
|
||||
"count": 22,
|
||||
"total_bytes": 9416,
|
||||
"max_bytes": 428
|
||||
}, {
|
||||
"kind": 11998,
|
||||
"count": 22,
|
||||
"total_bytes": 10182,
|
||||
"max_bytes": 465
|
||||
}, {
|
||||
"kind": 22676,
|
||||
"count": 22,
|
||||
"total_bytes": 9394,
|
||||
"max_bytes": 427
|
||||
}, {
|
||||
"kind": 13194,
|
||||
"count": 21,
|
||||
"total_bytes": 10617,
|
||||
"max_bytes": 514
|
||||
}, {
|
||||
"kind": 22774,
|
||||
"count": 20,
|
||||
"total_bytes": 8560,
|
||||
"max_bytes": 428
|
||||
}, {
|
||||
"kind": 23003,
|
||||
"count": 20,
|
||||
"total_bytes": 8560,
|
||||
"max_bytes": 428
|
||||
}, {
|
||||
"kind": 22655,
|
||||
"count": 19,
|
||||
"total_bytes": 8132,
|
||||
"max_bytes": 428
|
||||
}, {
|
||||
"kind": 22543,
|
||||
"count": 19,
|
||||
"total_bytes": 34993,
|
||||
"max_bytes": 1848
|
||||
}, {
|
||||
"kind": 22455,
|
||||
"count": 19,
|
||||
"total_bytes": 34943,
|
||||
"max_bytes": 1844
|
||||
}, {
|
||||
"kind": 25555,
|
||||
"count": 19,
|
||||
"total_bytes": 94673,
|
||||
"max_bytes": 17111
|
||||
}, {
|
||||
"kind": 30443,
|
||||
"count": 19,
|
||||
"total_bytes": 22379,
|
||||
"max_bytes": 1260
|
||||
}, {
|
||||
"kind": 22777,
|
||||
"count": 19,
|
||||
"total_bytes": 16685,
|
||||
"max_bytes": 1651
|
||||
}, {
|
||||
"kind": 22891,
|
||||
"count": 18,
|
||||
"total_bytes": 33189,
|
||||
"max_bytes": 1848
|
||||
}, {
|
||||
"kind": 31990,
|
||||
"count": 17,
|
||||
"total_bytes": 15825,
|
||||
"max_bytes": 1465
|
||||
}, {
|
||||
"kind": 20000,
|
||||
"count": 16,
|
||||
"total_bytes": 7206,
|
||||
"max_bytes": 522
|
||||
}, {
|
||||
"kind": 32123,
|
||||
"count": 14,
|
||||
"total_bytes": 10528,
|
||||
"max_bytes": 900
|
||||
}, {
|
||||
"kind": 22456,
|
||||
"count": 13,
|
||||
"total_bytes": 6110,
|
||||
"max_bytes": 470
|
||||
}, {
|
||||
"kind": 20004,
|
||||
"count": 13,
|
||||
"total_bytes": 6741,
|
||||
"max_bytes": 549
|
||||
}, {
|
||||
"kind": 22591,
|
||||
"count": 13,
|
||||
"total_bytes": 6348,
|
||||
"max_bytes": 697
|
||||
}, {
|
||||
"kind": 20787,
|
||||
"count": 12,
|
||||
"total_bytes": 16864,
|
||||
"max_bytes": 2478
|
||||
}, {
|
||||
"kind": 4,
|
||||
"count": 12,
|
||||
"total_bytes": 7972,
|
||||
"max_bytes": 786
|
||||
}, {
|
||||
"kind": 20387,
|
||||
"count": 12,
|
||||
"total_bytes": 6168,
|
||||
"max_bytes": 514
|
||||
}, {
|
||||
"kind": 38502,
|
||||
"count": 12,
|
||||
"total_bytes": 4620,
|
||||
"max_bytes": 385
|
||||
}, {
|
||||
"kind": 10100,
|
||||
"count": 11,
|
||||
"total_bytes": 20938,
|
||||
"max_bytes": 3825
|
||||
}, {
|
||||
"kind": 20050,
|
||||
"count": 11,
|
||||
"total_bytes": 9711,
|
||||
"max_bytes": 891
|
||||
}, {
|
||||
"kind": 3,
|
||||
"count": 10,
|
||||
"total_bytes": 72137,
|
||||
"max_bytes": 52672
|
||||
}, {
|
||||
"kind": 9735,
|
||||
"count": 10,
|
||||
"total_bytes": 20833,
|
||||
"max_bytes": 2143
|
||||
}, {
|
||||
"kind": 445,
|
||||
"count": 10,
|
||||
"total_bytes": 17866,
|
||||
"max_bytes": 4126
|
||||
}, {
|
||||
"kind": 22626,
|
||||
"count": 10,
|
||||
"total_bytes": 4280,
|
||||
"max_bytes": 428
|
||||
}, {
|
||||
"kind": 7368,
|
||||
"count": 9,
|
||||
"total_bytes": 9343,
|
||||
"max_bytes": 1041
|
||||
}, {
|
||||
"kind": 22736,
|
||||
"count": 9,
|
||||
"total_bytes": 3816,
|
||||
"max_bytes": 424
|
||||
}, {
|
||||
"kind": 1985,
|
||||
"count": 8,
|
||||
"total_bytes": 3810,
|
||||
"max_bytes": 483
|
||||
}, {
|
||||
"kind": 30091,
|
||||
"count": 8,
|
||||
"total_bytes": 4927,
|
||||
"max_bytes": 629
|
||||
}, {
|
||||
"kind": 30315,
|
||||
"count": 8,
|
||||
"total_bytes": 4522,
|
||||
"max_bytes": 872
|
||||
}, {
|
||||
"kind": 25055,
|
||||
"count": 8,
|
||||
"total_bytes": 10605,
|
||||
"max_bytes": 1764
|
||||
}, {
|
||||
"kind": 22791,
|
||||
"count": 8,
|
||||
"total_bytes": 3416,
|
||||
"max_bytes": 427
|
||||
}, {
|
||||
"kind": 22816,
|
||||
"count": 8,
|
||||
"total_bytes": 3432,
|
||||
"max_bytes": 429
|
||||
}, {
|
||||
"kind": 4004,
|
||||
"count": 8,
|
||||
"total_bytes": 9352,
|
||||
"max_bytes": 1169
|
||||
}, {
|
||||
"kind": 30088,
|
||||
"count": 8,
|
||||
"total_bytes": 14929,
|
||||
"max_bytes": 1871
|
||||
}, {
|
||||
"kind": 31234,
|
||||
"count": 8,
|
||||
"total_bytes": 14048,
|
||||
"max_bytes": 1756
|
||||
}, {
|
||||
"kind": 22813,
|
||||
"count": 7,
|
||||
"total_bytes": 2996,
|
||||
"max_bytes": 428
|
||||
}, {
|
||||
"kind": 22957,
|
||||
"count": 7,
|
||||
"total_bytes": 3010,
|
||||
"max_bytes": 430
|
||||
}, {
|
||||
"kind": 30089,
|
||||
"count": 7,
|
||||
"total_bytes": 45972,
|
||||
"max_bytes": 27988
|
||||
}, {
|
||||
"kind": 32678,
|
||||
"count": 7,
|
||||
"total_bytes": 5704,
|
||||
"max_bytes": 900
|
||||
}, {
|
||||
"kind": 22832,
|
||||
"count": 6,
|
||||
"total_bytes": 2574,
|
||||
"max_bytes": 429
|
||||
}, {
|
||||
"kind": 22897,
|
||||
"count": 6,
|
||||
"total_bytes": 2586,
|
||||
"max_bytes": 431
|
||||
}, {
|
||||
"kind": 22549,
|
||||
"count": 6,
|
||||
"total_bytes": 2574,
|
||||
"max_bytes": 429
|
||||
}, {
|
||||
"kind": 22702,
|
||||
"count": 6,
|
||||
"total_bytes": 4753,
|
||||
"max_bytes": 2618
|
||||
}, {
|
||||
"kind": 20333,
|
||||
"count": 6,
|
||||
"total_bytes": 4780,
|
||||
"max_bytes": 798
|
||||
}, {
|
||||
"kind": 30023,
|
||||
"count": 6,
|
||||
"total_bytes": 21101,
|
||||
"max_bytes": 5056
|
||||
}, {
|
||||
"kind": 22568,
|
||||
"count": 5,
|
||||
"total_bytes": 2135,
|
||||
"max_bytes": 427
|
||||
}, {
|
||||
"kind": 38385,
|
||||
"count": 5,
|
||||
"total_bytes": 6849,
|
||||
"max_bytes": 1496
|
||||
}, {
|
||||
"kind": 4244,
|
||||
"count": 5,
|
||||
"total_bytes": 2820,
|
||||
"max_bytes": 564
|
||||
}, {
|
||||
"kind": 22717,
|
||||
"count": 5,
|
||||
"total_bytes": 2135,
|
||||
"max_bytes": 427
|
||||
}, {
|
||||
"kind": 21617,
|
||||
"count": 4,
|
||||
"total_bytes": 1980,
|
||||
"max_bytes": 495
|
||||
}, {
|
||||
"kind": 38225,
|
||||
"count": 4,
|
||||
"total_bytes": 4061,
|
||||
"max_bytes": 1039
|
||||
}, {
|
||||
"kind": 6,
|
||||
"count": 4,
|
||||
"total_bytes": 8823,
|
||||
"max_bytes": 3647
|
||||
}, {
|
||||
"kind": 22333,
|
||||
"count": 4,
|
||||
"total_bytes": 1773,
|
||||
"max_bytes": 444
|
||||
}, {
|
||||
"kind": 22962,
|
||||
"count": 3,
|
||||
"total_bytes": 1290,
|
||||
"max_bytes": 430
|
||||
}, {
|
||||
"kind": 33334,
|
||||
"count": 3,
|
||||
"total_bytes": 2229,
|
||||
"max_bytes": 831
|
||||
}, {
|
||||
"kind": 1002,
|
||||
"count": 3,
|
||||
"total_bytes": 2793,
|
||||
"max_bytes": 979
|
||||
}, {
|
||||
"kind": 22244,
|
||||
"count": 3,
|
||||
"total_bytes": 1330,
|
||||
"max_bytes": 444
|
||||
}, {
|
||||
"kind": 22907,
|
||||
"count": 3,
|
||||
"total_bytes": 1287,
|
||||
"max_bytes": 429
|
||||
}, {
|
||||
"kind": 10011,
|
||||
"count": 3,
|
||||
"total_bytes": 1229,
|
||||
"max_bytes": 431
|
||||
}, {
|
||||
"kind": 22258,
|
||||
"count": 3,
|
||||
"total_bytes": 1330,
|
||||
"max_bytes": 444
|
||||
}, {
|
||||
"kind": 22245,
|
||||
"count": 3,
|
||||
"total_bytes": 1331,
|
||||
"max_bytes": 444
|
||||
}, {
|
||||
"kind": 30618,
|
||||
"count": 3,
|
||||
"total_bytes": 1755,
|
||||
"max_bytes": 733
|
||||
}, {
|
||||
"kind": 22296,
|
||||
"count": 3,
|
||||
"total_bytes": 1331,
|
||||
"max_bytes": 444
|
||||
}, {
|
||||
"kind": 38503,
|
||||
"count": 3,
|
||||
"total_bytes": 1659,
|
||||
"max_bytes": 553
|
||||
}, {
|
||||
"kind": 22338,
|
||||
"count": 3,
|
||||
"total_bytes": 1330,
|
||||
"max_bytes": 444
|
||||
}, {
|
||||
"kind": 22195,
|
||||
"count": 3,
|
||||
"total_bytes": 1331,
|
||||
"max_bytes": 444
|
||||
}, {
|
||||
"kind": 22342,
|
||||
"count": 3,
|
||||
"total_bytes": 1331,
|
||||
"max_bytes": 444
|
||||
}, {
|
||||
"kind": 10050,
|
||||
"count": 3,
|
||||
"total_bytes": 1350,
|
||||
"max_bytes": 450
|
||||
}, {
|
||||
"kind": 30311,
|
||||
"count": 3,
|
||||
"total_bytes": 3414,
|
||||
"max_bytes": 1197
|
||||
}, {
|
||||
"kind": 32680,
|
||||
"count": 2,
|
||||
"total_bytes": 1376,
|
||||
"max_bytes": 688
|
||||
}, {
|
||||
"kind": 30380,
|
||||
"count": 2,
|
||||
"total_bytes": 908,
|
||||
"max_bytes": 454
|
||||
}, {
|
||||
"kind": 22611,
|
||||
"count": 2,
|
||||
"total_bytes": 852,
|
||||
"max_bytes": 426
|
||||
}, {
|
||||
"kind": 4243,
|
||||
"count": 2,
|
||||
"total_bytes": 1128,
|
||||
"max_bytes": 564
|
||||
}, {
|
||||
"kind": 22526,
|
||||
"count": 2,
|
||||
"total_bytes": 860,
|
||||
"max_bytes": 430
|
||||
}, {
|
||||
"kind": 22320,
|
||||
"count": 2,
|
||||
"total_bytes": 887,
|
||||
"max_bytes": 444
|
||||
}, {
|
||||
"kind": 4245,
|
||||
"count": 2,
|
||||
"total_bytes": 888,
|
||||
"max_bytes": 444
|
||||
}, {
|
||||
"kind": 1984,
|
||||
"count": 2,
|
||||
"total_bytes": 873,
|
||||
"max_bytes": 446
|
||||
}, {
|
||||
"kind": 1111,
|
||||
"count": 2,
|
||||
"total_bytes": 3115,
|
||||
"max_bytes": 1558
|
||||
}, {
|
||||
"kind": 22311,
|
||||
"count": 2,
|
||||
"total_bytes": 886,
|
||||
"max_bytes": 443
|
||||
}, {
|
||||
"kind": 22662,
|
||||
"count": 2,
|
||||
"total_bytes": 858,
|
||||
"max_bytes": 429
|
||||
}, {
|
||||
"kind": 22089,
|
||||
"count": 2,
|
||||
"total_bytes": 886,
|
||||
"max_bytes": 443
|
||||
}, {
|
||||
"kind": 22221,
|
||||
"count": 2,
|
||||
"total_bytes": 887,
|
||||
"max_bytes": 444
|
||||
}, {
|
||||
"kind": 22157,
|
||||
"count": 2,
|
||||
"total_bytes": 887,
|
||||
"max_bytes": 444
|
||||
}, {
|
||||
"kind": 38384,
|
||||
"count": 2,
|
||||
"total_bytes": 1486,
|
||||
"max_bytes": 743
|
||||
}, {
|
||||
"kind": 20384,
|
||||
"count": 2,
|
||||
"total_bytes": 1278,
|
||||
"max_bytes": 639
|
||||
}, {
|
||||
"kind": 30080,
|
||||
"count": 2,
|
||||
"total_bytes": 1679,
|
||||
"max_bytes": 985
|
||||
}, {
|
||||
"kind": 39101,
|
||||
"count": 2,
|
||||
"total_bytes": 1066,
|
||||
"max_bytes": 533
|
||||
}, {
|
||||
"kind": 6300,
|
||||
"count": 2,
|
||||
"total_bytes": 11904,
|
||||
"max_bytes": 6898
|
||||
}, {
|
||||
"kind": 10003,
|
||||
"count": 2,
|
||||
"total_bytes": 14466,
|
||||
"max_bytes": 7233
|
||||
}, {
|
||||
"kind": 30515,
|
||||
"count": 2,
|
||||
"total_bytes": 9248,
|
||||
"max_bytes": 4624
|
||||
}, {
|
||||
"kind": 22829,
|
||||
"count": 2,
|
||||
"total_bytes": 6387,
|
||||
"max_bytes": 3194
|
||||
}, {
|
||||
"kind": 22106,
|
||||
"count": 2,
|
||||
"total_bytes": 887,
|
||||
"max_bytes": 444
|
||||
}, {
|
||||
"kind": 31927,
|
||||
"count": 2,
|
||||
"total_bytes": 3000,
|
||||
"max_bytes": 1500
|
||||
}, {
|
||||
"kind": 31510,
|
||||
"count": 2,
|
||||
"total_bytes": 1959,
|
||||
"max_bytes": 980
|
||||
}, {
|
||||
"kind": 3927,
|
||||
"count": 2,
|
||||
"total_bytes": 1066,
|
||||
"max_bytes": 533
|
||||
}, {
|
||||
"kind": 1040,
|
||||
"count": 2,
|
||||
"total_bytes": 2096,
|
||||
"max_bytes": 1048
|
||||
}, {
|
||||
"kind": 31000,
|
||||
"count": 2,
|
||||
"total_bytes": 1204,
|
||||
"max_bytes": 616
|
||||
}, {
|
||||
"kind": 22201,
|
||||
"count": 2,
|
||||
"total_bytes": 886,
|
||||
"max_bytes": 443
|
||||
}, {
|
||||
"kind": 22269,
|
||||
"count": 2,
|
||||
"total_bytes": 887,
|
||||
"max_bytes": 444
|
||||
}, {
|
||||
"kind": 22818,
|
||||
"count": 2,
|
||||
"total_bytes": 852,
|
||||
"max_bytes": 426
|
||||
}, {
|
||||
"kind": 22364,
|
||||
"count": 2,
|
||||
"total_bytes": 887,
|
||||
"max_bytes": 444
|
||||
}, {
|
||||
"kind": 25195,
|
||||
"count": 1,
|
||||
"total_bytes": 678,
|
||||
"max_bytes": 678
|
||||
}, {
|
||||
"kind": 25196,
|
||||
"count": 1,
|
||||
"total_bytes": 1362,
|
||||
"max_bytes": 1362
|
||||
}, {
|
||||
"kind": 22283,
|
||||
"count": 1,
|
||||
"total_bytes": 443,
|
||||
"max_bytes": 443
|
||||
}, {
|
||||
"kind": 10030,
|
||||
"count": 1,
|
||||
"total_bytes": 405,
|
||||
"max_bytes": 405
|
||||
}, {
|
||||
"kind": 22706,
|
||||
"count": 1,
|
||||
"total_bytes": 3192,
|
||||
"max_bytes": 3192
|
||||
}, {
|
||||
"kind": 22236,
|
||||
"count": 1,
|
||||
"total_bytes": 737,
|
||||
"max_bytes": 737
|
||||
}, {
|
||||
"kind": 31339,
|
||||
"count": 1,
|
||||
"total_bytes": 1470,
|
||||
"max_bytes": 1470
|
||||
}, {
|
||||
"kind": 22651,
|
||||
"count": 1,
|
||||
"total_bytes": 428,
|
||||
"max_bytes": 428
|
||||
}, {
|
||||
"kind": 38500,
|
||||
"count": 1,
|
||||
"total_bytes": 713,
|
||||
"max_bytes": 713
|
||||
}, {
|
||||
"kind": 10000,
|
||||
"count": 1,
|
||||
"total_bytes": 1311,
|
||||
"max_bytes": 1311
|
||||
}, {
|
||||
"kind": 31926,
|
||||
"count": 1,
|
||||
"total_bytes": 1038,
|
||||
"max_bytes": 1038
|
||||
}, {
|
||||
"kind": 22757,
|
||||
"count": 1,
|
||||
"total_bytes": 428,
|
||||
"max_bytes": 428
|
||||
}, {
|
||||
"kind": 39015,
|
||||
"count": 1,
|
||||
"total_bytes": 696,
|
||||
"max_bytes": 696
|
||||
}, {
|
||||
"kind": 30617,
|
||||
"count": 1,
|
||||
"total_bytes": 1089,
|
||||
"max_bytes": 1089
|
||||
}, {
|
||||
"kind": 22234,
|
||||
"count": 1,
|
||||
"total_bytes": 443,
|
||||
"max_bytes": 443
|
||||
}, {
|
||||
"kind": 30815,
|
||||
"count": 1,
|
||||
"total_bytes": 37534,
|
||||
"max_bytes": 37534
|
||||
}, {
|
||||
"kind": 1078,
|
||||
"count": 1,
|
||||
"total_bytes": 13939,
|
||||
"max_bytes": 13939
|
||||
}, {
|
||||
"kind": 39050,
|
||||
"count": 1,
|
||||
"total_bytes": 1843,
|
||||
"max_bytes": 1843
|
||||
}, {
|
||||
"kind": 22281,
|
||||
"count": 1,
|
||||
"total_bytes": 443,
|
||||
"max_bytes": 443
|
||||
}, {
|
||||
"kind": 30166,
|
||||
"count": 1,
|
||||
"total_bytes": 808,
|
||||
"max_bytes": 808
|
||||
}, {
|
||||
"kind": 22772,
|
||||
"count": 1,
|
||||
"total_bytes": 429,
|
||||
"max_bytes": 429
|
||||
}, {
|
||||
"kind": 22356,
|
||||
"count": 1,
|
||||
"total_bytes": 443,
|
||||
"max_bytes": 443
|
||||
}, {
|
||||
"kind": 30554,
|
||||
"count": 1,
|
||||
"total_bytes": 609,
|
||||
"max_bytes": 609
|
||||
}, {
|
||||
"kind": 38422,
|
||||
"count": 1,
|
||||
"total_bytes": 20025,
|
||||
"max_bytes": 20025
|
||||
}, {
|
||||
"kind": 38000,
|
||||
"count": 1,
|
||||
"total_bytes": 562,
|
||||
"max_bytes": 562
|
||||
}, {
|
||||
"kind": 22069,
|
||||
"count": 1,
|
||||
"total_bytes": 443,
|
||||
"max_bytes": 443
|
||||
}, {
|
||||
"kind": 1050,
|
||||
"count": 1,
|
||||
"total_bytes": 437,
|
||||
"max_bytes": 437
|
||||
}, {
|
||||
"kind": 33051,
|
||||
"count": 1,
|
||||
"total_bytes": 522,
|
||||
"max_bytes": 522
|
||||
}, {
|
||||
"kind": 39036,
|
||||
"count": 1,
|
||||
"total_bytes": 1138,
|
||||
"max_bytes": 1138
|
||||
}, {
|
||||
"kind": 23194,
|
||||
"count": 1,
|
||||
"total_bytes": 510,
|
||||
"max_bytes": 510
|
||||
}, {
|
||||
"kind": 30081,
|
||||
"count": 1,
|
||||
"total_bytes": 1370,
|
||||
"max_bytes": 1370
|
||||
}, {
|
||||
"kind": 22299,
|
||||
"count": 1,
|
||||
"total_bytes": 443,
|
||||
"max_bytes": 443
|
||||
}, {
|
||||
"kind": 22556,
|
||||
"count": 1,
|
||||
"total_bytes": 427,
|
||||
"max_bytes": 427
|
||||
}, {
|
||||
"kind": 22302,
|
||||
"count": 1,
|
||||
"total_bytes": 443,
|
||||
"max_bytes": 443
|
||||
}, {
|
||||
"kind": 39019,
|
||||
"count": 1,
|
||||
"total_bytes": 961,
|
||||
"max_bytes": 961
|
||||
}, {
|
||||
"kind": 30000,
|
||||
"count": 1,
|
||||
"total_bytes": 823,
|
||||
"max_bytes": 823
|
||||
}, {
|
||||
"kind": 38383,
|
||||
"count": 1,
|
||||
"total_bytes": 657,
|
||||
"max_bytes": 657
|
||||
}, {
|
||||
"kind": 30087,
|
||||
"count": 1,
|
||||
"total_bytes": 7325,
|
||||
"max_bytes": 7325
|
||||
}, {
|
||||
"kind": 30090,
|
||||
"count": 1,
|
||||
"total_bytes": 1515,
|
||||
"max_bytes": 1515
|
||||
}]
|
||||
}
|
||||
@@ -0,0 +1,281 @@
|
||||
{
|
||||
"duration_seconds": 0,
|
||||
"total_events": 0,
|
||||
"total_bytes": 0,
|
||||
"max_event_bytes": 0,
|
||||
"max_event_kind": 0,
|
||||
"unique_pubkeys": 0,
|
||||
"relay_count": 27,
|
||||
"relays": [{
|
||||
"url": "wss://relay.primal.net",
|
||||
"events": 0,
|
||||
"eose": 0,
|
||||
"closed": 0,
|
||||
"notice": 0,
|
||||
"errors": 0,
|
||||
"disconnects": 0,
|
||||
"connected": false,
|
||||
"raw_responses": []
|
||||
}, {
|
||||
"url": "wss://nos.lol",
|
||||
"events": 0,
|
||||
"eose": 0,
|
||||
"closed": 0,
|
||||
"notice": 0,
|
||||
"errors": 0,
|
||||
"disconnects": 0,
|
||||
"connected": false,
|
||||
"raw_responses": []
|
||||
}, {
|
||||
"url": "wss://relay.damus.io",
|
||||
"events": 0,
|
||||
"eose": 0,
|
||||
"closed": 0,
|
||||
"notice": 0,
|
||||
"errors": 0,
|
||||
"disconnects": 0,
|
||||
"connected": false,
|
||||
"raw_responses": []
|
||||
}, {
|
||||
"url": "wss://relay.ditto.pub",
|
||||
"events": 0,
|
||||
"eose": 0,
|
||||
"closed": 0,
|
||||
"notice": 0,
|
||||
"errors": 0,
|
||||
"disconnects": 0,
|
||||
"connected": false,
|
||||
"raw_responses": []
|
||||
}, {
|
||||
"url": "wss://nostr.land",
|
||||
"events": 0,
|
||||
"eose": 0,
|
||||
"closed": 0,
|
||||
"notice": 0,
|
||||
"errors": 0,
|
||||
"disconnects": 0,
|
||||
"connected": false,
|
||||
"raw_responses": []
|
||||
}, {
|
||||
"url": "wss://nostr.wine",
|
||||
"events": 0,
|
||||
"eose": 0,
|
||||
"closed": 0,
|
||||
"notice": 0,
|
||||
"errors": 0,
|
||||
"disconnects": 0,
|
||||
"connected": false,
|
||||
"raw_responses": []
|
||||
}, {
|
||||
"url": "wss://nostr.oxtr.dev",
|
||||
"events": 0,
|
||||
"eose": 0,
|
||||
"closed": 0,
|
||||
"notice": 0,
|
||||
"errors": 0,
|
||||
"disconnects": 0,
|
||||
"connected": false,
|
||||
"raw_responses": []
|
||||
}, {
|
||||
"url": "wss://spatia-arcana.com/inbox",
|
||||
"events": 0,
|
||||
"eose": 0,
|
||||
"closed": 0,
|
||||
"notice": 0,
|
||||
"errors": 0,
|
||||
"disconnects": 0,
|
||||
"connected": false,
|
||||
"raw_responses": []
|
||||
}, {
|
||||
"url": "wss://eden.nostr.land",
|
||||
"events": 0,
|
||||
"eose": 0,
|
||||
"closed": 0,
|
||||
"notice": 0,
|
||||
"errors": 0,
|
||||
"disconnects": 0,
|
||||
"connected": false,
|
||||
"raw_responses": []
|
||||
}, {
|
||||
"url": "wss://relay.nostr.band",
|
||||
"events": 0,
|
||||
"eose": 0,
|
||||
"closed": 0,
|
||||
"notice": 0,
|
||||
"errors": 0,
|
||||
"disconnects": 0,
|
||||
"connected": false,
|
||||
"raw_responses": []
|
||||
}, {
|
||||
"url": "wss://theforest.nostr1.com",
|
||||
"events": 0,
|
||||
"eose": 0,
|
||||
"closed": 0,
|
||||
"notice": 0,
|
||||
"errors": 0,
|
||||
"disconnects": 0,
|
||||
"connected": false,
|
||||
"raw_responses": []
|
||||
}, {
|
||||
"url": "wss://wot.utxo.one",
|
||||
"events": 0,
|
||||
"eose": 0,
|
||||
"closed": 0,
|
||||
"notice": 0,
|
||||
"errors": 0,
|
||||
"disconnects": 0,
|
||||
"connected": false,
|
||||
"raw_responses": []
|
||||
}, {
|
||||
"url": "wss://premium.primal.net",
|
||||
"events": 0,
|
||||
"eose": 0,
|
||||
"closed": 0,
|
||||
"notice": 0,
|
||||
"errors": 0,
|
||||
"disconnects": 0,
|
||||
"connected": false,
|
||||
"raw_responses": []
|
||||
}, {
|
||||
"url": "wss://nostr.mom",
|
||||
"events": 0,
|
||||
"eose": 0,
|
||||
"closed": 0,
|
||||
"notice": 0,
|
||||
"errors": 0,
|
||||
"disconnects": 0,
|
||||
"connected": false,
|
||||
"raw_responses": []
|
||||
}, {
|
||||
"url": "wss://relay.mostr.pub",
|
||||
"events": 0,
|
||||
"eose": 0,
|
||||
"closed": 0,
|
||||
"notice": 0,
|
||||
"errors": 0,
|
||||
"disconnects": 0,
|
||||
"connected": false,
|
||||
"raw_responses": []
|
||||
}, {
|
||||
"url": "wss://offchain.pub",
|
||||
"events": 0,
|
||||
"eose": 0,
|
||||
"closed": 0,
|
||||
"notice": 0,
|
||||
"errors": 0,
|
||||
"disconnects": 0,
|
||||
"connected": false,
|
||||
"raw_responses": []
|
||||
}, {
|
||||
"url": "wss://relay.divine.video",
|
||||
"events": 0,
|
||||
"eose": 0,
|
||||
"closed": 0,
|
||||
"notice": 0,
|
||||
"errors": 0,
|
||||
"disconnects": 0,
|
||||
"connected": false,
|
||||
"raw_responses": []
|
||||
}, {
|
||||
"url": "wss://relay.nostrplebs.com",
|
||||
"events": 0,
|
||||
"eose": 0,
|
||||
"closed": 0,
|
||||
"notice": 0,
|
||||
"errors": 0,
|
||||
"disconnects": 0,
|
||||
"connected": false,
|
||||
"raw_responses": []
|
||||
}, {
|
||||
"url": "wss://nostr-pub.wellorder.net",
|
||||
"events": 0,
|
||||
"eose": 0,
|
||||
"closed": 0,
|
||||
"notice": 0,
|
||||
"errors": 0,
|
||||
"disconnects": 0,
|
||||
"connected": false,
|
||||
"raw_responses": []
|
||||
}, {
|
||||
"url": "wss://devrelay.azzamo.net",
|
||||
"events": 0,
|
||||
"eose": 0,
|
||||
"closed": 0,
|
||||
"notice": 0,
|
||||
"errors": 0,
|
||||
"disconnects": 0,
|
||||
"connected": false,
|
||||
"raw_responses": []
|
||||
}, {
|
||||
"url": "wss://relay.noderunners.network",
|
||||
"events": 0,
|
||||
"eose": 0,
|
||||
"closed": 0,
|
||||
"notice": 0,
|
||||
"errors": 0,
|
||||
"disconnects": 0,
|
||||
"connected": false,
|
||||
"raw_responses": []
|
||||
}, {
|
||||
"url": "wss://nostr-pub.semisol.dev",
|
||||
"events": 0,
|
||||
"eose": 0,
|
||||
"closed": 0,
|
||||
"notice": 0,
|
||||
"errors": 0,
|
||||
"disconnects": 0,
|
||||
"connected": false,
|
||||
"raw_responses": []
|
||||
}, {
|
||||
"url": "wss://relay.shosho.live",
|
||||
"events": 0,
|
||||
"eose": 0,
|
||||
"closed": 0,
|
||||
"notice": 0,
|
||||
"errors": 0,
|
||||
"disconnects": 0,
|
||||
"connected": false,
|
||||
"raw_responses": []
|
||||
}, {
|
||||
"url": "wss://relay.nostrcheck.me",
|
||||
"events": 0,
|
||||
"eose": 0,
|
||||
"closed": 0,
|
||||
"notice": 0,
|
||||
"errors": 0,
|
||||
"disconnects": 0,
|
||||
"connected": false,
|
||||
"raw_responses": []
|
||||
}, {
|
||||
"url": "wss://relay.nostr.info",
|
||||
"events": 0,
|
||||
"eose": 0,
|
||||
"closed": 0,
|
||||
"notice": 0,
|
||||
"errors": 0,
|
||||
"disconnects": 0,
|
||||
"connected": false,
|
||||
"raw_responses": []
|
||||
}, {
|
||||
"url": "wss://relay.momostr.pink",
|
||||
"events": 0,
|
||||
"eose": 0,
|
||||
"closed": 0,
|
||||
"notice": 0,
|
||||
"errors": 0,
|
||||
"disconnects": 0,
|
||||
"connected": false,
|
||||
"raw_responses": []
|
||||
}, {
|
||||
"url": "wss://bitsat.molonlabe.holdings",
|
||||
"events": 0,
|
||||
"eose": 0,
|
||||
"closed": 0,
|
||||
"notice": 0,
|
||||
"errors": 0,
|
||||
"disconnects": 0,
|
||||
"connected": false,
|
||||
"raw_responses": []
|
||||
}],
|
||||
"kinds": []
|
||||
}
|
||||
@@ -0,0 +1,161 @@
|
||||
{
|
||||
"duration_seconds": 0,
|
||||
"total_events": 0,
|
||||
"total_bytes": 0,
|
||||
"max_event_bytes": 0,
|
||||
"max_event_kind": 0,
|
||||
"unique_pubkeys": 0,
|
||||
"relay_count": 15,
|
||||
"relays": [{
|
||||
"url": "wss://relay.primal.net",
|
||||
"events": 0,
|
||||
"eose": 0,
|
||||
"closed": 0,
|
||||
"notice": 0,
|
||||
"errors": 0,
|
||||
"disconnects": 0,
|
||||
"connected": false,
|
||||
"raw_responses": []
|
||||
}, {
|
||||
"url": "wss://nos.lol",
|
||||
"events": 0,
|
||||
"eose": 0,
|
||||
"closed": 0,
|
||||
"notice": 0,
|
||||
"errors": 0,
|
||||
"disconnects": 0,
|
||||
"connected": false,
|
||||
"raw_responses": []
|
||||
}, {
|
||||
"url": "wss://relay.damus.io",
|
||||
"events": 0,
|
||||
"eose": 0,
|
||||
"closed": 0,
|
||||
"notice": 0,
|
||||
"errors": 0,
|
||||
"disconnects": 0,
|
||||
"connected": false,
|
||||
"raw_responses": []
|
||||
}, {
|
||||
"url": "wss://nostr.land",
|
||||
"events": 0,
|
||||
"eose": 0,
|
||||
"closed": 0,
|
||||
"notice": 0,
|
||||
"errors": 0,
|
||||
"disconnects": 0,
|
||||
"connected": false,
|
||||
"raw_responses": []
|
||||
}, {
|
||||
"url": "wss://relay.ditto.pub",
|
||||
"events": 0,
|
||||
"eose": 0,
|
||||
"closed": 0,
|
||||
"notice": 0,
|
||||
"errors": 0,
|
||||
"disconnects": 0,
|
||||
"connected": false,
|
||||
"raw_responses": []
|
||||
}, {
|
||||
"url": "wss://nostr.oxtr.dev",
|
||||
"events": 0,
|
||||
"eose": 0,
|
||||
"closed": 0,
|
||||
"notice": 0,
|
||||
"errors": 0,
|
||||
"disconnects": 0,
|
||||
"connected": false,
|
||||
"raw_responses": []
|
||||
}, {
|
||||
"url": "wss://pyramid.fiatjaf.com/inbox",
|
||||
"events": 0,
|
||||
"eose": 0,
|
||||
"closed": 0,
|
||||
"notice": 0,
|
||||
"errors": 0,
|
||||
"disconnects": 0,
|
||||
"connected": false,
|
||||
"raw_responses": []
|
||||
}, {
|
||||
"url": "wss://relay.mostr.pub",
|
||||
"events": 0,
|
||||
"eose": 0,
|
||||
"closed": 0,
|
||||
"notice": 0,
|
||||
"errors": 0,
|
||||
"disconnects": 0,
|
||||
"connected": false,
|
||||
"raw_responses": []
|
||||
}, {
|
||||
"url": "wss://relay.divine.video",
|
||||
"events": 0,
|
||||
"eose": 0,
|
||||
"closed": 0,
|
||||
"notice": 0,
|
||||
"errors": 0,
|
||||
"disconnects": 0,
|
||||
"connected": false,
|
||||
"raw_responses": []
|
||||
}, {
|
||||
"url": "wss://nostr.wine",
|
||||
"events": 0,
|
||||
"eose": 0,
|
||||
"closed": 0,
|
||||
"notice": 0,
|
||||
"errors": 0,
|
||||
"disconnects": 0,
|
||||
"connected": false,
|
||||
"raw_responses": []
|
||||
}, {
|
||||
"url": "wss://theforest.nostr1.com",
|
||||
"events": 0,
|
||||
"eose": 0,
|
||||
"closed": 0,
|
||||
"notice": 0,
|
||||
"errors": 0,
|
||||
"disconnects": 0,
|
||||
"connected": false,
|
||||
"raw_responses": []
|
||||
}, {
|
||||
"url": "wss://relay.nostrplebs.com",
|
||||
"events": 0,
|
||||
"eose": 0,
|
||||
"closed": 0,
|
||||
"notice": 0,
|
||||
"errors": 0,
|
||||
"disconnects": 0,
|
||||
"connected": false,
|
||||
"raw_responses": []
|
||||
}, {
|
||||
"url": "wss://relay.shosho.live",
|
||||
"events": 0,
|
||||
"eose": 0,
|
||||
"closed": 0,
|
||||
"notice": 0,
|
||||
"errors": 0,
|
||||
"disconnects": 0,
|
||||
"connected": false,
|
||||
"raw_responses": []
|
||||
}, {
|
||||
"url": "wss://relay.nostr.band",
|
||||
"events": 0,
|
||||
"eose": 0,
|
||||
"closed": 0,
|
||||
"notice": 0,
|
||||
"errors": 0,
|
||||
"disconnects": 0,
|
||||
"connected": false,
|
||||
"raw_responses": []
|
||||
}, {
|
||||
"url": "wss://relay.nostr.info",
|
||||
"events": 0,
|
||||
"eose": 0,
|
||||
"closed": 0,
|
||||
"notice": 0,
|
||||
"errors": 0,
|
||||
"disconnects": 0,
|
||||
"connected": false,
|
||||
"raw_responses": []
|
||||
}],
|
||||
"kinds": []
|
||||
}
|
||||
@@ -0,0 +1,121 @@
|
||||
{
|
||||
"duration_seconds": 0,
|
||||
"total_events": 0,
|
||||
"total_bytes": 0,
|
||||
"max_event_bytes": 0,
|
||||
"max_event_kind": 0,
|
||||
"unique_pubkeys": 0,
|
||||
"relay_count": 11,
|
||||
"relays": [{
|
||||
"url": "wss://relay.primal.net",
|
||||
"events": 0,
|
||||
"eose": 0,
|
||||
"closed": 0,
|
||||
"notice": 0,
|
||||
"errors": 0,
|
||||
"disconnects": 0,
|
||||
"connected": false,
|
||||
"raw_responses": []
|
||||
}, {
|
||||
"url": "wss://nos.lol",
|
||||
"events": 0,
|
||||
"eose": 0,
|
||||
"closed": 0,
|
||||
"notice": 0,
|
||||
"errors": 0,
|
||||
"disconnects": 0,
|
||||
"connected": false,
|
||||
"raw_responses": []
|
||||
}, {
|
||||
"url": "wss://relay.damus.io",
|
||||
"events": 0,
|
||||
"eose": 0,
|
||||
"closed": 0,
|
||||
"notice": 0,
|
||||
"errors": 0,
|
||||
"disconnects": 0,
|
||||
"connected": false,
|
||||
"raw_responses": []
|
||||
}, {
|
||||
"url": "wss://relay.ditto.pub",
|
||||
"events": 0,
|
||||
"eose": 0,
|
||||
"closed": 0,
|
||||
"notice": 0,
|
||||
"errors": 0,
|
||||
"disconnects": 0,
|
||||
"connected": false,
|
||||
"raw_responses": []
|
||||
}, {
|
||||
"url": "wss://nostr.bitcoiner.social",
|
||||
"events": 0,
|
||||
"eose": 0,
|
||||
"closed": 0,
|
||||
"notice": 0,
|
||||
"errors": 0,
|
||||
"disconnects": 0,
|
||||
"connected": false,
|
||||
"raw_responses": []
|
||||
}, {
|
||||
"url": "wss://nostr.land",
|
||||
"events": 0,
|
||||
"eose": 0,
|
||||
"closed": 0,
|
||||
"notice": 0,
|
||||
"errors": 0,
|
||||
"disconnects": 0,
|
||||
"connected": false,
|
||||
"raw_responses": []
|
||||
}, {
|
||||
"url": "wss://pyramid.fiatjaf.com/inbox",
|
||||
"events": 0,
|
||||
"eose": 0,
|
||||
"closed": 0,
|
||||
"notice": 0,
|
||||
"errors": 0,
|
||||
"disconnects": 0,
|
||||
"connected": false,
|
||||
"raw_responses": []
|
||||
}, {
|
||||
"url": "wss://relay.divine.video",
|
||||
"events": 0,
|
||||
"eose": 0,
|
||||
"closed": 0,
|
||||
"notice": 0,
|
||||
"errors": 0,
|
||||
"disconnects": 0,
|
||||
"connected": false,
|
||||
"raw_responses": []
|
||||
}, {
|
||||
"url": "wss://relay.nostrplebs.com",
|
||||
"events": 0,
|
||||
"eose": 0,
|
||||
"closed": 0,
|
||||
"notice": 0,
|
||||
"errors": 0,
|
||||
"disconnects": 0,
|
||||
"connected": false,
|
||||
"raw_responses": []
|
||||
}, {
|
||||
"url": "wss://eden.nostr.land",
|
||||
"events": 0,
|
||||
"eose": 0,
|
||||
"closed": 0,
|
||||
"notice": 0,
|
||||
"errors": 0,
|
||||
"disconnects": 0,
|
||||
"connected": false,
|
||||
"raw_responses": []
|
||||
}, {
|
||||
"url": "wss://relay.shosho.live",
|
||||
"events": 0,
|
||||
"eose": 0,
|
||||
"closed": 0,
|
||||
"notice": 0,
|
||||
"errors": 0,
|
||||
"disconnects": 0,
|
||||
"connected": false,
|
||||
"raw_responses": []
|
||||
}],
|
||||
"kinds": []
|
||||
}
|
||||
@@ -0,0 +1,834 @@
|
||||
{
|
||||
"duration_seconds": 114,
|
||||
"total_events": 4719,
|
||||
"total_bytes": 6608416,
|
||||
"unique_pubkeys": 1333,
|
||||
"relay_count": 15,
|
||||
"relays": [{
|
||||
"url": "wss://laantungir.net",
|
||||
"events": 0,
|
||||
"eose": 0,
|
||||
"closed": 0,
|
||||
"notice": 0,
|
||||
"errors": 0,
|
||||
"disconnects": 0,
|
||||
"connected": false
|
||||
}, {
|
||||
"url": "wss://nos.lol",
|
||||
"events": 804,
|
||||
"eose": 0,
|
||||
"closed": 0,
|
||||
"notice": 0,
|
||||
"errors": 0,
|
||||
"disconnects": 3,
|
||||
"connected": true
|
||||
}, {
|
||||
"url": "wss://nostr-pub.wellorder.net",
|
||||
"events": 83,
|
||||
"eose": 0,
|
||||
"closed": 0,
|
||||
"notice": 0,
|
||||
"errors": 0,
|
||||
"disconnects": 0,
|
||||
"connected": true
|
||||
}, {
|
||||
"url": "wss://nostr.mom",
|
||||
"events": 175,
|
||||
"eose": 0,
|
||||
"closed": 0,
|
||||
"notice": 0,
|
||||
"errors": 0,
|
||||
"disconnects": 0,
|
||||
"connected": true
|
||||
}, {
|
||||
"url": "wss://nostr.oxtr.dev",
|
||||
"events": 108,
|
||||
"eose": 0,
|
||||
"closed": 0,
|
||||
"notice": 0,
|
||||
"errors": 0,
|
||||
"disconnects": 0,
|
||||
"connected": true
|
||||
}, {
|
||||
"url": "wss://offchain.pub",
|
||||
"events": 627,
|
||||
"eose": 0,
|
||||
"closed": 0,
|
||||
"notice": 0,
|
||||
"errors": 0,
|
||||
"disconnects": 0,
|
||||
"connected": true
|
||||
}, {
|
||||
"url": "wss://premium.primal.net",
|
||||
"events": 1,
|
||||
"eose": 0,
|
||||
"closed": 0,
|
||||
"notice": 0,
|
||||
"errors": 0,
|
||||
"disconnects": 0,
|
||||
"connected": true
|
||||
}, {
|
||||
"url": "wss://relay.damus.io",
|
||||
"events": 0,
|
||||
"eose": 0,
|
||||
"closed": 0,
|
||||
"notice": 0,
|
||||
"errors": 0,
|
||||
"disconnects": 0,
|
||||
"connected": false
|
||||
}, {
|
||||
"url": "wss://relay.ditto.pub",
|
||||
"events": 721,
|
||||
"eose": 0,
|
||||
"closed": 0,
|
||||
"notice": 0,
|
||||
"errors": 0,
|
||||
"disconnects": 0,
|
||||
"connected": true
|
||||
}, {
|
||||
"url": "wss://relay.divine.video",
|
||||
"events": 3,
|
||||
"eose": 0,
|
||||
"closed": 0,
|
||||
"notice": 0,
|
||||
"errors": 0,
|
||||
"disconnects": 0,
|
||||
"connected": true
|
||||
}, {
|
||||
"url": "wss://relay.momostr.pink",
|
||||
"events": 86,
|
||||
"eose": 0,
|
||||
"closed": 0,
|
||||
"notice": 0,
|
||||
"errors": 0,
|
||||
"disconnects": 0,
|
||||
"connected": true
|
||||
}, {
|
||||
"url": "wss://relay.mostr.pub",
|
||||
"events": 836,
|
||||
"eose": 0,
|
||||
"closed": 0,
|
||||
"notice": 0,
|
||||
"errors": 0,
|
||||
"disconnects": 0,
|
||||
"connected": true
|
||||
}, {
|
||||
"url": "wss://relay.nostrplebs.com",
|
||||
"events": 4,
|
||||
"eose": 0,
|
||||
"closed": 0,
|
||||
"notice": 0,
|
||||
"errors": 0,
|
||||
"disconnects": 0,
|
||||
"connected": true
|
||||
}, {
|
||||
"url": "wss://relay.primal.net",
|
||||
"events": 1239,
|
||||
"eose": 0,
|
||||
"closed": 0,
|
||||
"notice": 0,
|
||||
"errors": 0,
|
||||
"disconnects": 0,
|
||||
"connected": true
|
||||
}, {
|
||||
"url": "wss://theforest.nostr1.com",
|
||||
"events": 32,
|
||||
"eose": 0,
|
||||
"closed": 0,
|
||||
"notice": 0,
|
||||
"errors": 0,
|
||||
"disconnects": 0,
|
||||
"connected": true
|
||||
}],
|
||||
"kinds": [{
|
||||
"kind": 21059,
|
||||
"count": 675,
|
||||
"total_bytes": 2192938,
|
||||
"max_bytes": 5314
|
||||
}, {
|
||||
"kind": 30382,
|
||||
"count": 563,
|
||||
"total_bytes": 255591,
|
||||
"max_bytes": 498
|
||||
}, {
|
||||
"kind": 5,
|
||||
"count": 341,
|
||||
"total_bytes": 153667,
|
||||
"max_bytes": 1404
|
||||
}, {
|
||||
"kind": 22639,
|
||||
"count": 231,
|
||||
"total_bytes": 178011,
|
||||
"max_bytes": 1230
|
||||
}, {
|
||||
"kind": 22551,
|
||||
"count": 182,
|
||||
"total_bytes": 78260,
|
||||
"max_bytes": 430
|
||||
}, {
|
||||
"kind": 20001,
|
||||
"count": 143,
|
||||
"total_bytes": 70427,
|
||||
"max_bytes": 1206
|
||||
}, {
|
||||
"kind": 30078,
|
||||
"count": 141,
|
||||
"total_bytes": 1361122,
|
||||
"max_bytes": 44169
|
||||
}, {
|
||||
"kind": 0,
|
||||
"count": 135,
|
||||
"total_bytes": 119793,
|
||||
"max_bytes": 3483
|
||||
}, {
|
||||
"kind": 22734,
|
||||
"count": 122,
|
||||
"total_bytes": 52094,
|
||||
"max_bytes": 427
|
||||
}, {
|
||||
"kind": 24747,
|
||||
"count": 101,
|
||||
"total_bytes": 59352,
|
||||
"max_bytes": 594
|
||||
}, {
|
||||
"kind": 1,
|
||||
"count": 90,
|
||||
"total_bytes": 92140,
|
||||
"max_bytes": 4709
|
||||
}, {
|
||||
"kind": 22668,
|
||||
"count": 88,
|
||||
"total_bytes": 37752,
|
||||
"max_bytes": 429
|
||||
}, {
|
||||
"kind": 22850,
|
||||
"count": 83,
|
||||
"total_bytes": 35690,
|
||||
"max_bytes": 430
|
||||
}, {
|
||||
"kind": 22870,
|
||||
"count": 76,
|
||||
"total_bytes": 77061,
|
||||
"max_bytes": 2202
|
||||
}, {
|
||||
"kind": 22951,
|
||||
"count": 75,
|
||||
"total_bytes": 77282,
|
||||
"max_bytes": 2204
|
||||
}, {
|
||||
"kind": 10002,
|
||||
"count": 75,
|
||||
"total_bytes": 202196,
|
||||
"max_bytes": 42385
|
||||
}, {
|
||||
"kind": 22912,
|
||||
"count": 74,
|
||||
"total_bytes": 31672,
|
||||
"max_bytes": 428
|
||||
}, {
|
||||
"kind": 38501,
|
||||
"count": 65,
|
||||
"total_bytes": 48152,
|
||||
"max_bytes": 744
|
||||
}, {
|
||||
"kind": 24133,
|
||||
"count": 63,
|
||||
"total_bytes": 72262,
|
||||
"max_bytes": 2898
|
||||
}, {
|
||||
"kind": 6,
|
||||
"count": 50,
|
||||
"total_bytes": 40985,
|
||||
"max_bytes": 3346
|
||||
}, {
|
||||
"kind": 37195,
|
||||
"count": 48,
|
||||
"total_bytes": 36225,
|
||||
"max_bytes": 771
|
||||
}, {
|
||||
"kind": 21050,
|
||||
"count": 48,
|
||||
"total_bytes": 46800,
|
||||
"max_bytes": 2558
|
||||
}, {
|
||||
"kind": 4515,
|
||||
"count": 46,
|
||||
"total_bytes": 81638,
|
||||
"max_bytes": 6028
|
||||
}, {
|
||||
"kind": 25555,
|
||||
"count": 45,
|
||||
"total_bytes": 209551,
|
||||
"max_bytes": 16603
|
||||
}, {
|
||||
"kind": 7,
|
||||
"count": 40,
|
||||
"total_bytes": 22486,
|
||||
"max_bytes": 805
|
||||
}, {
|
||||
"kind": 22917,
|
||||
"count": 39,
|
||||
"total_bytes": 35435,
|
||||
"max_bytes": 1166
|
||||
}, {
|
||||
"kind": 22699,
|
||||
"count": 39,
|
||||
"total_bytes": 26723,
|
||||
"max_bytes": 1166
|
||||
}, {
|
||||
"kind": 22690,
|
||||
"count": 39,
|
||||
"total_bytes": 16770,
|
||||
"max_bytes": 430
|
||||
}, {
|
||||
"kind": 22918,
|
||||
"count": 38,
|
||||
"total_bytes": 36470,
|
||||
"max_bytes": 1507
|
||||
}, {
|
||||
"kind": 22832,
|
||||
"count": 37,
|
||||
"total_bytes": 16128,
|
||||
"max_bytes": 446
|
||||
}, {
|
||||
"kind": 25050,
|
||||
"count": 35,
|
||||
"total_bytes": 15507,
|
||||
"max_bytes": 465
|
||||
}, {
|
||||
"kind": 30383,
|
||||
"count": 35,
|
||||
"total_bytes": 18766,
|
||||
"max_bytes": 541
|
||||
}, {
|
||||
"kind": 22713,
|
||||
"count": 34,
|
||||
"total_bytes": 14570,
|
||||
"max_bytes": 430
|
||||
}, {
|
||||
"kind": 22698,
|
||||
"count": 34,
|
||||
"total_bytes": 31371,
|
||||
"max_bytes": 1674
|
||||
}, {
|
||||
"kind": 22601,
|
||||
"count": 28,
|
||||
"total_bytes": 11984,
|
||||
"max_bytes": 428
|
||||
}, {
|
||||
"kind": 22655,
|
||||
"count": 28,
|
||||
"total_bytes": 11984,
|
||||
"max_bytes": 428
|
||||
}, {
|
||||
"kind": 1059,
|
||||
"count": 23,
|
||||
"total_bytes": 46912,
|
||||
"max_bytes": 5285
|
||||
}, {
|
||||
"kind": 22751,
|
||||
"count": 21,
|
||||
"total_bytes": 8946,
|
||||
"max_bytes": 426
|
||||
}, {
|
||||
"kind": 22676,
|
||||
"count": 21,
|
||||
"total_bytes": 8967,
|
||||
"max_bytes": 427
|
||||
}, {
|
||||
"kind": 29333,
|
||||
"count": 20,
|
||||
"total_bytes": 9840,
|
||||
"max_bytes": 492
|
||||
}, {
|
||||
"kind": 5300,
|
||||
"count": 20,
|
||||
"total_bytes": 11959,
|
||||
"max_bytes": 630
|
||||
}, {
|
||||
"kind": 22743,
|
||||
"count": 19,
|
||||
"total_bytes": 8132,
|
||||
"max_bytes": 428
|
||||
}, {
|
||||
"kind": 22603,
|
||||
"count": 19,
|
||||
"total_bytes": 8094,
|
||||
"max_bytes": 426
|
||||
}, {
|
||||
"kind": 22693,
|
||||
"count": 19,
|
||||
"total_bytes": 8113,
|
||||
"max_bytes": 427
|
||||
}, {
|
||||
"kind": 22774,
|
||||
"count": 19,
|
||||
"total_bytes": 8132,
|
||||
"max_bytes": 428
|
||||
}, {
|
||||
"kind": 22808,
|
||||
"count": 19,
|
||||
"total_bytes": 8151,
|
||||
"max_bytes": 429
|
||||
}, {
|
||||
"kind": 22575,
|
||||
"count": 19,
|
||||
"total_bytes": 8075,
|
||||
"max_bytes": 425
|
||||
}, {
|
||||
"kind": 23003,
|
||||
"count": 19,
|
||||
"total_bytes": 8132,
|
||||
"max_bytes": 428
|
||||
}, {
|
||||
"kind": 22949,
|
||||
"count": 19,
|
||||
"total_bytes": 8151,
|
||||
"max_bytes": 429
|
||||
}, {
|
||||
"kind": 23334,
|
||||
"count": 19,
|
||||
"total_bytes": 8189,
|
||||
"max_bytes": 431
|
||||
}, {
|
||||
"kind": 24242,
|
||||
"count": 17,
|
||||
"total_bytes": 9843,
|
||||
"max_bytes": 579
|
||||
}, {
|
||||
"kind": 22816,
|
||||
"count": 16,
|
||||
"total_bytes": 6864,
|
||||
"max_bytes": 429
|
||||
}, {
|
||||
"kind": 20787,
|
||||
"count": 16,
|
||||
"total_bytes": 25100,
|
||||
"max_bytes": 2478
|
||||
}, {
|
||||
"kind": 13194,
|
||||
"count": 15,
|
||||
"total_bytes": 7574,
|
||||
"max_bytes": 514
|
||||
}, {
|
||||
"kind": 38502,
|
||||
"count": 14,
|
||||
"total_bytes": 5390,
|
||||
"max_bytes": 385
|
||||
}, {
|
||||
"kind": 22236,
|
||||
"count": 14,
|
||||
"total_bytes": 11214,
|
||||
"max_bytes": 814
|
||||
}, {
|
||||
"kind": 22613,
|
||||
"count": 13,
|
||||
"total_bytes": 8977,
|
||||
"max_bytes": 694
|
||||
}, {
|
||||
"kind": 30088,
|
||||
"count": 12,
|
||||
"total_bytes": 22340,
|
||||
"max_bytes": 1871
|
||||
}, {
|
||||
"kind": 22484,
|
||||
"count": 12,
|
||||
"total_bytes": 10948,
|
||||
"max_bytes": 1165
|
||||
}, {
|
||||
"kind": 30091,
|
||||
"count": 12,
|
||||
"total_bytes": 7385,
|
||||
"max_bytes": 629
|
||||
}, {
|
||||
"kind": 20004,
|
||||
"count": 11,
|
||||
"total_bytes": 5643,
|
||||
"max_bytes": 549
|
||||
}, {
|
||||
"kind": 31990,
|
||||
"count": 11,
|
||||
"total_bytes": 8711,
|
||||
"max_bytes": 1465
|
||||
}, {
|
||||
"kind": 445,
|
||||
"count": 10,
|
||||
"total_bytes": 17972,
|
||||
"max_bytes": 4126
|
||||
}, {
|
||||
"kind": 22795,
|
||||
"count": 9,
|
||||
"total_bytes": 3861,
|
||||
"max_bytes": 429
|
||||
}, {
|
||||
"kind": 22507,
|
||||
"count": 9,
|
||||
"total_bytes": 8480,
|
||||
"max_bytes": 1165
|
||||
}, {
|
||||
"kind": 22922,
|
||||
"count": 9,
|
||||
"total_bytes": 3870,
|
||||
"max_bytes": 430
|
||||
}, {
|
||||
"kind": 24421,
|
||||
"count": 9,
|
||||
"total_bytes": 4644,
|
||||
"max_bytes": 516
|
||||
}, {
|
||||
"kind": 22830,
|
||||
"count": 9,
|
||||
"total_bytes": 7317,
|
||||
"max_bytes": 1168
|
||||
}, {
|
||||
"kind": 20000,
|
||||
"count": 9,
|
||||
"total_bytes": 3854,
|
||||
"max_bytes": 484
|
||||
}, {
|
||||
"kind": 22955,
|
||||
"count": 9,
|
||||
"total_bytes": 3852,
|
||||
"max_bytes": 428
|
||||
}, {
|
||||
"kind": 22793,
|
||||
"count": 9,
|
||||
"total_bytes": 3843,
|
||||
"max_bytes": 427
|
||||
}, {
|
||||
"kind": 30315,
|
||||
"count": 8,
|
||||
"total_bytes": 4604,
|
||||
"max_bytes": 926
|
||||
}, {
|
||||
"kind": 20387,
|
||||
"count": 8,
|
||||
"total_bytes": 4112,
|
||||
"max_bytes": 514
|
||||
}, {
|
||||
"kind": 7368,
|
||||
"count": 8,
|
||||
"total_bytes": 8309,
|
||||
"max_bytes": 1041
|
||||
}, {
|
||||
"kind": 4004,
|
||||
"count": 8,
|
||||
"total_bytes": 9352,
|
||||
"max_bytes": 1169
|
||||
}, {
|
||||
"kind": 443,
|
||||
"count": 8,
|
||||
"total_bytes": 8928,
|
||||
"max_bytes": 1116
|
||||
}, {
|
||||
"kind": 11998,
|
||||
"count": 7,
|
||||
"total_bytes": 3255,
|
||||
"max_bytes": 465
|
||||
}, {
|
||||
"kind": 10100,
|
||||
"count": 7,
|
||||
"total_bytes": 11851,
|
||||
"max_bytes": 3825
|
||||
}, {
|
||||
"kind": 22456,
|
||||
"count": 7,
|
||||
"total_bytes": 3290,
|
||||
"max_bytes": 470
|
||||
}, {
|
||||
"kind": 30089,
|
||||
"count": 7,
|
||||
"total_bytes": 157322,
|
||||
"max_bytes": 44372
|
||||
}, {
|
||||
"kind": 22737,
|
||||
"count": 7,
|
||||
"total_bytes": 4669,
|
||||
"max_bytes": 707
|
||||
}, {
|
||||
"kind": 23337,
|
||||
"count": 7,
|
||||
"total_bytes": 3557,
|
||||
"max_bytes": 509
|
||||
}, {
|
||||
"kind": 30515,
|
||||
"count": 7,
|
||||
"total_bytes": 18032,
|
||||
"max_bytes": 2576
|
||||
}, {
|
||||
"kind": 30311,
|
||||
"count": 6,
|
||||
"total_bytes": 5818,
|
||||
"max_bytes": 1197
|
||||
}, {
|
||||
"kind": 1985,
|
||||
"count": 6,
|
||||
"total_bytes": 2860,
|
||||
"max_bytes": 482
|
||||
}, {
|
||||
"kind": 22859,
|
||||
"count": 5,
|
||||
"total_bytes": 8606,
|
||||
"max_bytes": 2195
|
||||
}, {
|
||||
"kind": 4,
|
||||
"count": 5,
|
||||
"total_bytes": 3222,
|
||||
"max_bytes": 722
|
||||
}, {
|
||||
"kind": 10011,
|
||||
"count": 5,
|
||||
"total_bytes": 2027,
|
||||
"max_bytes": 431
|
||||
}, {
|
||||
"kind": 22764,
|
||||
"count": 4,
|
||||
"total_bytes": 1712,
|
||||
"max_bytes": 428
|
||||
}, {
|
||||
"kind": 22777,
|
||||
"count": 4,
|
||||
"total_bytes": 2790,
|
||||
"max_bytes": 698
|
||||
}, {
|
||||
"kind": 4244,
|
||||
"count": 4,
|
||||
"total_bytes": 2256,
|
||||
"max_bytes": 564
|
||||
}, {
|
||||
"kind": 30023,
|
||||
"count": 4,
|
||||
"total_bytes": 22789,
|
||||
"max_bytes": 6817
|
||||
}, {
|
||||
"kind": 9735,
|
||||
"count": 4,
|
||||
"total_bytes": 7033,
|
||||
"max_bytes": 1805
|
||||
}, {
|
||||
"kind": 20333,
|
||||
"count": 4,
|
||||
"total_bytes": 3188,
|
||||
"max_bytes": 798
|
||||
}, {
|
||||
"kind": 3,
|
||||
"count": 3,
|
||||
"total_bytes": 26232,
|
||||
"max_bytes": 14166
|
||||
}, {
|
||||
"kind": 38503,
|
||||
"count": 3,
|
||||
"total_bytes": 1655,
|
||||
"max_bytes": 552
|
||||
}, {
|
||||
"kind": 10050,
|
||||
"count": 3,
|
||||
"total_bytes": 1411,
|
||||
"max_bytes": 511
|
||||
}, {
|
||||
"kind": 21617,
|
||||
"count": 3,
|
||||
"total_bytes": 1485,
|
||||
"max_bytes": 495
|
||||
}, {
|
||||
"kind": 1984,
|
||||
"count": 3,
|
||||
"total_bytes": 1986,
|
||||
"max_bytes": 662
|
||||
}, {
|
||||
"kind": 3927,
|
||||
"count": 3,
|
||||
"total_bytes": 1599,
|
||||
"max_bytes": 533
|
||||
}, {
|
||||
"kind": 3434,
|
||||
"count": 3,
|
||||
"total_bytes": 1907,
|
||||
"max_bytes": 665
|
||||
}, {
|
||||
"kind": 22514,
|
||||
"count": 2,
|
||||
"total_bytes": 856,
|
||||
"max_bytes": 428
|
||||
}, {
|
||||
"kind": 33334,
|
||||
"count": 2,
|
||||
"total_bytes": 1662,
|
||||
"max_bytes": 831
|
||||
}, {
|
||||
"kind": 38500,
|
||||
"count": 2,
|
||||
"total_bytes": 1424,
|
||||
"max_bytes": 713
|
||||
}, {
|
||||
"kind": 22526,
|
||||
"count": 2,
|
||||
"total_bytes": 860,
|
||||
"max_bytes": 430
|
||||
}, {
|
||||
"kind": 30380,
|
||||
"count": 2,
|
||||
"total_bytes": 908,
|
||||
"max_bytes": 454
|
||||
}, {
|
||||
"kind": 23194,
|
||||
"count": 2,
|
||||
"total_bytes": 1020,
|
||||
"max_bytes": 510
|
||||
}, {
|
||||
"kind": 23042,
|
||||
"count": 2,
|
||||
"total_bytes": 858,
|
||||
"max_bytes": 429
|
||||
}, {
|
||||
"kind": 38385,
|
||||
"count": 2,
|
||||
"total_bytes": 2692,
|
||||
"max_bytes": 1478
|
||||
}, {
|
||||
"kind": 30443,
|
||||
"count": 2,
|
||||
"total_bytes": 2369,
|
||||
"max_bytes": 1219
|
||||
}, {
|
||||
"kind": 22747,
|
||||
"count": 2,
|
||||
"total_bytes": 2064,
|
||||
"max_bytes": 1288
|
||||
}, {
|
||||
"kind": 4245,
|
||||
"count": 2,
|
||||
"total_bytes": 888,
|
||||
"max_bytes": 444
|
||||
}, {
|
||||
"kind": 1111,
|
||||
"count": 2,
|
||||
"total_bytes": 1936,
|
||||
"max_bytes": 981
|
||||
}, {
|
||||
"kind": 38383,
|
||||
"count": 2,
|
||||
"total_bytes": 1439,
|
||||
"max_bytes": 720
|
||||
}, {
|
||||
"kind": 4243,
|
||||
"count": 2,
|
||||
"total_bytes": 1128,
|
||||
"max_bytes": 564
|
||||
}, {
|
||||
"kind": 38225,
|
||||
"count": 1,
|
||||
"total_bytes": 978,
|
||||
"max_bytes": 978
|
||||
}, {
|
||||
"kind": 30618,
|
||||
"count": 1,
|
||||
"total_bytes": 733,
|
||||
"max_bytes": 733
|
||||
}, {
|
||||
"kind": 31510,
|
||||
"count": 1,
|
||||
"total_bytes": 981,
|
||||
"max_bytes": 981
|
||||
}, {
|
||||
"kind": 30617,
|
||||
"count": 1,
|
||||
"total_bytes": 1089,
|
||||
"max_bytes": 1089
|
||||
}, {
|
||||
"kind": 1077,
|
||||
"count": 1,
|
||||
"total_bytes": 607,
|
||||
"max_bytes": 607
|
||||
}, {
|
||||
"kind": 20201,
|
||||
"count": 1,
|
||||
"total_bytes": 491,
|
||||
"max_bytes": 491
|
||||
}, {
|
||||
"kind": 20200,
|
||||
"count": 1,
|
||||
"total_bytes": 491,
|
||||
"max_bytes": 491
|
||||
}, {
|
||||
"kind": 1078,
|
||||
"count": 1,
|
||||
"total_bytes": 14173,
|
||||
"max_bytes": 14173
|
||||
}, {
|
||||
"kind": 6300,
|
||||
"count": 1,
|
||||
"total_bytes": 3698,
|
||||
"max_bytes": 3698
|
||||
}, {
|
||||
"kind": 11316,
|
||||
"count": 1,
|
||||
"total_bytes": 791,
|
||||
"max_bytes": 791
|
||||
}, {
|
||||
"kind": 11317,
|
||||
"count": 1,
|
||||
"total_bytes": 2873,
|
||||
"max_bytes": 2873
|
||||
}, {
|
||||
"kind": 17,
|
||||
"count": 1,
|
||||
"total_bytes": 610,
|
||||
"max_bytes": 610
|
||||
}, {
|
||||
"kind": 23059,
|
||||
"count": 1,
|
||||
"total_bytes": 429,
|
||||
"max_bytes": 429
|
||||
}, {
|
||||
"kind": 22806,
|
||||
"count": 1,
|
||||
"total_bytes": 1520,
|
||||
"max_bytes": 1520
|
||||
}, {
|
||||
"kind": 22120,
|
||||
"count": 1,
|
||||
"total_bytes": 1127,
|
||||
"max_bytes": 1127
|
||||
}, {
|
||||
"kind": 13196,
|
||||
"count": 1,
|
||||
"total_bytes": 656,
|
||||
"max_bytes": 656
|
||||
}, {
|
||||
"kind": 24913,
|
||||
"count": 1,
|
||||
"total_bytes": 431,
|
||||
"max_bytes": 431
|
||||
}, {
|
||||
"kind": 12222,
|
||||
"count": 1,
|
||||
"total_bytes": 579,
|
||||
"max_bytes": 579
|
||||
}, {
|
||||
"kind": 1040,
|
||||
"count": 1,
|
||||
"total_bytes": 1048,
|
||||
"max_bytes": 1048
|
||||
}, {
|
||||
"kind": 22119,
|
||||
"count": 1,
|
||||
"total_bytes": 845,
|
||||
"max_bytes": 845
|
||||
}, {
|
||||
"kind": 10312,
|
||||
"count": 1,
|
||||
"total_bytes": 472,
|
||||
"max_bytes": 472
|
||||
}, {
|
||||
"kind": 3079,
|
||||
"count": 1,
|
||||
"total_bytes": 909,
|
||||
"max_bytes": 909
|
||||
}, {
|
||||
"kind": 30000,
|
||||
"count": 1,
|
||||
"total_bytes": 594,
|
||||
"max_bytes": 594
|
||||
}]
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,704 @@
|
||||
{
|
||||
"duration_seconds": 32,
|
||||
"total_events": 1485,
|
||||
"total_bytes": 1812166,
|
||||
"unique_pubkeys": 511,
|
||||
"relay_count": 15,
|
||||
"relays": [{
|
||||
"url": "wss://laantungir.net",
|
||||
"events": 0,
|
||||
"eose": 0,
|
||||
"closed": 0,
|
||||
"notice": 0,
|
||||
"errors": 0,
|
||||
"disconnects": 0,
|
||||
"connected": false
|
||||
}, {
|
||||
"url": "wss://nos.lol",
|
||||
"events": 247,
|
||||
"eose": 0,
|
||||
"closed": 0,
|
||||
"notice": 0,
|
||||
"errors": 0,
|
||||
"disconnects": 0,
|
||||
"connected": true
|
||||
}, {
|
||||
"url": "wss://nostr-pub.wellorder.net",
|
||||
"events": 37,
|
||||
"eose": 0,
|
||||
"closed": 0,
|
||||
"notice": 0,
|
||||
"errors": 0,
|
||||
"disconnects": 0,
|
||||
"connected": true
|
||||
}, {
|
||||
"url": "wss://nostr.mom",
|
||||
"events": 38,
|
||||
"eose": 0,
|
||||
"closed": 0,
|
||||
"notice": 0,
|
||||
"errors": 0,
|
||||
"disconnects": 0,
|
||||
"connected": true
|
||||
}, {
|
||||
"url": "wss://nostr.oxtr.dev",
|
||||
"events": 36,
|
||||
"eose": 0,
|
||||
"closed": 0,
|
||||
"notice": 0,
|
||||
"errors": 0,
|
||||
"disconnects": 0,
|
||||
"connected": true
|
||||
}, {
|
||||
"url": "wss://offchain.pub",
|
||||
"events": 113,
|
||||
"eose": 0,
|
||||
"closed": 0,
|
||||
"notice": 0,
|
||||
"errors": 0,
|
||||
"disconnects": 0,
|
||||
"connected": true
|
||||
}, {
|
||||
"url": "wss://premium.primal.net",
|
||||
"events": 1,
|
||||
"eose": 0,
|
||||
"closed": 0,
|
||||
"notice": 0,
|
||||
"errors": 0,
|
||||
"disconnects": 0,
|
||||
"connected": true
|
||||
}, {
|
||||
"url": "wss://relay.damus.io",
|
||||
"events": 194,
|
||||
"eose": 0,
|
||||
"closed": 0,
|
||||
"notice": 0,
|
||||
"errors": 0,
|
||||
"disconnects": 0,
|
||||
"connected": true
|
||||
}, {
|
||||
"url": "wss://relay.ditto.pub",
|
||||
"events": 277,
|
||||
"eose": 0,
|
||||
"closed": 0,
|
||||
"notice": 0,
|
||||
"errors": 0,
|
||||
"disconnects": 1,
|
||||
"connected": true
|
||||
}, {
|
||||
"url": "wss://relay.divine.video",
|
||||
"events": 2,
|
||||
"eose": 0,
|
||||
"closed": 0,
|
||||
"notice": 0,
|
||||
"errors": 0,
|
||||
"disconnects": 0,
|
||||
"connected": true
|
||||
}, {
|
||||
"url": "wss://relay.momostr.pink",
|
||||
"events": 27,
|
||||
"eose": 0,
|
||||
"closed": 0,
|
||||
"notice": 0,
|
||||
"errors": 0,
|
||||
"disconnects": 0,
|
||||
"connected": true
|
||||
}, {
|
||||
"url": "wss://relay.mostr.pub",
|
||||
"events": 148,
|
||||
"eose": 0,
|
||||
"closed": 0,
|
||||
"notice": 0,
|
||||
"errors": 0,
|
||||
"disconnects": 0,
|
||||
"connected": true
|
||||
}, {
|
||||
"url": "wss://relay.nostrplebs.com",
|
||||
"events": 0,
|
||||
"eose": 0,
|
||||
"closed": 0,
|
||||
"notice": 0,
|
||||
"errors": 0,
|
||||
"disconnects": 0,
|
||||
"connected": true
|
||||
}, {
|
||||
"url": "wss://relay.primal.net",
|
||||
"events": 360,
|
||||
"eose": 0,
|
||||
"closed": 0,
|
||||
"notice": 0,
|
||||
"errors": 0,
|
||||
"disconnects": 0,
|
||||
"connected": true
|
||||
}, {
|
||||
"url": "wss://theforest.nostr1.com",
|
||||
"events": 5,
|
||||
"eose": 0,
|
||||
"closed": 0,
|
||||
"notice": 0,
|
||||
"errors": 0,
|
||||
"disconnects": 0,
|
||||
"connected": true
|
||||
}],
|
||||
"kinds": [{
|
||||
"kind": 21059,
|
||||
"count": 184,
|
||||
"total_bytes": 623532,
|
||||
"max_bytes": 5314
|
||||
}, {
|
||||
"kind": 22591,
|
||||
"count": 139,
|
||||
"total_bytes": 107560,
|
||||
"max_bytes": 1223
|
||||
}, {
|
||||
"kind": 30382,
|
||||
"count": 119,
|
||||
"total_bytes": 53663,
|
||||
"max_bytes": 458
|
||||
}, {
|
||||
"kind": 30383,
|
||||
"count": 119,
|
||||
"total_bytes": 53605,
|
||||
"max_bytes": 536
|
||||
}, {
|
||||
"kind": 5,
|
||||
"count": 91,
|
||||
"total_bytes": 39950,
|
||||
"max_bytes": 624
|
||||
}, {
|
||||
"kind": 30078,
|
||||
"count": 54,
|
||||
"total_bytes": 179695,
|
||||
"max_bytes": 14343
|
||||
}, {
|
||||
"kind": 20001,
|
||||
"count": 49,
|
||||
"total_bytes": 35635,
|
||||
"max_bytes": 1871
|
||||
}, {
|
||||
"kind": 0,
|
||||
"count": 48,
|
||||
"total_bytes": 39906,
|
||||
"max_bytes": 1468
|
||||
}, {
|
||||
"kind": 22668,
|
||||
"count": 48,
|
||||
"total_bytes": 20592,
|
||||
"max_bytes": 429
|
||||
}, {
|
||||
"kind": 1,
|
||||
"count": 45,
|
||||
"total_bytes": 38547,
|
||||
"max_bytes": 2413
|
||||
}, {
|
||||
"kind": 22734,
|
||||
"count": 26,
|
||||
"total_bytes": 11102,
|
||||
"max_bytes": 427
|
||||
}, {
|
||||
"kind": 4515,
|
||||
"count": 26,
|
||||
"total_bytes": 38218,
|
||||
"max_bytes": 2956
|
||||
}, {
|
||||
"kind": 10002,
|
||||
"count": 25,
|
||||
"total_bytes": 11707,
|
||||
"max_bytes": 565
|
||||
}, {
|
||||
"kind": 22850,
|
||||
"count": 24,
|
||||
"total_bytes": 10320,
|
||||
"max_bytes": 430
|
||||
}, {
|
||||
"kind": 7,
|
||||
"count": 24,
|
||||
"total_bytes": 13528,
|
||||
"max_bytes": 780
|
||||
}, {
|
||||
"kind": 22551,
|
||||
"count": 24,
|
||||
"total_bytes": 10320,
|
||||
"max_bytes": 430
|
||||
}, {
|
||||
"kind": 31991,
|
||||
"count": 20,
|
||||
"total_bytes": 9220,
|
||||
"max_bytes": 461
|
||||
}, {
|
||||
"kind": 38501,
|
||||
"count": 18,
|
||||
"total_bytes": 13341,
|
||||
"max_bytes": 744
|
||||
}, {
|
||||
"kind": 22663,
|
||||
"count": 17,
|
||||
"total_bytes": 7276,
|
||||
"max_bytes": 428
|
||||
}, {
|
||||
"kind": 25555,
|
||||
"count": 15,
|
||||
"total_bytes": 90493,
|
||||
"max_bytes": 16887
|
||||
}, {
|
||||
"kind": 22912,
|
||||
"count": 13,
|
||||
"total_bytes": 5564,
|
||||
"max_bytes": 428
|
||||
}, {
|
||||
"kind": 1059,
|
||||
"count": 13,
|
||||
"total_bytes": 23775,
|
||||
"max_bytes": 1883
|
||||
}, {
|
||||
"kind": 22832,
|
||||
"count": 12,
|
||||
"total_bytes": 5233,
|
||||
"max_bytes": 446
|
||||
}, {
|
||||
"kind": 22690,
|
||||
"count": 11,
|
||||
"total_bytes": 4730,
|
||||
"max_bytes": 430
|
||||
}, {
|
||||
"kind": 22545,
|
||||
"count": 11,
|
||||
"total_bytes": 4697,
|
||||
"max_bytes": 427
|
||||
}, {
|
||||
"kind": 25050,
|
||||
"count": 10,
|
||||
"total_bytes": 4394,
|
||||
"max_bytes": 465
|
||||
}, {
|
||||
"kind": 37195,
|
||||
"count": 10,
|
||||
"total_bytes": 7494,
|
||||
"max_bytes": 771
|
||||
}, {
|
||||
"kind": 22601,
|
||||
"count": 10,
|
||||
"total_bytes": 4280,
|
||||
"max_bytes": 428
|
||||
}, {
|
||||
"kind": 22795,
|
||||
"count": 10,
|
||||
"total_bytes": 11639,
|
||||
"max_bytes": 1487
|
||||
}, {
|
||||
"kind": 22891,
|
||||
"count": 9,
|
||||
"total_bytes": 13331,
|
||||
"max_bytes": 1490
|
||||
}, {
|
||||
"kind": 22655,
|
||||
"count": 9,
|
||||
"total_bytes": 3852,
|
||||
"max_bytes": 428
|
||||
}, {
|
||||
"kind": 22911,
|
||||
"count": 9,
|
||||
"total_bytes": 13328,
|
||||
"max_bytes": 1487
|
||||
}, {
|
||||
"kind": 24133,
|
||||
"count": 9,
|
||||
"total_bytes": 8250,
|
||||
"max_bytes": 1534
|
||||
}, {
|
||||
"kind": 13194,
|
||||
"count": 8,
|
||||
"total_bytes": 4112,
|
||||
"max_bytes": 514
|
||||
}, {
|
||||
"kind": 22647,
|
||||
"count": 8,
|
||||
"total_bytes": 3416,
|
||||
"max_bytes": 427
|
||||
}, {
|
||||
"kind": 22695,
|
||||
"count": 7,
|
||||
"total_bytes": 10339,
|
||||
"max_bytes": 1481
|
||||
}, {
|
||||
"kind": 22653,
|
||||
"count": 7,
|
||||
"total_bytes": 10368,
|
||||
"max_bytes": 1487
|
||||
}, {
|
||||
"kind": 22455,
|
||||
"count": 7,
|
||||
"total_bytes": 10339,
|
||||
"max_bytes": 1485
|
||||
}, {
|
||||
"kind": 22543,
|
||||
"count": 7,
|
||||
"total_bytes": 10354,
|
||||
"max_bytes": 1487
|
||||
}, {
|
||||
"kind": 30315,
|
||||
"count": 7,
|
||||
"total_bytes": 2714,
|
||||
"max_bytes": 398
|
||||
}, {
|
||||
"kind": 22676,
|
||||
"count": 6,
|
||||
"total_bytes": 2562,
|
||||
"max_bytes": 427
|
||||
}, {
|
||||
"kind": 22575,
|
||||
"count": 6,
|
||||
"total_bytes": 2550,
|
||||
"max_bytes": 425
|
||||
}, {
|
||||
"kind": 22689,
|
||||
"count": 6,
|
||||
"total_bytes": 8851,
|
||||
"max_bytes": 1484
|
||||
}, {
|
||||
"kind": 22913,
|
||||
"count": 6,
|
||||
"total_bytes": 2586,
|
||||
"max_bytes": 431
|
||||
}, {
|
||||
"kind": 22774,
|
||||
"count": 6,
|
||||
"total_bytes": 2568,
|
||||
"max_bytes": 428
|
||||
}, {
|
||||
"kind": 24242,
|
||||
"count": 6,
|
||||
"total_bytes": 3474,
|
||||
"max_bytes": 579
|
||||
}, {
|
||||
"kind": 22808,
|
||||
"count": 6,
|
||||
"total_bytes": 2574,
|
||||
"max_bytes": 429
|
||||
}, {
|
||||
"kind": 22842,
|
||||
"count": 6,
|
||||
"total_bytes": 8891,
|
||||
"max_bytes": 1488
|
||||
}, {
|
||||
"kind": 22603,
|
||||
"count": 5,
|
||||
"total_bytes": 2130,
|
||||
"max_bytes": 426
|
||||
}, {
|
||||
"kind": 6,
|
||||
"count": 5,
|
||||
"total_bytes": 10814,
|
||||
"max_bytes": 7298
|
||||
}, {
|
||||
"kind": 31990,
|
||||
"count": 5,
|
||||
"total_bytes": 4305,
|
||||
"max_bytes": 1321
|
||||
}, {
|
||||
"kind": 22384,
|
||||
"count": 5,
|
||||
"total_bytes": 2130,
|
||||
"max_bytes": 426
|
||||
}, {
|
||||
"kind": 22699,
|
||||
"count": 5,
|
||||
"total_bytes": 2140,
|
||||
"max_bytes": 428
|
||||
}, {
|
||||
"kind": 22613,
|
||||
"count": 5,
|
||||
"total_bytes": 3443,
|
||||
"max_bytes": 691
|
||||
}, {
|
||||
"kind": 38502,
|
||||
"count": 5,
|
||||
"total_bytes": 1925,
|
||||
"max_bytes": 385
|
||||
}, {
|
||||
"kind": 23003,
|
||||
"count": 5,
|
||||
"total_bytes": 2140,
|
||||
"max_bytes": 428
|
||||
}, {
|
||||
"kind": 22743,
|
||||
"count": 5,
|
||||
"total_bytes": 2140,
|
||||
"max_bytes": 428
|
||||
}, {
|
||||
"kind": 29333,
|
||||
"count": 5,
|
||||
"total_bytes": 2460,
|
||||
"max_bytes": 492
|
||||
}, {
|
||||
"kind": 20004,
|
||||
"count": 4,
|
||||
"total_bytes": 1800,
|
||||
"max_bytes": 549
|
||||
}, {
|
||||
"kind": 4,
|
||||
"count": 4,
|
||||
"total_bytes": 3072,
|
||||
"max_bytes": 826
|
||||
}, {
|
||||
"kind": 20387,
|
||||
"count": 4,
|
||||
"total_bytes": 2056,
|
||||
"max_bytes": 514
|
||||
}, {
|
||||
"kind": 22816,
|
||||
"count": 4,
|
||||
"total_bytes": 1716,
|
||||
"max_bytes": 429
|
||||
}, {
|
||||
"kind": 20000,
|
||||
"count": 4,
|
||||
"total_bytes": 1872,
|
||||
"max_bytes": 628
|
||||
}, {
|
||||
"kind": 22934,
|
||||
"count": 3,
|
||||
"total_bytes": 5535,
|
||||
"max_bytes": 1846
|
||||
}, {
|
||||
"kind": 1985,
|
||||
"count": 2,
|
||||
"total_bytes": 948,
|
||||
"max_bytes": 474
|
||||
}, {
|
||||
"kind": 31234,
|
||||
"count": 2,
|
||||
"total_bytes": 89092,
|
||||
"max_bytes": 44546
|
||||
}, {
|
||||
"kind": 10777,
|
||||
"count": 2,
|
||||
"total_bytes": 976,
|
||||
"max_bytes": 488
|
||||
}, {
|
||||
"kind": 4004,
|
||||
"count": 2,
|
||||
"total_bytes": 2338,
|
||||
"max_bytes": 1169
|
||||
}, {
|
||||
"kind": 9735,
|
||||
"count": 2,
|
||||
"total_bytes": 3926,
|
||||
"max_bytes": 2135
|
||||
}, {
|
||||
"kind": 1000,
|
||||
"count": 2,
|
||||
"total_bytes": 3415,
|
||||
"max_bytes": 1712
|
||||
}, {
|
||||
"kind": 25195,
|
||||
"count": 2,
|
||||
"total_bytes": 1356,
|
||||
"max_bytes": 678
|
||||
}, {
|
||||
"kind": 30311,
|
||||
"count": 2,
|
||||
"total_bytes": 2210,
|
||||
"max_bytes": 1198
|
||||
}, {
|
||||
"kind": 25196,
|
||||
"count": 2,
|
||||
"total_bytes": 3576,
|
||||
"max_bytes": 2214
|
||||
}, {
|
||||
"kind": 1040,
|
||||
"count": 2,
|
||||
"total_bytes": 1920,
|
||||
"max_bytes": 960
|
||||
}, {
|
||||
"kind": 38383,
|
||||
"count": 2,
|
||||
"total_bytes": 1532,
|
||||
"max_bytes": 815
|
||||
}, {
|
||||
"kind": 30515,
|
||||
"count": 2,
|
||||
"total_bytes": 5152,
|
||||
"max_bytes": 2576
|
||||
}, {
|
||||
"kind": 30091,
|
||||
"count": 2,
|
||||
"total_bytes": 1221,
|
||||
"max_bytes": 611
|
||||
}, {
|
||||
"kind": 30088,
|
||||
"count": 2,
|
||||
"total_bytes": 3717,
|
||||
"max_bytes": 1859
|
||||
}, {
|
||||
"kind": 21617,
|
||||
"count": 1,
|
||||
"total_bytes": 494,
|
||||
"max_bytes": 494
|
||||
}, {
|
||||
"kind": 30380,
|
||||
"count": 1,
|
||||
"total_bytes": 454,
|
||||
"max_bytes": 454
|
||||
}, {
|
||||
"kind": 22611,
|
||||
"count": 1,
|
||||
"total_bytes": 426,
|
||||
"max_bytes": 426
|
||||
}, {
|
||||
"kind": 30079,
|
||||
"count": 1,
|
||||
"total_bytes": 875,
|
||||
"max_bytes": 875
|
||||
}, {
|
||||
"kind": 22767,
|
||||
"count": 1,
|
||||
"total_bytes": 429,
|
||||
"max_bytes": 429
|
||||
}, {
|
||||
"kind": 38500,
|
||||
"count": 1,
|
||||
"total_bytes": 711,
|
||||
"max_bytes": 711
|
||||
}, {
|
||||
"kind": 30312,
|
||||
"count": 1,
|
||||
"total_bytes": 461,
|
||||
"max_bytes": 461
|
||||
}, {
|
||||
"kind": 7368,
|
||||
"count": 1,
|
||||
"total_bytes": 1039,
|
||||
"max_bytes": 1039
|
||||
}, {
|
||||
"kind": 22967,
|
||||
"count": 1,
|
||||
"total_bytes": 431,
|
||||
"max_bytes": 431
|
||||
}, {
|
||||
"kind": 39101,
|
||||
"count": 1,
|
||||
"total_bytes": 533,
|
||||
"max_bytes": 533
|
||||
}, {
|
||||
"kind": 445,
|
||||
"count": 1,
|
||||
"total_bytes": 4130,
|
||||
"max_bytes": 4130
|
||||
}, {
|
||||
"kind": 10000,
|
||||
"count": 1,
|
||||
"total_bytes": 1722,
|
||||
"max_bytes": 1722
|
||||
}, {
|
||||
"kind": 30617,
|
||||
"count": 1,
|
||||
"total_bytes": 1089,
|
||||
"max_bytes": 1089
|
||||
}, {
|
||||
"kind": 22526,
|
||||
"count": 1,
|
||||
"total_bytes": 430,
|
||||
"max_bytes": 430
|
||||
}, {
|
||||
"kind": 20787,
|
||||
"count": 1,
|
||||
"total_bytes": 926,
|
||||
"max_bytes": 926
|
||||
}, {
|
||||
"kind": 443,
|
||||
"count": 1,
|
||||
"total_bytes": 800,
|
||||
"max_bytes": 800
|
||||
}, {
|
||||
"kind": 16,
|
||||
"count": 1,
|
||||
"total_bytes": 780,
|
||||
"max_bytes": 780
|
||||
}, {
|
||||
"kind": 10011,
|
||||
"count": 1,
|
||||
"total_bytes": 397,
|
||||
"max_bytes": 397
|
||||
}, {
|
||||
"kind": 22679,
|
||||
"count": 1,
|
||||
"total_bytes": 693,
|
||||
"max_bytes": 693
|
||||
}, {
|
||||
"kind": 23042,
|
||||
"count": 1,
|
||||
"total_bytes": 429,
|
||||
"max_bytes": 429
|
||||
}, {
|
||||
"kind": 22514,
|
||||
"count": 1,
|
||||
"total_bytes": 428,
|
||||
"max_bytes": 428
|
||||
}, {
|
||||
"kind": 30023,
|
||||
"count": 1,
|
||||
"total_bytes": 8164,
|
||||
"max_bytes": 8164
|
||||
}, {
|
||||
"kind": 5300,
|
||||
"count": 1,
|
||||
"total_bytes": 630,
|
||||
"max_bytes": 630
|
||||
}, {
|
||||
"kind": 22605,
|
||||
"count": 1,
|
||||
"total_bytes": 692,
|
||||
"max_bytes": 692
|
||||
}, {
|
||||
"kind": 34237,
|
||||
"count": 1,
|
||||
"total_bytes": 418,
|
||||
"max_bytes": 418
|
||||
}, {
|
||||
"kind": 30618,
|
||||
"count": 1,
|
||||
"total_bytes": 733,
|
||||
"max_bytes": 733
|
||||
}, {
|
||||
"kind": 38421,
|
||||
"count": 1,
|
||||
"total_bytes": 1069,
|
||||
"max_bytes": 1069
|
||||
}, {
|
||||
"kind": 10100,
|
||||
"count": 1,
|
||||
"total_bytes": 1036,
|
||||
"max_bytes": 1036
|
||||
}, {
|
||||
"kind": 30080,
|
||||
"count": 1,
|
||||
"total_bytes": 925,
|
||||
"max_bytes": 925
|
||||
}, {
|
||||
"kind": 38385,
|
||||
"count": 1,
|
||||
"total_bytes": 1214,
|
||||
"max_bytes": 1214
|
||||
}, {
|
||||
"kind": 38225,
|
||||
"count": 1,
|
||||
"total_bytes": 1012,
|
||||
"max_bytes": 1012
|
||||
}, {
|
||||
"kind": 11998,
|
||||
"count": 1,
|
||||
"total_bytes": 465,
|
||||
"max_bytes": 465
|
||||
}, {
|
||||
"kind": 22236,
|
||||
"count": 1,
|
||||
"total_bytes": 747,
|
||||
"max_bytes": 747
|
||||
}, {
|
||||
"kind": 22823,
|
||||
"count": 1,
|
||||
"total_bytes": 1852,
|
||||
"max_bytes": 1852
|
||||
}]
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,998 @@
|
||||
{
|
||||
"duration_seconds": 503,
|
||||
"total_events": 7884,
|
||||
"total_bytes": 12205231,
|
||||
"unique_pubkeys": 2301,
|
||||
"relay_count": 1,
|
||||
"relays": [{
|
||||
"url": "wss://relay.primal.net",
|
||||
"events": 7884,
|
||||
"eose": 0,
|
||||
"closed": 0,
|
||||
"notice": 0,
|
||||
"errors": 0,
|
||||
"disconnects": 10,
|
||||
"connected": true
|
||||
}],
|
||||
"kinds": [{
|
||||
"kind": 1059,
|
||||
"count": 871,
|
||||
"total_bytes": 1657832,
|
||||
"max_bytes": 55121
|
||||
}, {
|
||||
"kind": 21059,
|
||||
"count": 740,
|
||||
"total_bytes": 2308644,
|
||||
"max_bytes": 22354
|
||||
}, {
|
||||
"kind": 30078,
|
||||
"count": 622,
|
||||
"total_bytes": 2651879,
|
||||
"max_bytes": 55090
|
||||
}, {
|
||||
"kind": 30383,
|
||||
"count": 520,
|
||||
"total_bytes": 278610,
|
||||
"max_bytes": 548
|
||||
}, {
|
||||
"kind": 20001,
|
||||
"count": 386,
|
||||
"total_bytes": 403111,
|
||||
"max_bytes": 2026
|
||||
}, {
|
||||
"kind": 22734,
|
||||
"count": 357,
|
||||
"total_bytes": 152451,
|
||||
"max_bytes": 428
|
||||
}, {
|
||||
"kind": 1,
|
||||
"count": 303,
|
||||
"total_bytes": 303990,
|
||||
"max_bytes": 4648
|
||||
}, {
|
||||
"kind": 30382,
|
||||
"count": 288,
|
||||
"total_bytes": 137207,
|
||||
"max_bytes": 484
|
||||
}, {
|
||||
"kind": 0,
|
||||
"count": 189,
|
||||
"total_bytes": 140594,
|
||||
"max_bytes": 2012
|
||||
}, {
|
||||
"kind": 29333,
|
||||
"count": 165,
|
||||
"total_bytes": 81180,
|
||||
"max_bytes": 492
|
||||
}, {
|
||||
"kind": 10002,
|
||||
"count": 158,
|
||||
"total_bytes": 571188,
|
||||
"max_bytes": 42385
|
||||
}, {
|
||||
"kind": 22236,
|
||||
"count": 158,
|
||||
"total_bytes": 120802,
|
||||
"max_bytes": 801
|
||||
}, {
|
||||
"kind": 5,
|
||||
"count": 154,
|
||||
"total_bytes": 73847,
|
||||
"max_bytes": 664
|
||||
}, {
|
||||
"kind": 4515,
|
||||
"count": 154,
|
||||
"total_bytes": 463562,
|
||||
"max_bytes": 38797
|
||||
}, {
|
||||
"kind": 22743,
|
||||
"count": 134,
|
||||
"total_bytes": 57352,
|
||||
"max_bytes": 428
|
||||
}, {
|
||||
"kind": 7,
|
||||
"count": 113,
|
||||
"total_bytes": 62452,
|
||||
"max_bytes": 727
|
||||
}, {
|
||||
"kind": 24133,
|
||||
"count": 102,
|
||||
"total_bytes": 132440,
|
||||
"max_bytes": 7334
|
||||
}, {
|
||||
"kind": 22684,
|
||||
"count": 99,
|
||||
"total_bytes": 42669,
|
||||
"max_bytes": 431
|
||||
}, {
|
||||
"kind": 22850,
|
||||
"count": 94,
|
||||
"total_bytes": 40420,
|
||||
"max_bytes": 430
|
||||
}, {
|
||||
"kind": 22838,
|
||||
"count": 88,
|
||||
"total_bytes": 37752,
|
||||
"max_bytes": 429
|
||||
}, {
|
||||
"kind": 22774,
|
||||
"count": 84,
|
||||
"total_bytes": 35952,
|
||||
"max_bytes": 428
|
||||
}, {
|
||||
"kind": 23003,
|
||||
"count": 84,
|
||||
"total_bytes": 35952,
|
||||
"max_bytes": 428
|
||||
}, {
|
||||
"kind": 22876,
|
||||
"count": 83,
|
||||
"total_bytes": 35358,
|
||||
"max_bytes": 426
|
||||
}, {
|
||||
"kind": 22611,
|
||||
"count": 75,
|
||||
"total_bytes": 32175,
|
||||
"max_bytes": 429
|
||||
}, {
|
||||
"kind": 25555,
|
||||
"count": 69,
|
||||
"total_bytes": 281319,
|
||||
"max_bytes": 16987
|
||||
}, {
|
||||
"kind": 4,
|
||||
"count": 66,
|
||||
"total_bytes": 72028,
|
||||
"max_bytes": 17018
|
||||
}, {
|
||||
"kind": 22613,
|
||||
"count": 63,
|
||||
"total_bytes": 43489,
|
||||
"max_bytes": 692
|
||||
}, {
|
||||
"kind": 25050,
|
||||
"count": 61,
|
||||
"total_bytes": 24461,
|
||||
"max_bytes": 401
|
||||
}, {
|
||||
"kind": 11998,
|
||||
"count": 61,
|
||||
"total_bytes": 28269,
|
||||
"max_bytes": 465
|
||||
}, {
|
||||
"kind": 443,
|
||||
"count": 49,
|
||||
"total_bytes": 68056,
|
||||
"max_bytes": 22480
|
||||
}, {
|
||||
"kind": 30301,
|
||||
"count": 47,
|
||||
"total_bytes": 53284,
|
||||
"max_bytes": 1912
|
||||
}, {
|
||||
"kind": 3927,
|
||||
"count": 47,
|
||||
"total_bytes": 25051,
|
||||
"max_bytes": 533
|
||||
}, {
|
||||
"kind": 20387,
|
||||
"count": 44,
|
||||
"total_bytes": 22616,
|
||||
"max_bytes": 514
|
||||
}, {
|
||||
"kind": 22761,
|
||||
"count": 44,
|
||||
"total_bytes": 18832,
|
||||
"max_bytes": 428
|
||||
}, {
|
||||
"kind": 13194,
|
||||
"count": 43,
|
||||
"total_bytes": 22043,
|
||||
"max_bytes": 514
|
||||
}, {
|
||||
"kind": 20004,
|
||||
"count": 42,
|
||||
"total_bytes": 22266,
|
||||
"max_bytes": 549
|
||||
}, {
|
||||
"kind": 5300,
|
||||
"count": 42,
|
||||
"total_bytes": 25437,
|
||||
"max_bytes": 637
|
||||
}, {
|
||||
"kind": 22546,
|
||||
"count": 39,
|
||||
"total_bytes": 16614,
|
||||
"max_bytes": 426
|
||||
}, {
|
||||
"kind": 22714,
|
||||
"count": 37,
|
||||
"total_bytes": 15836,
|
||||
"max_bytes": 428
|
||||
}, {
|
||||
"kind": 30166,
|
||||
"count": 35,
|
||||
"total_bytes": 17904,
|
||||
"max_bytes": 589
|
||||
}, {
|
||||
"kind": 9735,
|
||||
"count": 35,
|
||||
"total_bytes": 70344,
|
||||
"max_bytes": 3538
|
||||
}, {
|
||||
"kind": 23334,
|
||||
"count": 35,
|
||||
"total_bytes": 15084,
|
||||
"max_bytes": 432
|
||||
}, {
|
||||
"kind": 1985,
|
||||
"count": 34,
|
||||
"total_bytes": 16232,
|
||||
"max_bytes": 483
|
||||
}, {
|
||||
"kind": 22816,
|
||||
"count": 33,
|
||||
"total_bytes": 14157,
|
||||
"max_bytes": 429
|
||||
}, {
|
||||
"kind": 21050,
|
||||
"count": 33,
|
||||
"total_bytes": 30862,
|
||||
"max_bytes": 1874
|
||||
}, {
|
||||
"kind": 30315,
|
||||
"count": 32,
|
||||
"total_bytes": 21166,
|
||||
"max_bytes": 925
|
||||
}, {
|
||||
"kind": 445,
|
||||
"count": 32,
|
||||
"total_bytes": 120956,
|
||||
"max_bytes": 9346
|
||||
}, {
|
||||
"kind": 22698,
|
||||
"count": 32,
|
||||
"total_bytes": 13664,
|
||||
"max_bytes": 427
|
||||
}, {
|
||||
"kind": 4004,
|
||||
"count": 32,
|
||||
"total_bytes": 37408,
|
||||
"max_bytes": 1169
|
||||
}, {
|
||||
"kind": 38501,
|
||||
"count": 31,
|
||||
"total_bytes": 23034,
|
||||
"max_bytes": 744
|
||||
}, {
|
||||
"kind": 31990,
|
||||
"count": 25,
|
||||
"total_bytes": 9675,
|
||||
"max_bytes": 387
|
||||
}, {
|
||||
"kind": 10100,
|
||||
"count": 24,
|
||||
"total_bytes": 27687,
|
||||
"max_bytes": 1589
|
||||
}, {
|
||||
"kind": 20333,
|
||||
"count": 24,
|
||||
"total_bytes": 19120,
|
||||
"max_bytes": 798
|
||||
}, {
|
||||
"kind": 3,
|
||||
"count": 23,
|
||||
"total_bytes": 328284,
|
||||
"max_bytes": 56750
|
||||
}, {
|
||||
"kind": 24913,
|
||||
"count": 22,
|
||||
"total_bytes": 9700,
|
||||
"max_bytes": 493
|
||||
}, {
|
||||
"kind": 30311,
|
||||
"count": 21,
|
||||
"total_bytes": 22061,
|
||||
"max_bytes": 1197
|
||||
}, {
|
||||
"kind": 6,
|
||||
"count": 21,
|
||||
"total_bytes": 49793,
|
||||
"max_bytes": 12925
|
||||
}, {
|
||||
"kind": 10050,
|
||||
"count": 19,
|
||||
"total_bytes": 8172,
|
||||
"max_bytes": 450
|
||||
}, {
|
||||
"kind": 22712,
|
||||
"count": 18,
|
||||
"total_bytes": 7704,
|
||||
"max_bytes": 428
|
||||
}, {
|
||||
"kind": 22808,
|
||||
"count": 17,
|
||||
"total_bytes": 7293,
|
||||
"max_bytes": 429
|
||||
}, {
|
||||
"kind": 10000,
|
||||
"count": 16,
|
||||
"total_bytes": 26659,
|
||||
"max_bytes": 12630
|
||||
}, {
|
||||
"kind": 4244,
|
||||
"count": 15,
|
||||
"total_bytes": 8460,
|
||||
"max_bytes": 564
|
||||
}, {
|
||||
"kind": 23025,
|
||||
"count": 15,
|
||||
"total_bytes": 6465,
|
||||
"max_bytes": 431
|
||||
}, {
|
||||
"kind": 31234,
|
||||
"count": 14,
|
||||
"total_bytes": 24051,
|
||||
"max_bytes": 2268
|
||||
}, {
|
||||
"kind": 38503,
|
||||
"count": 13,
|
||||
"total_bytes": 7174,
|
||||
"max_bytes": 552
|
||||
}, {
|
||||
"kind": 22630,
|
||||
"count": 12,
|
||||
"total_bytes": 11762,
|
||||
"max_bytes": 1654
|
||||
}, {
|
||||
"kind": 37195,
|
||||
"count": 12,
|
||||
"total_bytes": 8752,
|
||||
"max_bytes": 934
|
||||
}, {
|
||||
"kind": 6300,
|
||||
"count": 12,
|
||||
"total_bytes": 77247,
|
||||
"max_bytes": 17248
|
||||
}, {
|
||||
"kind": 10777,
|
||||
"count": 12,
|
||||
"total_bytes": 5861,
|
||||
"max_bytes": 489
|
||||
}, {
|
||||
"kind": 30091,
|
||||
"count": 11,
|
||||
"total_bytes": 6763,
|
||||
"max_bytes": 629
|
||||
}, {
|
||||
"kind": 20000,
|
||||
"count": 11,
|
||||
"total_bytes": 3806,
|
||||
"max_bytes": 346
|
||||
}, {
|
||||
"kind": 30515,
|
||||
"count": 11,
|
||||
"total_bytes": 58344,
|
||||
"max_bytes": 5304
|
||||
}, {
|
||||
"kind": 30088,
|
||||
"count": 11,
|
||||
"total_bytes": 20483,
|
||||
"max_bytes": 1871
|
||||
}, {
|
||||
"kind": 22361,
|
||||
"count": 10,
|
||||
"total_bytes": 4439,
|
||||
"max_bytes": 445
|
||||
}, {
|
||||
"kind": 30280,
|
||||
"count": 9,
|
||||
"total_bytes": 4617,
|
||||
"max_bytes": 513
|
||||
}, {
|
||||
"kind": 22902,
|
||||
"count": 9,
|
||||
"total_bytes": 3861,
|
||||
"max_bytes": 429
|
||||
}, {
|
||||
"kind": 22506,
|
||||
"count": 8,
|
||||
"total_bytes": 3416,
|
||||
"max_bytes": 427
|
||||
}, {
|
||||
"kind": 7368,
|
||||
"count": 8,
|
||||
"total_bytes": 8304,
|
||||
"max_bytes": 1040
|
||||
}, {
|
||||
"kind": 22645,
|
||||
"count": 8,
|
||||
"total_bytes": 3432,
|
||||
"max_bytes": 429
|
||||
}, {
|
||||
"kind": 38500,
|
||||
"count": 8,
|
||||
"total_bytes": 5696,
|
||||
"max_bytes": 713
|
||||
}, {
|
||||
"kind": 33334,
|
||||
"count": 8,
|
||||
"total_bytes": 6648,
|
||||
"max_bytes": 831
|
||||
}, {
|
||||
"kind": 30380,
|
||||
"count": 8,
|
||||
"total_bytes": 3632,
|
||||
"max_bytes": 454
|
||||
}, {
|
||||
"kind": 22688,
|
||||
"count": 7,
|
||||
"total_bytes": 2989,
|
||||
"max_bytes": 427
|
||||
}, {
|
||||
"kind": 22656,
|
||||
"count": 7,
|
||||
"total_bytes": 3017,
|
||||
"max_bytes": 431
|
||||
}, {
|
||||
"kind": 22316,
|
||||
"count": 7,
|
||||
"total_bytes": 3106,
|
||||
"max_bytes": 444
|
||||
}, {
|
||||
"kind": 30089,
|
||||
"count": 6,
|
||||
"total_bytes": 123676,
|
||||
"max_bytes": 44372
|
||||
}, {
|
||||
"kind": 22456,
|
||||
"count": 6,
|
||||
"total_bytes": 3140,
|
||||
"max_bytes": 790
|
||||
}, {
|
||||
"kind": 22739,
|
||||
"count": 6,
|
||||
"total_bytes": 2580,
|
||||
"max_bytes": 430
|
||||
}, {
|
||||
"kind": 22882,
|
||||
"count": 6,
|
||||
"total_bytes": 5292,
|
||||
"max_bytes": 1449
|
||||
}, {
|
||||
"kind": 22862,
|
||||
"count": 6,
|
||||
"total_bytes": 2574,
|
||||
"max_bytes": 429
|
||||
}, {
|
||||
"kind": 1111,
|
||||
"count": 6,
|
||||
"total_bytes": 7227,
|
||||
"max_bytes": 1698
|
||||
}, {
|
||||
"kind": 4245,
|
||||
"count": 5,
|
||||
"total_bytes": 2220,
|
||||
"max_bytes": 444
|
||||
}, {
|
||||
"kind": 30512,
|
||||
"count": 5,
|
||||
"total_bytes": 7504,
|
||||
"max_bytes": 1506
|
||||
}, {
|
||||
"kind": 22641,
|
||||
"count": 5,
|
||||
"total_bytes": 2145,
|
||||
"max_bytes": 429
|
||||
}, {
|
||||
"kind": 22586,
|
||||
"count": 5,
|
||||
"total_bytes": 2135,
|
||||
"max_bytes": 427
|
||||
}, {
|
||||
"kind": 4243,
|
||||
"count": 5,
|
||||
"total_bytes": 2820,
|
||||
"max_bytes": 564
|
||||
}, {
|
||||
"kind": 22835,
|
||||
"count": 5,
|
||||
"total_bytes": 2145,
|
||||
"max_bytes": 429
|
||||
}, {
|
||||
"kind": 22620,
|
||||
"count": 5,
|
||||
"total_bytes": 2145,
|
||||
"max_bytes": 429
|
||||
}, {
|
||||
"kind": 22298,
|
||||
"count": 5,
|
||||
"total_bytes": 2218,
|
||||
"max_bytes": 444
|
||||
}, {
|
||||
"kind": 22852,
|
||||
"count": 5,
|
||||
"total_bytes": 2140,
|
||||
"max_bytes": 428
|
||||
}, {
|
||||
"kind": 22726,
|
||||
"count": 5,
|
||||
"total_bytes": 2150,
|
||||
"max_bytes": 430
|
||||
}, {
|
||||
"kind": 22362,
|
||||
"count": 5,
|
||||
"total_bytes": 2218,
|
||||
"max_bytes": 444
|
||||
}, {
|
||||
"kind": 22772,
|
||||
"count": 5,
|
||||
"total_bytes": 4051,
|
||||
"max_bytes": 1132
|
||||
}, {
|
||||
"kind": 22805,
|
||||
"count": 4,
|
||||
"total_bytes": 1712,
|
||||
"max_bytes": 428
|
||||
}, {
|
||||
"kind": 9734,
|
||||
"count": 4,
|
||||
"total_bytes": 3756,
|
||||
"max_bytes": 1033
|
||||
}, {
|
||||
"kind": 22200,
|
||||
"count": 4,
|
||||
"total_bytes": 1774,
|
||||
"max_bytes": 444
|
||||
}, {
|
||||
"kind": 31510,
|
||||
"count": 4,
|
||||
"total_bytes": 3922,
|
||||
"max_bytes": 982
|
||||
}, {
|
||||
"kind": 22570,
|
||||
"count": 4,
|
||||
"total_bytes": 1716,
|
||||
"max_bytes": 429
|
||||
}, {
|
||||
"kind": 25195,
|
||||
"count": 4,
|
||||
"total_bytes": 2712,
|
||||
"max_bytes": 678
|
||||
}, {
|
||||
"kind": 22752,
|
||||
"count": 3,
|
||||
"total_bytes": 4047,
|
||||
"max_bytes": 3191
|
||||
}, {
|
||||
"kind": 31339,
|
||||
"count": 3,
|
||||
"total_bytes": 4410,
|
||||
"max_bytes": 1470
|
||||
}, {
|
||||
"kind": 22949,
|
||||
"count": 3,
|
||||
"total_bytes": 1287,
|
||||
"max_bytes": 429
|
||||
}, {
|
||||
"kind": 22358,
|
||||
"count": 3,
|
||||
"total_bytes": 1331,
|
||||
"max_bytes": 444
|
||||
}, {
|
||||
"kind": 22474,
|
||||
"count": 3,
|
||||
"total_bytes": 1330,
|
||||
"max_bytes": 444
|
||||
}, {
|
||||
"kind": 22185,
|
||||
"count": 3,
|
||||
"total_bytes": 1330,
|
||||
"max_bytes": 444
|
||||
}, {
|
||||
"kind": 22936,
|
||||
"count": 3,
|
||||
"total_bytes": 1290,
|
||||
"max_bytes": 430
|
||||
}, {
|
||||
"kind": 25196,
|
||||
"count": 3,
|
||||
"total_bytes": 4938,
|
||||
"max_bytes": 2214
|
||||
}, {
|
||||
"kind": 22439,
|
||||
"count": 3,
|
||||
"total_bytes": 1330,
|
||||
"max_bytes": 444
|
||||
}, {
|
||||
"kind": 22824,
|
||||
"count": 3,
|
||||
"total_bytes": 1281,
|
||||
"max_bytes": 427
|
||||
}, {
|
||||
"kind": 22270,
|
||||
"count": 3,
|
||||
"total_bytes": 1330,
|
||||
"max_bytes": 444
|
||||
}, {
|
||||
"kind": 22263,
|
||||
"count": 3,
|
||||
"total_bytes": 1330,
|
||||
"max_bytes": 444
|
||||
}, {
|
||||
"kind": 22755,
|
||||
"count": 3,
|
||||
"total_bytes": 1284,
|
||||
"max_bytes": 428
|
||||
}, {
|
||||
"kind": 10051,
|
||||
"count": 3,
|
||||
"total_bytes": 1317,
|
||||
"max_bytes": 439
|
||||
}, {
|
||||
"kind": 34775,
|
||||
"count": 3,
|
||||
"total_bytes": 7599,
|
||||
"max_bytes": 2561
|
||||
}, {
|
||||
"kind": 30300,
|
||||
"count": 3,
|
||||
"total_bytes": 5502,
|
||||
"max_bytes": 1834
|
||||
}, {
|
||||
"kind": 22234,
|
||||
"count": 3,
|
||||
"total_bytes": 1330,
|
||||
"max_bytes": 444
|
||||
}, {
|
||||
"kind": 7403,
|
||||
"count": 2,
|
||||
"total_bytes": 978,
|
||||
"max_bytes": 489
|
||||
}, {
|
||||
"kind": 22626,
|
||||
"count": 2,
|
||||
"total_bytes": 1916,
|
||||
"max_bytes": 1486
|
||||
}, {
|
||||
"kind": 30079,
|
||||
"count": 2,
|
||||
"total_bytes": 1750,
|
||||
"max_bytes": 875
|
||||
}, {
|
||||
"kind": 15750,
|
||||
"count": 2,
|
||||
"total_bytes": 1242,
|
||||
"max_bytes": 626
|
||||
}, {
|
||||
"kind": 23337,
|
||||
"count": 2,
|
||||
"total_bytes": 1027,
|
||||
"max_bytes": 514
|
||||
}, {
|
||||
"kind": 30815,
|
||||
"count": 2,
|
||||
"total_bytes": 75068,
|
||||
"max_bytes": 37534
|
||||
}, {
|
||||
"kind": 30213,
|
||||
"count": 2,
|
||||
"total_bytes": 1264,
|
||||
"max_bytes": 632
|
||||
}, {
|
||||
"kind": 22716,
|
||||
"count": 2,
|
||||
"total_bytes": 854,
|
||||
"max_bytes": 427
|
||||
}, {
|
||||
"kind": 22492,
|
||||
"count": 2,
|
||||
"total_bytes": 887,
|
||||
"max_bytes": 444
|
||||
}, {
|
||||
"kind": 30000,
|
||||
"count": 2,
|
||||
"total_bytes": 1646,
|
||||
"max_bytes": 823
|
||||
}, {
|
||||
"kind": 22463,
|
||||
"count": 2,
|
||||
"total_bytes": 887,
|
||||
"max_bytes": 444
|
||||
}, {
|
||||
"kind": 22304,
|
||||
"count": 2,
|
||||
"total_bytes": 887,
|
||||
"max_bytes": 444
|
||||
}, {
|
||||
"kind": 10003,
|
||||
"count": 2,
|
||||
"total_bytes": 20016,
|
||||
"max_bytes": 15003
|
||||
}, {
|
||||
"kind": 30443,
|
||||
"count": 2,
|
||||
"total_bytes": 2572,
|
||||
"max_bytes": 1312
|
||||
}, {
|
||||
"kind": 22233,
|
||||
"count": 2,
|
||||
"total_bytes": 886,
|
||||
"max_bytes": 443
|
||||
}, {
|
||||
"kind": 22275,
|
||||
"count": 2,
|
||||
"total_bytes": 887,
|
||||
"max_bytes": 444
|
||||
}, {
|
||||
"kind": 30087,
|
||||
"count": 2,
|
||||
"total_bytes": 11238,
|
||||
"max_bytes": 7325
|
||||
}, {
|
||||
"kind": 20078,
|
||||
"count": 2,
|
||||
"total_bytes": 1458,
|
||||
"max_bytes": 729
|
||||
}, {
|
||||
"kind": 22057,
|
||||
"count": 2,
|
||||
"total_bytes": 887,
|
||||
"max_bytes": 444
|
||||
}, {
|
||||
"kind": 22251,
|
||||
"count": 2,
|
||||
"total_bytes": 887,
|
||||
"max_bytes": 444
|
||||
}, {
|
||||
"kind": 22181,
|
||||
"count": 2,
|
||||
"total_bytes": 887,
|
||||
"max_bytes": 444
|
||||
}, {
|
||||
"kind": 22678,
|
||||
"count": 2,
|
||||
"total_bytes": 1388,
|
||||
"max_bytes": 694
|
||||
}, {
|
||||
"kind": 22747,
|
||||
"count": 2,
|
||||
"total_bytes": 858,
|
||||
"max_bytes": 429
|
||||
}, {
|
||||
"kind": 22410,
|
||||
"count": 2,
|
||||
"total_bytes": 887,
|
||||
"max_bytes": 444
|
||||
}, {
|
||||
"kind": 22334,
|
||||
"count": 2,
|
||||
"total_bytes": 887,
|
||||
"max_bytes": 444
|
||||
}, {
|
||||
"kind": 22249,
|
||||
"count": 2,
|
||||
"total_bytes": 887,
|
||||
"max_bytes": 444
|
||||
}, {
|
||||
"kind": 22258,
|
||||
"count": 2,
|
||||
"total_bytes": 887,
|
||||
"max_bytes": 444
|
||||
}, {
|
||||
"kind": 30090,
|
||||
"count": 2,
|
||||
"total_bytes": 2588,
|
||||
"max_bytes": 1515
|
||||
}, {
|
||||
"kind": 10312,
|
||||
"count": 1,
|
||||
"total_bytes": 472,
|
||||
"max_bytes": 472
|
||||
}, {
|
||||
"kind": 22853,
|
||||
"count": 1,
|
||||
"total_bytes": 1673,
|
||||
"max_bytes": 1673
|
||||
}, {
|
||||
"kind": 22303,
|
||||
"count": 1,
|
||||
"total_bytes": 443,
|
||||
"max_bytes": 443
|
||||
}, {
|
||||
"kind": 22306,
|
||||
"count": 1,
|
||||
"total_bytes": 443,
|
||||
"max_bytes": 443
|
||||
}, {
|
||||
"kind": 20200,
|
||||
"count": 1,
|
||||
"total_bytes": 491,
|
||||
"max_bytes": 491
|
||||
}, {
|
||||
"kind": 22132,
|
||||
"count": 1,
|
||||
"total_bytes": 443,
|
||||
"max_bytes": 443
|
||||
}, {
|
||||
"kind": 20201,
|
||||
"count": 1,
|
||||
"total_bytes": 491,
|
||||
"max_bytes": 491
|
||||
}, {
|
||||
"kind": 22245,
|
||||
"count": 1,
|
||||
"total_bytes": 443,
|
||||
"max_bytes": 443
|
||||
}, {
|
||||
"kind": 22352,
|
||||
"count": 1,
|
||||
"total_bytes": 443,
|
||||
"max_bytes": 443
|
||||
}, {
|
||||
"kind": 22240,
|
||||
"count": 1,
|
||||
"total_bytes": 443,
|
||||
"max_bytes": 443
|
||||
}, {
|
||||
"kind": 34236,
|
||||
"count": 1,
|
||||
"total_bytes": 931,
|
||||
"max_bytes": 931
|
||||
}, {
|
||||
"kind": 17,
|
||||
"count": 1,
|
||||
"total_bytes": 610,
|
||||
"max_bytes": 610
|
||||
}, {
|
||||
"kind": 22286,
|
||||
"count": 1,
|
||||
"total_bytes": 443,
|
||||
"max_bytes": 443
|
||||
}, {
|
||||
"kind": 13196,
|
||||
"count": 1,
|
||||
"total_bytes": 656,
|
||||
"max_bytes": 656
|
||||
}, {
|
||||
"kind": 20242,
|
||||
"count": 1,
|
||||
"total_bytes": 346,
|
||||
"max_bytes": 346
|
||||
}, {
|
||||
"kind": 7376,
|
||||
"count": 1,
|
||||
"total_bytes": 670,
|
||||
"max_bytes": 670
|
||||
}, {
|
||||
"kind": 38385,
|
||||
"count": 1,
|
||||
"total_bytes": 1350,
|
||||
"max_bytes": 1350
|
||||
}, {
|
||||
"kind": 22355,
|
||||
"count": 1,
|
||||
"total_bytes": 443,
|
||||
"max_bytes": 443
|
||||
}, {
|
||||
"kind": 23333,
|
||||
"count": 1,
|
||||
"total_bytes": 571,
|
||||
"max_bytes": 571
|
||||
}, {
|
||||
"kind": 22737,
|
||||
"count": 1,
|
||||
"total_bytes": 556,
|
||||
"max_bytes": 556
|
||||
}, {
|
||||
"kind": 22291,
|
||||
"count": 1,
|
||||
"total_bytes": 443,
|
||||
"max_bytes": 443
|
||||
}, {
|
||||
"kind": 30421,
|
||||
"count": 1,
|
||||
"total_bytes": 995,
|
||||
"max_bytes": 995
|
||||
}, {
|
||||
"kind": 22860,
|
||||
"count": 1,
|
||||
"total_bytes": 553,
|
||||
"max_bytes": 553
|
||||
}, {
|
||||
"kind": 2333,
|
||||
"count": 1,
|
||||
"total_bytes": 659,
|
||||
"max_bytes": 659
|
||||
}, {
|
||||
"kind": 22219,
|
||||
"count": 1,
|
||||
"total_bytes": 443,
|
||||
"max_bytes": 443
|
||||
}, {
|
||||
"kind": 22382,
|
||||
"count": 1,
|
||||
"total_bytes": 443,
|
||||
"max_bytes": 443
|
||||
}, {
|
||||
"kind": 23032,
|
||||
"count": 1,
|
||||
"total_bytes": 430,
|
||||
"max_bytes": 430
|
||||
}, {
|
||||
"kind": 7375,
|
||||
"count": 1,
|
||||
"total_bytes": 1822,
|
||||
"max_bytes": 1822
|
||||
}, {
|
||||
"kind": 22579,
|
||||
"count": 1,
|
||||
"total_bytes": 1670,
|
||||
"max_bytes": 1670
|
||||
}, {
|
||||
"kind": 10007,
|
||||
"count": 1,
|
||||
"total_bytes": 715,
|
||||
"max_bytes": 715
|
||||
}, {
|
||||
"kind": 10086,
|
||||
"count": 1,
|
||||
"total_bytes": 715,
|
||||
"max_bytes": 715
|
||||
}, {
|
||||
"kind": 22729,
|
||||
"count": 1,
|
||||
"total_bytes": 3030,
|
||||
"max_bytes": 3030
|
||||
}, {
|
||||
"kind": 22540,
|
||||
"count": 1,
|
||||
"total_bytes": 426,
|
||||
"max_bytes": 426
|
||||
}, {
|
||||
"kind": 22671,
|
||||
"count": 1,
|
||||
"total_bytes": 3194,
|
||||
"max_bytes": 3194
|
||||
}, {
|
||||
"kind": 30618,
|
||||
"count": 1,
|
||||
"total_bytes": 460,
|
||||
"max_bytes": 460
|
||||
}, {
|
||||
"kind": 23118,
|
||||
"count": 1,
|
||||
"total_bytes": 430,
|
||||
"max_bytes": 430
|
||||
}, {
|
||||
"kind": 38421,
|
||||
"count": 1,
|
||||
"total_bytes": 1069,
|
||||
"max_bytes": 1069
|
||||
}, {
|
||||
"kind": 10377,
|
||||
"count": 1,
|
||||
"total_bytes": 664,
|
||||
"max_bytes": 664
|
||||
}, {
|
||||
"kind": 11111,
|
||||
"count": 1,
|
||||
"total_bytes": 382,
|
||||
"max_bytes": 382
|
||||
}, {
|
||||
"kind": 34550,
|
||||
"count": 1,
|
||||
"total_bytes": 867,
|
||||
"max_bytes": 867
|
||||
}, {
|
||||
"kind": 22307,
|
||||
"count": 1,
|
||||
"total_bytes": 443,
|
||||
"max_bytes": 443
|
||||
}, {
|
||||
"kind": 1078,
|
||||
"count": 1,
|
||||
"total_bytes": 13969,
|
||||
"max_bytes": 13969
|
||||
}]
|
||||
}
|
||||
@@ -0,0 +1,938 @@
|
||||
{
|
||||
"duration_seconds": 376,
|
||||
"total_events": 5992,
|
||||
"total_bytes": 8743262,
|
||||
"unique_pubkeys": 1142,
|
||||
"relay_count": 1,
|
||||
"relays": [{
|
||||
"url": "wss://relay.primal.net",
|
||||
"events": 5992,
|
||||
"eose": 0,
|
||||
"closed": 0,
|
||||
"notice": 0,
|
||||
"errors": 0,
|
||||
"disconnects": 3,
|
||||
"connected": true
|
||||
}],
|
||||
"kinds": [{
|
||||
"kind": 30078,
|
||||
"count": 495,
|
||||
"total_bytes": 2024957,
|
||||
"max_bytes": 54029
|
||||
}, {
|
||||
"kind": 21059,
|
||||
"count": 386,
|
||||
"total_bytes": 1099128,
|
||||
"max_bytes": 5314
|
||||
}, {
|
||||
"kind": 4515,
|
||||
"count": 374,
|
||||
"total_bytes": 781718,
|
||||
"max_bytes": 14221
|
||||
}, {
|
||||
"kind": 22591,
|
||||
"count": 371,
|
||||
"total_bytes": 286839,
|
||||
"max_bytes": 1228
|
||||
}, {
|
||||
"kind": 20001,
|
||||
"count": 271,
|
||||
"total_bytes": 315643,
|
||||
"max_bytes": 2029
|
||||
}, {
|
||||
"kind": 22734,
|
||||
"count": 264,
|
||||
"total_bytes": 112728,
|
||||
"max_bytes": 427
|
||||
}, {
|
||||
"kind": 30382,
|
||||
"count": 255,
|
||||
"total_bytes": 121375,
|
||||
"max_bytes": 483
|
||||
}, {
|
||||
"kind": 30383,
|
||||
"count": 237,
|
||||
"total_bytes": 126938,
|
||||
"max_bytes": 547
|
||||
}, {
|
||||
"kind": 1,
|
||||
"count": 212,
|
||||
"total_bytes": 211399,
|
||||
"max_bytes": 2011
|
||||
}, {
|
||||
"kind": 5,
|
||||
"count": 183,
|
||||
"total_bytes": 91915,
|
||||
"max_bytes": 664
|
||||
}, {
|
||||
"kind": 22236,
|
||||
"count": 146,
|
||||
"total_bytes": 104252,
|
||||
"max_bytes": 810
|
||||
}, {
|
||||
"kind": 0,
|
||||
"count": 145,
|
||||
"total_bytes": 103418,
|
||||
"max_bytes": 2012
|
||||
}, {
|
||||
"kind": 7,
|
||||
"count": 138,
|
||||
"total_bytes": 79421,
|
||||
"max_bytes": 1036
|
||||
}, {
|
||||
"kind": 22743,
|
||||
"count": 134,
|
||||
"total_bytes": 57352,
|
||||
"max_bytes": 428
|
||||
}, {
|
||||
"kind": 1059,
|
||||
"count": 132,
|
||||
"total_bytes": 430222,
|
||||
"max_bytes": 5285
|
||||
}, {
|
||||
"kind": 29333,
|
||||
"count": 130,
|
||||
"total_bytes": 63960,
|
||||
"max_bytes": 492
|
||||
}, {
|
||||
"kind": 22611,
|
||||
"count": 117,
|
||||
"total_bytes": 50147,
|
||||
"max_bytes": 429
|
||||
}, {
|
||||
"kind": 10002,
|
||||
"count": 114,
|
||||
"total_bytes": 510211,
|
||||
"max_bytes": 42449
|
||||
}, {
|
||||
"kind": 23456,
|
||||
"count": 72,
|
||||
"total_bytes": 121616,
|
||||
"max_bytes": 1874
|
||||
}, {
|
||||
"kind": 22850,
|
||||
"count": 71,
|
||||
"total_bytes": 30530,
|
||||
"max_bytes": 430
|
||||
}, {
|
||||
"kind": 22684,
|
||||
"count": 70,
|
||||
"total_bytes": 30170,
|
||||
"max_bytes": 431
|
||||
}, {
|
||||
"kind": 22838,
|
||||
"count": 63,
|
||||
"total_bytes": 27027,
|
||||
"max_bytes": 429
|
||||
}, {
|
||||
"kind": 23003,
|
||||
"count": 63,
|
||||
"total_bytes": 26964,
|
||||
"max_bytes": 428
|
||||
}, {
|
||||
"kind": 22774,
|
||||
"count": 62,
|
||||
"total_bytes": 26536,
|
||||
"max_bytes": 428
|
||||
}, {
|
||||
"kind": 22876,
|
||||
"count": 61,
|
||||
"total_bytes": 28880,
|
||||
"max_bytes": 3193
|
||||
}, {
|
||||
"kind": 22583,
|
||||
"count": 61,
|
||||
"total_bytes": 26047,
|
||||
"max_bytes": 427
|
||||
}, {
|
||||
"kind": 22613,
|
||||
"count": 60,
|
||||
"total_bytes": 43172,
|
||||
"max_bytes": 1133
|
||||
}, {
|
||||
"kind": 4,
|
||||
"count": 58,
|
||||
"total_bytes": 61778,
|
||||
"max_bytes": 17018
|
||||
}, {
|
||||
"kind": 25555,
|
||||
"count": 56,
|
||||
"total_bytes": 249772,
|
||||
"max_bytes": 16895
|
||||
}, {
|
||||
"kind": 25050,
|
||||
"count": 51,
|
||||
"total_bytes": 20451,
|
||||
"max_bytes": 401
|
||||
}, {
|
||||
"kind": 11998,
|
||||
"count": 48,
|
||||
"total_bytes": 22272,
|
||||
"max_bytes": 465
|
||||
}, {
|
||||
"kind": 22728,
|
||||
"count": 48,
|
||||
"total_bytes": 20592,
|
||||
"max_bytes": 429
|
||||
}, {
|
||||
"kind": 31234,
|
||||
"count": 33,
|
||||
"total_bytes": 77859,
|
||||
"max_bytes": 2612
|
||||
}, {
|
||||
"kind": 13194,
|
||||
"count": 32,
|
||||
"total_bytes": 16448,
|
||||
"max_bytes": 514
|
||||
}, {
|
||||
"kind": 20387,
|
||||
"count": 32,
|
||||
"total_bytes": 16448,
|
||||
"max_bytes": 514
|
||||
}, {
|
||||
"kind": 24133,
|
||||
"count": 32,
|
||||
"total_bytes": 23680,
|
||||
"max_bytes": 2214
|
||||
}, {
|
||||
"kind": 3,
|
||||
"count": 31,
|
||||
"total_bytes": 167289,
|
||||
"max_bytes": 61894
|
||||
}, {
|
||||
"kind": 4004,
|
||||
"count": 26,
|
||||
"total_bytes": 30394,
|
||||
"max_bytes": 1169
|
||||
}, {
|
||||
"kind": 22816,
|
||||
"count": 26,
|
||||
"total_bytes": 11154,
|
||||
"max_bytes": 429
|
||||
}, {
|
||||
"kind": 20004,
|
||||
"count": 26,
|
||||
"total_bytes": 13878,
|
||||
"max_bytes": 549
|
||||
}, {
|
||||
"kind": 30315,
|
||||
"count": 26,
|
||||
"total_bytes": 17657,
|
||||
"max_bytes": 872
|
||||
}, {
|
||||
"kind": 443,
|
||||
"count": 25,
|
||||
"total_bytes": 43504,
|
||||
"max_bytes": 22480
|
||||
}, {
|
||||
"kind": 38501,
|
||||
"count": 24,
|
||||
"total_bytes": 17819,
|
||||
"max_bytes": 744
|
||||
}, {
|
||||
"kind": 1985,
|
||||
"count": 24,
|
||||
"total_bytes": 11435,
|
||||
"max_bytes": 483
|
||||
}, {
|
||||
"kind": 22882,
|
||||
"count": 23,
|
||||
"total_bytes": 20949,
|
||||
"max_bytes": 1455
|
||||
}, {
|
||||
"kind": 5300,
|
||||
"count": 22,
|
||||
"total_bytes": 13434,
|
||||
"max_bytes": 701
|
||||
}, {
|
||||
"kind": 31990,
|
||||
"count": 22,
|
||||
"total_bytes": 21777,
|
||||
"max_bytes": 6861
|
||||
}, {
|
||||
"kind": 22790,
|
||||
"count": 21,
|
||||
"total_bytes": 8988,
|
||||
"max_bytes": 428
|
||||
}, {
|
||||
"kind": 21050,
|
||||
"count": 19,
|
||||
"total_bytes": 17510,
|
||||
"max_bytes": 1874
|
||||
}, {
|
||||
"kind": 10100,
|
||||
"count": 19,
|
||||
"total_bytes": 22108,
|
||||
"max_bytes": 1589
|
||||
}, {
|
||||
"kind": 20333,
|
||||
"count": 18,
|
||||
"total_bytes": 14340,
|
||||
"max_bytes": 798
|
||||
}, {
|
||||
"kind": 30088,
|
||||
"count": 16,
|
||||
"total_bytes": 29798,
|
||||
"max_bytes": 1871
|
||||
}, {
|
||||
"kind": 6,
|
||||
"count": 16,
|
||||
"total_bytes": 28131,
|
||||
"max_bytes": 3369
|
||||
}, {
|
||||
"kind": 30091,
|
||||
"count": 16,
|
||||
"total_bytes": 9842,
|
||||
"max_bytes": 629
|
||||
}, {
|
||||
"kind": 6300,
|
||||
"count": 15,
|
||||
"total_bytes": 45643,
|
||||
"max_bytes": 8157
|
||||
}, {
|
||||
"kind": 22658,
|
||||
"count": 15,
|
||||
"total_bytes": 11909,
|
||||
"max_bytes": 1161
|
||||
}, {
|
||||
"kind": 30311,
|
||||
"count": 15,
|
||||
"total_bytes": 16556,
|
||||
"max_bytes": 1197
|
||||
}, {
|
||||
"kind": 445,
|
||||
"count": 15,
|
||||
"total_bytes": 45070,
|
||||
"max_bytes": 4130
|
||||
}, {
|
||||
"kind": 10777,
|
||||
"count": 14,
|
||||
"total_bytes": 6840,
|
||||
"max_bytes": 489
|
||||
}, {
|
||||
"kind": 9735,
|
||||
"count": 14,
|
||||
"total_bytes": 27231,
|
||||
"max_bytes": 2777
|
||||
}, {
|
||||
"kind": 4244,
|
||||
"count": 12,
|
||||
"total_bytes": 6768,
|
||||
"max_bytes": 564
|
||||
}, {
|
||||
"kind": 22456,
|
||||
"count": 12,
|
||||
"total_bytes": 6808,
|
||||
"max_bytes": 790
|
||||
}, {
|
||||
"kind": 38503,
|
||||
"count": 11,
|
||||
"total_bytes": 6070,
|
||||
"max_bytes": 552
|
||||
}, {
|
||||
"kind": 10050,
|
||||
"count": 11,
|
||||
"total_bytes": 4882,
|
||||
"max_bytes": 592
|
||||
}, {
|
||||
"kind": 30515,
|
||||
"count": 10,
|
||||
"total_bytes": 53040,
|
||||
"max_bytes": 5304
|
||||
}, {
|
||||
"kind": 30512,
|
||||
"count": 10,
|
||||
"total_bytes": 15210,
|
||||
"max_bytes": 1596
|
||||
}, {
|
||||
"kind": 30089,
|
||||
"count": 10,
|
||||
"total_bytes": 164434,
|
||||
"max_bytes": 44372
|
||||
}, {
|
||||
"kind": 10000,
|
||||
"count": 10,
|
||||
"total_bytes": 16448,
|
||||
"max_bytes": 4287
|
||||
}, {
|
||||
"kind": 22809,
|
||||
"count": 9,
|
||||
"total_bytes": 3852,
|
||||
"max_bytes": 428
|
||||
}, {
|
||||
"kind": 22486,
|
||||
"count": 9,
|
||||
"total_bytes": 3834,
|
||||
"max_bytes": 426
|
||||
}, {
|
||||
"kind": 22376,
|
||||
"count": 8,
|
||||
"total_bytes": 3550,
|
||||
"max_bytes": 444
|
||||
}, {
|
||||
"kind": 7368,
|
||||
"count": 8,
|
||||
"total_bytes": 8294,
|
||||
"max_bytes": 1040
|
||||
}, {
|
||||
"kind": 38500,
|
||||
"count": 8,
|
||||
"total_bytes": 5696,
|
||||
"max_bytes": 713
|
||||
}, {
|
||||
"kind": 30380,
|
||||
"count": 7,
|
||||
"total_bytes": 3178,
|
||||
"max_bytes": 454
|
||||
}, {
|
||||
"kind": 20000,
|
||||
"count": 7,
|
||||
"total_bytes": 2422,
|
||||
"max_bytes": 346
|
||||
}, {
|
||||
"kind": 22104,
|
||||
"count": 7,
|
||||
"total_bytes": 3105,
|
||||
"max_bytes": 444
|
||||
}, {
|
||||
"kind": 23025,
|
||||
"count": 7,
|
||||
"total_bytes": 3017,
|
||||
"max_bytes": 431
|
||||
}, {
|
||||
"kind": 22896,
|
||||
"count": 7,
|
||||
"total_bytes": 3003,
|
||||
"max_bytes": 429
|
||||
}, {
|
||||
"kind": 33334,
|
||||
"count": 7,
|
||||
"total_bytes": 5817,
|
||||
"max_bytes": 831
|
||||
}, {
|
||||
"kind": 22835,
|
||||
"count": 6,
|
||||
"total_bytes": 2574,
|
||||
"max_bytes": 429
|
||||
}, {
|
||||
"kind": 30443,
|
||||
"count": 6,
|
||||
"total_bytes": 7297,
|
||||
"max_bytes": 1260
|
||||
}, {
|
||||
"kind": 22633,
|
||||
"count": 6,
|
||||
"total_bytes": 6097,
|
||||
"max_bytes": 1668
|
||||
}, {
|
||||
"kind": 22392,
|
||||
"count": 6,
|
||||
"total_bytes": 2662,
|
||||
"max_bytes": 444
|
||||
}, {
|
||||
"kind": 1984,
|
||||
"count": 6,
|
||||
"total_bytes": 3180,
|
||||
"max_bytes": 530
|
||||
}, {
|
||||
"kind": 30064,
|
||||
"count": 6,
|
||||
"total_bytes": 4438,
|
||||
"max_bytes": 991
|
||||
}, {
|
||||
"kind": 22715,
|
||||
"count": 6,
|
||||
"total_bytes": 2562,
|
||||
"max_bytes": 427
|
||||
}, {
|
||||
"kind": 30280,
|
||||
"count": 6,
|
||||
"total_bytes": 3078,
|
||||
"max_bytes": 513
|
||||
}, {
|
||||
"kind": 22559,
|
||||
"count": 6,
|
||||
"total_bytes": 2574,
|
||||
"max_bytes": 429
|
||||
}, {
|
||||
"kind": 22813,
|
||||
"count": 6,
|
||||
"total_bytes": 2562,
|
||||
"max_bytes": 427
|
||||
}, {
|
||||
"kind": 22635,
|
||||
"count": 6,
|
||||
"total_bytes": 2556,
|
||||
"max_bytes": 426
|
||||
}, {
|
||||
"kind": 22746,
|
||||
"count": 5,
|
||||
"total_bytes": 2155,
|
||||
"max_bytes": 431
|
||||
}, {
|
||||
"kind": 22364,
|
||||
"count": 5,
|
||||
"total_bytes": 2135,
|
||||
"max_bytes": 427
|
||||
}, {
|
||||
"kind": 37195,
|
||||
"count": 5,
|
||||
"total_bytes": 3664,
|
||||
"max_bytes": 786
|
||||
}, {
|
||||
"kind": 22571,
|
||||
"count": 5,
|
||||
"total_bytes": 4055,
|
||||
"max_bytes": 1127
|
||||
}, {
|
||||
"kind": 23004,
|
||||
"count": 5,
|
||||
"total_bytes": 2145,
|
||||
"max_bytes": 429
|
||||
}, {
|
||||
"kind": 22834,
|
||||
"count": 5,
|
||||
"total_bytes": 4050,
|
||||
"max_bytes": 1126
|
||||
}, {
|
||||
"kind": 22636,
|
||||
"count": 5,
|
||||
"total_bytes": 3280,
|
||||
"max_bytes": 1164
|
||||
}, {
|
||||
"kind": 22786,
|
||||
"count": 4,
|
||||
"total_bytes": 1720,
|
||||
"max_bytes": 430
|
||||
}, {
|
||||
"kind": 25195,
|
||||
"count": 4,
|
||||
"total_bytes": 2712,
|
||||
"max_bytes": 678
|
||||
}, {
|
||||
"kind": 4243,
|
||||
"count": 4,
|
||||
"total_bytes": 2256,
|
||||
"max_bytes": 564
|
||||
}, {
|
||||
"kind": 22168,
|
||||
"count": 4,
|
||||
"total_bytes": 1774,
|
||||
"max_bytes": 444
|
||||
}, {
|
||||
"kind": 22760,
|
||||
"count": 4,
|
||||
"total_bytes": 2239,
|
||||
"max_bytes": 695
|
||||
}, {
|
||||
"kind": 22733,
|
||||
"count": 4,
|
||||
"total_bytes": 1696,
|
||||
"max_bytes": 424
|
||||
}, {
|
||||
"kind": 22878,
|
||||
"count": 3,
|
||||
"total_bytes": 4059,
|
||||
"max_bytes": 3203
|
||||
}, {
|
||||
"kind": 22902,
|
||||
"count": 3,
|
||||
"total_bytes": 5023,
|
||||
"max_bytes": 1675
|
||||
}, {
|
||||
"kind": 22428,
|
||||
"count": 3,
|
||||
"total_bytes": 1331,
|
||||
"max_bytes": 444
|
||||
}, {
|
||||
"kind": 25196,
|
||||
"count": 3,
|
||||
"total_bytes": 4938,
|
||||
"max_bytes": 2214
|
||||
}, {
|
||||
"kind": 22325,
|
||||
"count": 3,
|
||||
"total_bytes": 1331,
|
||||
"max_bytes": 444
|
||||
}, {
|
||||
"kind": 4245,
|
||||
"count": 3,
|
||||
"total_bytes": 1332,
|
||||
"max_bytes": 444
|
||||
}, {
|
||||
"kind": 22258,
|
||||
"count": 3,
|
||||
"total_bytes": 1331,
|
||||
"max_bytes": 444
|
||||
}, {
|
||||
"kind": 22625,
|
||||
"count": 3,
|
||||
"total_bytes": 1284,
|
||||
"max_bytes": 428
|
||||
}, {
|
||||
"kind": 22631,
|
||||
"count": 3,
|
||||
"total_bytes": 1281,
|
||||
"max_bytes": 427
|
||||
}, {
|
||||
"kind": 22551,
|
||||
"count": 3,
|
||||
"total_bytes": 1816,
|
||||
"max_bytes": 695
|
||||
}, {
|
||||
"kind": 22763,
|
||||
"count": 3,
|
||||
"total_bytes": 2988,
|
||||
"max_bytes": 1331
|
||||
}, {
|
||||
"kind": 3927,
|
||||
"count": 2,
|
||||
"total_bytes": 1066,
|
||||
"max_bytes": 533
|
||||
}, {
|
||||
"kind": 22186,
|
||||
"count": 2,
|
||||
"total_bytes": 887,
|
||||
"max_bytes": 444
|
||||
}, {
|
||||
"kind": 30213,
|
||||
"count": 2,
|
||||
"total_bytes": 1264,
|
||||
"max_bytes": 632
|
||||
}, {
|
||||
"kind": 22367,
|
||||
"count": 2,
|
||||
"total_bytes": 887,
|
||||
"max_bytes": 444
|
||||
}, {
|
||||
"kind": 22783,
|
||||
"count": 2,
|
||||
"total_bytes": 1391,
|
||||
"max_bytes": 697
|
||||
}, {
|
||||
"kind": 22616,
|
||||
"count": 2,
|
||||
"total_bytes": 858,
|
||||
"max_bytes": 429
|
||||
}, {
|
||||
"kind": 22268,
|
||||
"count": 2,
|
||||
"total_bytes": 887,
|
||||
"max_bytes": 444
|
||||
}, {
|
||||
"kind": 22279,
|
||||
"count": 2,
|
||||
"total_bytes": 887,
|
||||
"max_bytes": 444
|
||||
}, {
|
||||
"kind": 22474,
|
||||
"count": 2,
|
||||
"total_bytes": 887,
|
||||
"max_bytes": 444
|
||||
}, {
|
||||
"kind": 22407,
|
||||
"count": 2,
|
||||
"total_bytes": 887,
|
||||
"max_bytes": 444
|
||||
}, {
|
||||
"kind": 22729,
|
||||
"count": 2,
|
||||
"total_bytes": 854,
|
||||
"max_bytes": 427
|
||||
}, {
|
||||
"kind": 22234,
|
||||
"count": 2,
|
||||
"total_bytes": 887,
|
||||
"max_bytes": 444
|
||||
}, {
|
||||
"kind": 10003,
|
||||
"count": 2,
|
||||
"total_bytes": 18782,
|
||||
"max_bytes": 15076
|
||||
}, {
|
||||
"kind": 30815,
|
||||
"count": 2,
|
||||
"total_bytes": 75068,
|
||||
"max_bytes": 37534
|
||||
}, {
|
||||
"kind": 1111,
|
||||
"count": 2,
|
||||
"total_bytes": 1775,
|
||||
"max_bytes": 922
|
||||
}, {
|
||||
"kind": 30087,
|
||||
"count": 2,
|
||||
"total_bytes": 13286,
|
||||
"max_bytes": 7325
|
||||
}, {
|
||||
"kind": 22256,
|
||||
"count": 2,
|
||||
"total_bytes": 886,
|
||||
"max_bytes": 443
|
||||
}, {
|
||||
"kind": 22299,
|
||||
"count": 2,
|
||||
"total_bytes": 887,
|
||||
"max_bytes": 444
|
||||
}, {
|
||||
"kind": 30090,
|
||||
"count": 2,
|
||||
"total_bytes": 2911,
|
||||
"max_bytes": 1515
|
||||
}, {
|
||||
"kind": 22260,
|
||||
"count": 2,
|
||||
"total_bytes": 887,
|
||||
"max_bytes": 444
|
||||
}, {
|
||||
"kind": 7376,
|
||||
"count": 2,
|
||||
"total_bytes": 1340,
|
||||
"max_bytes": 670
|
||||
}, {
|
||||
"kind": 22012,
|
||||
"count": 2,
|
||||
"total_bytes": 887,
|
||||
"max_bytes": 444
|
||||
}, {
|
||||
"kind": 30618,
|
||||
"count": 2,
|
||||
"total_bytes": 920,
|
||||
"max_bytes": 460
|
||||
}, {
|
||||
"kind": 1078,
|
||||
"count": 2,
|
||||
"total_bytes": 28397,
|
||||
"max_bytes": 14219
|
||||
}, {
|
||||
"kind": 22313,
|
||||
"count": 2,
|
||||
"total_bytes": 887,
|
||||
"max_bytes": 444
|
||||
}, {
|
||||
"kind": 31339,
|
||||
"count": 2,
|
||||
"total_bytes": 2940,
|
||||
"max_bytes": 1470
|
||||
}, {
|
||||
"kind": 15750,
|
||||
"count": 2,
|
||||
"total_bytes": 1184,
|
||||
"max_bytes": 620
|
||||
}, {
|
||||
"kind": 20,
|
||||
"count": 2,
|
||||
"total_bytes": 1664,
|
||||
"max_bytes": 834
|
||||
}, {
|
||||
"kind": 22326,
|
||||
"count": 2,
|
||||
"total_bytes": 887,
|
||||
"max_bytes": 444
|
||||
}, {
|
||||
"kind": 22841,
|
||||
"count": 1,
|
||||
"total_bytes": 428,
|
||||
"max_bytes": 428
|
||||
}, {
|
||||
"kind": 22738,
|
||||
"count": 1,
|
||||
"total_bytes": 1668,
|
||||
"max_bytes": 1668
|
||||
}, {
|
||||
"kind": 22295,
|
||||
"count": 1,
|
||||
"total_bytes": 443,
|
||||
"max_bytes": 443
|
||||
}, {
|
||||
"kind": 22296,
|
||||
"count": 1,
|
||||
"total_bytes": 443,
|
||||
"max_bytes": 443
|
||||
}, {
|
||||
"kind": 31510,
|
||||
"count": 1,
|
||||
"total_bytes": 979,
|
||||
"max_bytes": 979
|
||||
}, {
|
||||
"kind": 22691,
|
||||
"count": 1,
|
||||
"total_bytes": 431,
|
||||
"max_bytes": 431
|
||||
}, {
|
||||
"kind": 22340,
|
||||
"count": 1,
|
||||
"total_bytes": 443,
|
||||
"max_bytes": 443
|
||||
}, {
|
||||
"kind": 30003,
|
||||
"count": 1,
|
||||
"total_bytes": 387,
|
||||
"max_bytes": 387
|
||||
}, {
|
||||
"kind": 22197,
|
||||
"count": 1,
|
||||
"total_bytes": 443,
|
||||
"max_bytes": 443
|
||||
}, {
|
||||
"kind": 22257,
|
||||
"count": 1,
|
||||
"total_bytes": 443,
|
||||
"max_bytes": 443
|
||||
}, {
|
||||
"kind": 30079,
|
||||
"count": 1,
|
||||
"total_bytes": 875,
|
||||
"max_bytes": 875
|
||||
}, {
|
||||
"kind": 22811,
|
||||
"count": 1,
|
||||
"total_bytes": 3211,
|
||||
"max_bytes": 3211
|
||||
}, {
|
||||
"kind": 38385,
|
||||
"count": 1,
|
||||
"total_bytes": 1350,
|
||||
"max_bytes": 1350
|
||||
}, {
|
||||
"kind": 22339,
|
||||
"count": 1,
|
||||
"total_bytes": 443,
|
||||
"max_bytes": 443
|
||||
}, {
|
||||
"kind": 13196,
|
||||
"count": 1,
|
||||
"total_bytes": 656,
|
||||
"max_bytes": 656
|
||||
}, {
|
||||
"kind": 20200,
|
||||
"count": 1,
|
||||
"total_bytes": 491,
|
||||
"max_bytes": 491
|
||||
}, {
|
||||
"kind": 20201,
|
||||
"count": 1,
|
||||
"total_bytes": 491,
|
||||
"max_bytes": 491
|
||||
}, {
|
||||
"kind": 22395,
|
||||
"count": 1,
|
||||
"total_bytes": 443,
|
||||
"max_bytes": 443
|
||||
}, {
|
||||
"kind": 30023,
|
||||
"count": 1,
|
||||
"total_bytes": 27062,
|
||||
"max_bytes": 27062
|
||||
}, {
|
||||
"kind": 7403,
|
||||
"count": 1,
|
||||
"total_bytes": 490,
|
||||
"max_bytes": 490
|
||||
}, {
|
||||
"kind": 22618,
|
||||
"count": 1,
|
||||
"total_bytes": 1668,
|
||||
"max_bytes": 1668
|
||||
}, {
|
||||
"kind": 17,
|
||||
"count": 1,
|
||||
"total_bytes": 593,
|
||||
"max_bytes": 593
|
||||
}, {
|
||||
"kind": 30000,
|
||||
"count": 1,
|
||||
"total_bytes": 823,
|
||||
"max_bytes": 823
|
||||
}, {
|
||||
"kind": 22558,
|
||||
"count": 1,
|
||||
"total_bytes": 428,
|
||||
"max_bytes": 428
|
||||
}, {
|
||||
"kind": 22143,
|
||||
"count": 1,
|
||||
"total_bytes": 443,
|
||||
"max_bytes": 443
|
||||
}, {
|
||||
"kind": 22198,
|
||||
"count": 1,
|
||||
"total_bytes": 443,
|
||||
"max_bytes": 443
|
||||
}, {
|
||||
"kind": 7375,
|
||||
"count": 1,
|
||||
"total_bytes": 2846,
|
||||
"max_bytes": 2846
|
||||
}, {
|
||||
"kind": 22506,
|
||||
"count": 1,
|
||||
"total_bytes": 426,
|
||||
"max_bytes": 426
|
||||
}, {
|
||||
"kind": 22243,
|
||||
"count": 1,
|
||||
"total_bytes": 443,
|
||||
"max_bytes": 443
|
||||
}, {
|
||||
"kind": 23086,
|
||||
"count": 1,
|
||||
"total_bytes": 431,
|
||||
"max_bytes": 431
|
||||
}, {
|
||||
"kind": 22688,
|
||||
"count": 1,
|
||||
"total_bytes": 3201,
|
||||
"max_bytes": 3201
|
||||
}, {
|
||||
"kind": 22975,
|
||||
"count": 1,
|
||||
"total_bytes": 429,
|
||||
"max_bytes": 429
|
||||
}, {
|
||||
"kind": 22270,
|
||||
"count": 1,
|
||||
"total_bytes": 443,
|
||||
"max_bytes": 443
|
||||
}, {
|
||||
"kind": 22584,
|
||||
"count": 1,
|
||||
"total_bytes": 1675,
|
||||
"max_bytes": 1675
|
||||
}, {
|
||||
"kind": 22764,
|
||||
"count": 1,
|
||||
"total_bytes": 551,
|
||||
"max_bytes": 551
|
||||
}, {
|
||||
"kind": 23071,
|
||||
"count": 1,
|
||||
"total_bytes": 1675,
|
||||
"max_bytes": 1675
|
||||
}, {
|
||||
"kind": 22817,
|
||||
"count": 1,
|
||||
"total_bytes": 559,
|
||||
"max_bytes": 559
|
||||
}, {
|
||||
"kind": 22614,
|
||||
"count": 1,
|
||||
"total_bytes": 3200,
|
||||
"max_bytes": 3200
|
||||
}, {
|
||||
"kind": 22330,
|
||||
"count": 1,
|
||||
"total_bytes": 443,
|
||||
"max_bytes": 443
|
||||
}, {
|
||||
"kind": 22229,
|
||||
"count": 1,
|
||||
"total_bytes": 443,
|
||||
"max_bytes": 443
|
||||
}, {
|
||||
"kind": 24421,
|
||||
"count": 1,
|
||||
"total_bytes": 525,
|
||||
"max_bytes": 525
|
||||
}]
|
||||
}
|
||||
@@ -0,0 +1,63 @@
|
||||
import json, sys, os
|
||||
from collections import Counter
|
||||
|
||||
def analyze(filepath):
|
||||
kinds = Counter()
|
||||
sizes = Counter()
|
||||
pubkeys = Counter()
|
||||
total = 0
|
||||
total_bytes = 0
|
||||
max_size = 0
|
||||
max_size_kind = None
|
||||
relay_msgs = []
|
||||
|
||||
with open(filepath) as f:
|
||||
for line in f:
|
||||
line = line.strip()
|
||||
if not line:
|
||||
continue
|
||||
try:
|
||||
ev = json.loads(line)
|
||||
except:
|
||||
relay_msgs.append(line)
|
||||
continue
|
||||
|
||||
kind = ev.get('kind', -1)
|
||||
kinds[kind] += 1
|
||||
total += 1
|
||||
|
||||
pk = ev.get('pubkey', '')
|
||||
pubkeys[pk] += 1
|
||||
|
||||
sz = len(line)
|
||||
sizes[kind] += sz
|
||||
total_bytes += sz
|
||||
if sz > max_size:
|
||||
max_size = sz
|
||||
max_size_kind = kind
|
||||
|
||||
print(f"{'='*60}")
|
||||
print(f"File: {os.path.basename(filepath)}")
|
||||
print(f"{'='*60}")
|
||||
print(f"Total events: {total}")
|
||||
print(f"Total bytes: {total_bytes:,}")
|
||||
print(f"Avg size: {total_bytes/max(total,1):,.0f} bytes")
|
||||
print(f"Max event: {max_size:,} bytes (kind {max_size_kind})")
|
||||
print(f"Unique pubkeys: {len(pubkeys)}")
|
||||
print(f"Relay messages: {len(relay_msgs)}")
|
||||
if relay_msgs:
|
||||
print(f" First few: {relay_msgs[:3]}")
|
||||
print()
|
||||
|
||||
print(f"{'Kind':>8} {'Count':>8} {'%':>6} {'Total Bytes':>14} {'Avg Bytes':>10}")
|
||||
print(f"{'-'*8} {'-'*8} {'-'*6} {'-'*14} {'-'*10}")
|
||||
for kind, count in kinds.most_common():
|
||||
pct = count / total * 100
|
||||
tb = sizes[kind]
|
||||
avg = tb / count
|
||||
print(f"{kind:>8} {count:>8} {pct:>5.1f}% {tb:>12,} {avg:>8,.0f}")
|
||||
print()
|
||||
|
||||
if __name__ == '__main__':
|
||||
for f in sys.argv[1:]:
|
||||
analyze(f)
|
||||
@@ -0,0 +1,2 @@
|
||||
connecting to relay.damus.io... status 503
|
||||
failed to connect to any of the given relays.
|
||||
@@ -0,0 +1 @@
|
||||
connecting to nos.lol... ok.
|
||||
@@ -0,0 +1,100 @@
|
||||
{"kind":1059,"id":"3b112c9920bc79584669face207b9491a2a2da388110b84aa085a543d99ac841","pubkey":"c91a8fba68b9d08b9917e3a7443083a9b1364c984685bc56e2310024507612e9","created_at":1785677036,"tags":[["p","0ac458d69b9340c2e8a20a4d5f3afac1211b59e372a646beec37ac32b05ea4cb"]],"content":"v2:v4hmDySAiOH_Iv0uoZ0c5ctYsNwIFjWYQaAr5RPg5s-jqC95LxG56m_gZyio5uKm_7bImZ7hKuyoKXPx8_lfvJsg042FpZnUE8kCU8gAbl0lPTlHbwi-uPL43u0p1SACh1HHf8zyQMLaSBEIV-FTIghxtz9nIjo962bVbCqbh1sk_iMJ6qeEkmmYOCukb8ryRBYnW_7RsruPUsXnbGq5-JS4LXaKwmFmk78GYnaVaRzr_9IlQfUNKe2KD89hcsg5-SbOfLX-YEXeIeB7fKGT741tCtHs9JOBvwA7pgGwdfvUHUmz7WbSv4E6au2JENZ944rkxkv-8LinUAt0vlkXvzmHh-vwhnF9d09BZSj_tHvX2d7PEVg70EgifE6p6X5NnOjILq7VaSYTf2BLfkGl_dwV0R3pGL5_EtHr4abVGCeWTn30YJdUYHu7WV_7YuaX8tAxi0QtZ_5wstZEi8EkIS7R-ocJHNLVX8V3qp8hbFJ9jw_ZZv2Yjfjs_1CZLY7z-1u1WVjcBeXzEGQj5jnQTsf05D9Lv0fE9dmz5UL172LIJhDRQarhtowUJihycoQvRgcY8QH9wZzND-xCclxoncgku2x86TPyMmOPE9vhZX-UeimbJVSFO_PUt71quXF3l6kSLJqGK9Kpjf_yTKlcOiWqRlZ89QYuPfX5jNWEvWfv-g2rLmq2HM59Yq_J7iZZmXB_j0MH0Wz95Vdy6BdFkKA2boYWh7EKTslQHNw7uFZAsbH4keW64urcx1f21y6ccssz3snUGesmxlflSgbQCaY0C4J91OSOU8HsjGwbF1JIAK-UmLwNXsr645Z8iVingbQnSiUyR_RCWgufGaT03bJVp0uZNhrEAHckvYQ15mhHLDSIJoNCiTr0nBfpc1_iupYVQYXjWLgDcFIXhYbrr_cGPL_7sCVrfxKzrCbcm4Nz2LQo2ICrKWFUvWsDOw7Rp8e-gjLaLQxf349rgPPH0bz3VpA_vyiina8G8MGjZ1DnmRRyWn7IqN1Zc2x81_eYu4d25QAeqtctF86keK-nwQcQJt-frFmn9_Ei4uaj56g7YPTIFJF7VLV1af5xf8QfnsDnstmXejfIfq59k6H8-jJKrYbQ3Yue58qTin0wgUOKkPUmq0hml7BeQCykConuV33wV8Y0pJcPkTo69ufeaB8q8t-6xx78-mYNJWLM1KjXLLwqoG6Qqs0-CaASLVYJL7oVFZBpzD1FM8M4h_1d4YC9-_g22ilzm2wu2Z_EHaTOn184oiIpjg80umDtGoNgDejcAb9R8gdnI5SbLo-ianC52UO4piD1DheYurE0sDIuTbbnGgT03q4xtu3xxi-olmPScr3CHvH3mt8wWgjwRGIUgH71yoT0dvPUq6APmqOz_FAMLhFws8rMFaYLzoyzO3knSdwVkNyBqrzapRtP4DiD2pzx8w7mHI6bEpc7zMJZquJ6ksM8g9k","sig":"909df887f9f6ff688a919d16cf49a9cfc542c70e57676a663baa020aa10a28ae01d39aadf79b9ead4ef0f9a95e6af8205ca371b928f2dc498ff5f3b184d75e97"}
|
||||
{"kind":38501,"id":"73b2e63fc89ae708f89d2d355cffebcdd5bbfcea39da46e6410b408f8b9fe2b9","pubkey":"45ac97d8c6b2896d43dbc903105ad722548ff1b986269654ebdc0228ffed4bb3","created_at":1785676888,"tags":[["d","btf-descriptor-2"]],"content":"{\"created\":1785676888,\"enc\":\"3d7e99d510750b3af7b20e45c2116c88f2fca84c5147f3c839a83b4be80a982f\",\"meeting_node\":\"92.246.128.180:8434\",\"pubkey\":\"45ac97d8c6b2896d43dbc903105ad722548ff1b986269654ebdc0228ffed4bb3\",\"sig\":\"a32af8b0a024dc7a67fa881041ccd4f1c50bcd600d7e8bdac5aadc143a3c2fbeca6ba616ded91df6e92d3669cc8f8114a15778786293e1822f8b6f99867efb55\",\"v\":2}","sig":"b00356fe4f3371d47d3348ca1d5d8d66b92da75ee8f3fe7799fb5744127fa4a76758a97db7bee777b30d4da3e710d6497009e6f9775275ac516f3dbe3cd52830"}
|
||||
{"kind":30078,"id":"769fffcd14f4044105b49e1233169861c48eee0f156e70a0d3c5bbe4dce4caee","pubkey":"45ac97d8c6b2896d43dbc903105ad722548ff1b986269654ebdc0228ffed4bb3","created_at":1785676888,"tags":[["d","bitflash-mainnet-2"],["t","bitflash-mainnet-2"]],"content":"82.67.0.226:8433","sig":"60557df1a6c814e0f815d5cd4d5e8285e7e5a724080af10b5ab0ae382e70a42e1e6af0a9ecf62cbba4e0ba8ff60ef16f485be5ffdc2ee809b7769799a0465a11"}
|
||||
{"kind":445,"id":"1cb1e652eee8d63d61792139730edae9141329d91c37afb61b6cd5cc3c2cfa27","pubkey":"6bf7822615d8091f8d5b76879cf8e8bef5f20b2a73d81e36bc06bb5b4d5e3034","created_at":1785676878,"tags":[["h","8c3f1c25eefc49fb83a272a826d5a36235381ffdd1ba0c7fa4d774f0c7f1b55b"],["encoding","base64"]],"content":"Ygn9YOUc48RIHWWOgepFIxy0yRbxXB1LWu3Md/RE8sbwnnF50ijaMTQTiVCxlb5s6dITCwpFaz4oPOHIwre/vn4Se9+WXFA2sgl9iNAanzh4ltnzP1c9mG6zQtZRRSYyvCBtBrsAx333eiOKMzSPFov9QqCK0F9Pwz+5Ee3CQpVC/hJfmo0vz4RHOe6WvxW4tjPbGFVd5PrMqeGv8xtMKlAYDdKZIXmRPySxllV7+zH17sN56eRITT/6zRq0enPORGqIAsgQqIZOSe652mRyOqkvkaJ9sxv3IyEb/u8gnZ9sdOuSQs1iRAGQgvLoCKBoTqoIAqMZT6YL/NjhuQ0NzZVZLXJwggfM7rBlv3F0Ad0MgRO6HMpSXxyxKSW1T0/+rgxcvNV7Q3DNOEMOPugCyfmrKboLIHfBSTyFgKdrQ6gZZtwUA72TgGLQctXjCzXwudG+n/q2s1KAItcmG6BpxiqQYAi7iw+fOivUwz41ra8x0hpZEVbU6K9wHwpjhN9tcqq+j6ALdjkFdnffRCMUMXB5GjLubaTdA4MCWZvEGdM5YACnmcCNhTMJMvLzurm3d1+8V/wwQvsIiYIYoa6Ph/ZoXvvE6P/Pvmrg+mARugiS3rSPyE7wZDcTXrhC/gGzBJdLrTW1hDgse5QFh+/m21O0eWJFweOnZSBWYkgDotuyAhzInsHZ4Lh3KtCMnAV/O12j5R78VtwwZHrT4nnejtenNxzIcwmSNpn10kTalHPYWOw=","sig":"a7d756444139f09ebb1c69c38cbd76787d6a2d9d30a2262853f017c78420177fc40307d803b7fe4f472332cfa312f0e0549da0d258648ea58c3792905a2ea05c"}
|
||||
{"kind":7,"id":"7db435801117613a1eeffa3eaf68a9fc51fbade2951f16b7ddfa0b44ea367113","pubkey":"21c1a52506a343d12c34c0a434f7c6cda276a609ee51a0a02533febf0c84fb3a","created_at":1785676832,"tags":[["e","0000352da8dcd26bb6cbbada87e4ad466090ee86caa2e1a039eb7ee7d9b5a415"],["p","40b9c85fffeafc1cadf8c30a4e5c88660ff6e4971a0dc723d5ab674b5e61b451"],["k","1"]],"content":"😂","sig":"865e4ddde04a31a03dd07c7f3db1f87a87dee1057d60497b9f234b1f5d4d2919fe2db33b8810b8a0f557e5fb7bcde1fd2cb3a87336857f7e24333250b3a674a6"}
|
||||
{"kind":22749,"id":"e1abe91e8827ce0b42b55440d14182531ec10413503e0f0df44bf6ffb1d2ce77","pubkey":"38879d5f7d6ca197f5a43f4043cde208002391eda3d7a66529cc29f95754fb5f","created_at":1785676832,"tags":[["x","14305u172l2k3a2wn1e103y5j6k5v4q69c214a"]],"content":"{\"peerId\":\"hMQ2j8o62EZB1aaiWa0D\"}","sig":"d2a05f9d679f36d1ad95b172ec7343e42f26225621e2a05e8ae79cdd779bec6b0800a74165c66bfc6b3af283a1e1f833890ac87301b15188cd7d6775f86e5805"}
|
||||
{"kind":21059,"id":"ffc75a95b53a380a2de1114ecfa1426c080d5908df48fc66ce209c429ec8d4d3","pubkey":"a249d052bdf16251537b47555586389c8090db4a08687811edfb8a5dbe574044","created_at":1785676831,"tags":[["p","32a6df90883d1d026ce75ca91bfed54353fd2feb9e9f7329f7a94cb467037b05"],["expiration","1785676951"]],"content":"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","sig":"8a6d018e1563b415ed70a13ebd5adf1fe2ee36f92006c570bcfffa198646314280f07fa6788801ce809fcf8e8b5470f629f836076ba19d30600eb273ffbfc542"}
|
||||
{"kind":21059,"id":"518b7655489f9339f73a7d4cc9013b817e731288dea4b45d2e5eb6485f438489","pubkey":"7b353d5d4669607809fdc4e22690fe19e068912e0aa67c5d83c65ed12803e7e7","created_at":1785676831,"tags":[["p","32a6df90883d1d026ce75ca91bfed54353fd2feb9e9f7329f7a94cb467037b05"],["expiration","1785676935"]],"content":"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","sig":"c7c4162fc010944e98390ba22f03d2027dc635c2ec5bc52501d43cec6bc2bd78bd515de180b5586d961d9dc8b374e29597b548c28376b018b8264e28c3860f6a"}
|
||||
{"kind":21059,"id":"5e8ffd1a6c5f869a3a04aef3bc0cb701930c4348110ba8d52ff0549c0f463d58","pubkey":"79e0b421158103026cfd58b00ed88d52fea107e5974f419879d80a5b7ce3d40a","created_at":1785676831,"tags":[["p","32a6df90883d1d026ce75ca91bfed54353fd2feb9e9f7329f7a94cb467037b05"],["expiration","1785676951"]],"content":"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","sig":"bc53226df7c6b32d70168c939b2f810791493f408f365d779e652ab9cf9a88203b25b8d2f40d12ffa29e90101528de9078be4a146317b1ea1ccd80b56af6022a"}
|
||||
{"kind":38501,"id":"1a8b39de152c04c4cf7d46e9ecd4b05d718cc83f8c283e89c920b5ef91a72a81","pubkey":"bb4f1716ebb55c0cc2759c6ec70be71884486568237be5b0a24fb94b87ab0d5a","created_at":1785676831,"tags":[["d","btf-descriptor-2"]],"content":"{\"created\":1785676831,\"enc\":\"d395724b1f1d6cec4f76cb341404015ace916a410ce93993358b6ee568051329\",\"meeting_node\":\"92.246.128.180:8434\",\"pubkey\":\"bb4f1716ebb55c0cc2759c6ec70be71884486568237be5b0a24fb94b87ab0d5a\",\"sig\":\"56006b2ad9357724b0848a25f049343e59177e414550d609a1970900b80fe679335e7fbf09503d5581513676daed140d68313c6d6f0efd075e9b2cd4ca52d8cb\",\"v\":2}","sig":"111a08e451e1733ecbf6fa8e89ad9bff22f9e49bb5059688cdb741db58851656143013b8ee33fe0668e13ff5bc2348764631bad217da59d26ab82775002ab9e5"}
|
||||
{"kind":21059,"id":"1fa1cc7fb9b195dfb7bb587649e1f57a13c22a716d5b6b7ad1eaa35f3682ba36","pubkey":"df37a8e8a754e2aa7c61085a67f70c11c548381b45f6bfa45c1fe4fc6a05d60f","created_at":1785676831,"tags":[["p","9131564f29a6caa4884f5dc2bc7f2f37cf9f9f3ea79eac6cbee56f23faacfdc4"],["expiration","1785676951"]],"content":"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","sig":"b4f89cad58ddb2840fce5d18b59703412e7781d721482486e53c10a540ca6bb91266bd747ee03301cc4bc638838c2f8e1d19aeb7959597ad3a9c667c808e52a1"}
|
||||
{"kind":21059,"id":"c6a07a7a6c5efe9492211f5c7ac91af555b672564450a29a13d6c4d480da58e5","pubkey":"33f9b8d989cc0db6caa5503b2e59a174550054c8eb93688641d71371ae305338","created_at":1785676831,"tags":[["p","605e6516fc17fab93c5e1c66534b5d4a8a2b3de64942c3ed742b51626d267cf5"],["expiration","1785676945"]],"content":"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","sig":"291c834d1ba72b4cc0830e8f69bc4a07cee371fdfdad2466d1cfc6cc69b4866cf5e3895ebdfdc43255320a9473423f83f1a2c92d37d7e9acf51e46e344a6e814"}
|
||||
{"kind":21059,"id":"0f9efae4bd3dc697c547733b74c1c0b2f36c17a14031ad3f9257e35ce8c11d18","pubkey":"a6b8b3720e7a311904a9d6d5ddfcacedd7e0a70654bd41c043072de6f53f8107","created_at":1785676831,"tags":[["p","4f8e06e55adc2dff717adbde066c79a192468858816257c8c717dcaa8d51a28e"],["expiration","1785676951"]],"content":"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","sig":"70c6036ef7b66b2954d3ac4a944f8c5234bad1b37b43a50cfd947fe8e984e0cbf91b3ac51b17aa8babcfadfbd27affe5dee578c36103a9660290e7aabcc814b8"}
|
||||
{"kind":21059,"id":"233787bfae7c7d89e6d09ee4d1348e59be138204edec57ab399abed267e9ad43","pubkey":"38cd9712528928a6b85f526abf6613917c52c636608e1f7411b33ee457d5bc4b","created_at":1785676831,"tags":[["p","7b938b906ad984ea438f8af5e464ae3c2fcca4acefcfadbe7a3d66a7a69212c0"],["expiration","1785676951"]],"content":"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","sig":"e7894c60e30fdbcb92032f6e2a80090b2474996796771becec02a2e1af748f3c893b113cc6ab197b6fadeceb10805fcdba74ec43617cb665199ebad82209a2d4"}
|
||||
{"kind":21059,"id":"f22714bcb70a4b41ffd4712f8e5764a0d6bd3af78f6107134932bf8531f52621","pubkey":"fbae19b87545bf7615aeb74ac04cf926a50bf332f3b8c2a0aa5f4c877d36e351","created_at":1785676831,"tags":[["p","fc62a3263abf4a39c09a7b7064aa40480788f868b653c66dc6e3a32c6880a506"],["expiration","1785676951"]],"content":"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","sig":"69949c1cb10548c9a991212c50390aff75777fa2eaf5f979c23f7e031d48fbd0202b7882248552330464dccd8fdd089b613e46e343e540ea49c111005da39d01"}
|
||||
{"kind":21059,"id":"83cd0f7e4b2e434807599c79a7f0549266bd37f0b91847b0c1cc9681417c9041","pubkey":"b6b05517cc607db1425e192c3ced2df864b46000526d5f50e47b74d25c99436a","created_at":1785676831,"tags":[["p","08e99116ad58c5aa5e6e7dc40668d5d7f2c080fc9fd697ec0aeb76880cf54bd9"],["expiration","1785676951"]],"content":"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","sig":"466fcb9413f41abf5337adc2032829603aed33963cdaa304cdf5522bd45b59905298465515310b00588aea216c0aa3249618d60e907a19363bf84bddac67cd25"}
|
||||
{"kind":21059,"id":"0afb26e3a41a100c304aedc5b80548e679da585e4af81391b7e0196f5eb694ee","pubkey":"d66b7344ecf950b1261dd49de99deea8b325f038dcc1ed9e436b57f9fccefbe3","created_at":1785676831,"tags":[["p","fde8ca9b4a9d1f5d2ed8b82ea13766c37bdbf6cb50bd272d642eaeacc713563d"],["expiration","1785676951"]],"content":"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","sig":"6e8c0633ec51e9d5663a865754116c27582180150f5eb7581570cef47b58449b79315c1623c2684eb4075f46120cdcdecf7fcdd59e57181132e754be7fd8d4de"}
|
||||
{"kind":21059,"id":"eea2139089ca939ab3e858c7c626609fe629f4dec943497e0aa8bc5c49d13b78","pubkey":"71654ee31d04384b529f095a9cca21b58530ab86c35e239257ae5a6b86b1f70c","created_at":1785676831,"tags":[["p","5376ff74b7bb5a5c9e97cb60a1d068dbdbc5ec39c4346156335747b776ec6d84"],["expiration","1785676951"]],"content":"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","sig":"e03f0a94db48468a6a07bd0ae0a9792c4752f3d498497bbbb3b6fb1873bcea3ba8f2d08efd7e2ca67928a5183f3bf9361699785adbad273a1da60c58cbbd31d7"}
|
||||
{"kind":10002,"id":"0ff496f20a3bc170afc15a4141498259c26fb487702ba35b9260a96b7b5ba0bb","pubkey":"0000521bbc284afcbc646771c0fda5b1a839a0d3cd7b6f4fe2eda9be15ecbc6b","created_at":1785676831,"tags":[["r","wss://relay.damus.io"],["r","wss://relay.mostro.network"],["r","wss://nos.lol"]],"content":"","sig":"111925db0e99748aedfae54d2442ea8053130095695c5cecf798f3d34cd4039afc4b41662ee128fde49e3c3d517523fe8a828b21d31033c7f4d264e43c2ed35a"}
|
||||
{"kind":21059,"id":"7f897e9c805c499c963dd8999caf3645b5c6aa968568d5f37462ab8659e41853","pubkey":"6e7e9c51e2739dafb6348212fbf48fb6d768002b018125c8cfbbadfe70b37dd6","created_at":1785676831,"tags":[["p","aaf802c63614f6028fca31eedc3d0021bc3320fc95d0e3af5ddf8e7cae871472"],["expiration","1785676951"]],"content":"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","sig":"24b691e5868fdfa5546625783063d68c5d6bd412e389851e5555bb15b4c6aff3251474fa3580501b8cce93e9711a982dc2f1e7da6ae167ddf459ffec1af0d94f"}
|
||||
{"kind":21059,"id":"ee1cdd05723f5a6ef4ad3caf9db988f33f9a2921a82cce6f7a24158218ab38ec","pubkey":"755a026b88668c9ce69857b49983a95039dd7689739acabc169a21315ee04783","created_at":1785676831,"tags":[["p","e15d56d1b0ca49d50a4f71cbf04774ae606c4632ad7752195ff9b80c5574e0b3"],["expiration","1785676951"]],"content":"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","sig":"0f74f06f1c14373856bac66f45fbef85bb774aa1e6a7ef82ee821c5dd81b3d32a6666b815d2b53613fb28d7eb63b7a6859c15dcc9ee6b67930ecfa086b10ded8"}
|
||||
{"kind":22653,"id":"35b97981fe7f50b3f20cae1277b4861b9fa3d49ee7dc7acb8da9d45c1287399e","pubkey":"146c70d40e1f4f96528309629258f8dc97e9a61aa53e54e13b999ba5d2276968","created_at":1785676831,"tags":[["x","1w3v3i5c503a1e531y6b136q2s5466t39322o4"]],"content":"{\"peerId\":\"9IVDCiG4hlib9t5iG017\",\"offer\":{\"type\":\"offer\",\"sdp\":\"180,27,136,119,41,56,194,227,43,3,188,67,19,22,123,115$ZeuNQlPcrzNPMpEycw20kbmWmAQ9LQA2e4EBLwCM4jl3ajWwnnK7utcxXmapzWDz2xsFhpNRr1jg81viwHLkwzGfOHC4/0o7KKF5Jl4TnLLwSj8g6oToW1FNupDZeu9NkaY0j8JEJCU/G9iTJ/mnnTFSyMZUY9Y3AB5v9+uk+uBij+wmOk1Q4CBDPScFZll2oBNoq/GhlUP9BqhSavsUerOnATJMjqzcMT1m8pZYe8RV5KnCDn6YnSaIlje9LmePx1qMBQBWugymQGuaX5OufdXkvabgjXBMkoj2X1/I9KbAsNGWU2ePqgfGhYXO2IrpEuqwsyiYn9UaZN+RI5v6c847DIpLpVo12xlDg+gog8L1ueTawBSBLazJmCytxqvLROFKCv0EctnbbMKpGu79nsa8NPYcp6c5BVaYFZgWbDxHaEJx2vz85n4STQ8OhjyvA003IwSrE60SUu78URUKA9SXTQoQMbu7H9Uc3+JukT4W3wCMOiMgnJNqQYvYgr2+HJ5EFWLEyD8dlnmI838FJGwnHl05fkAv5vHmdT1Eyrbbstlrn9wrSEmla5mq3cf4lLSkb+06a4D47/j3QBrtfREhnc31O/+XCzhGYZKs5HajWQF3YVW3Md9nHCGFe+yYplq5pCe6HlVSbooXQsYuYyHH8BmfdZCA+Jkrhfbasr+MKTXvvR1ARfXuddxvOjuxk9uQbIN+k1eJmnlyzxODDhMi7gJmQeOpudYWlcquuPhSYHBzKlPs15ibSr/+/Ki/upX0+AZCywGZEyPQE5MYYD6jGoX1SyoZ4jIfl8Xw6oTOTJ+esJc9Ub5LQNBNLUhU8Lh5lxw4LPkZpnepAfyGno1BbrN6V5gg3LA+aoD8pQY8DajozXQX3OWTCu8CGZTu/RXK/VCEnUykrfYaXBU+88+F+3xAxS38G1jdek7VmAMqlfxGY/21roM4zVKahtTJTSZBDK6RtK60tZffGkxOugNHGTY6+DbOAa+NfLg2GWsSkcXSStUmCzFQbql5p4g8FiiO/3udMNlqIx1nxX0DWclYGgHi4DGJw7E/wyuXn7324Tvw/UjVQvm5fHVLc7LnClr//dsQArzagNjdIolCSC+pnI/EUkWAFVwcnwu5RpcPam6c6ZtLkXPhB0bK15vdRY4QUKLNSm0kGDDs3HC6/xi6oZQgF6j49ziOGeV5YYS42XVk41mZG4cGqX9R1EWGd4ZQFiWyRXNLttaMol2CJTQ+yJC1DYjD2N793qoMRuzLVXStld6436buBHJrqL4Wzywzi6eS6ANXyX4jqKxQlXOl9nTxCQ==\"}}","sig":"849aeadaa749a4d431cb91f8a282ac09b9fb322872ff0895430f978ee69108deb02f0cbd323a4b0a92148d4014d8bc8c503e22f9b05569d7d751824737661f9a"}
|
||||
{"kind":22842,"id":"a497bc4e9330b78979645581cb7422c54b64d990b295d18fb965c15c8b28e0e4","pubkey":"146c70d40e1f4f96528309629258f8dc97e9a61aa53e54e13b999ba5d2276968","created_at":1785676831,"tags":[["x","3b47662o2j5h6w4431116d4l6k6z6z2o3s2tk51"]],"content":"{\"peerId\":\"9IVDCiG4hlib9t5iG017\",\"offer\":{\"type\":\"offer\",\"sdp\":\"167,11,114,204,116,88,224,166,141,164,164,64,134,197,97,18$zMoeDUlzCvWcmm9Mn8HB1tuqvdDd4BvM3uJBCzwaUKQ0gnUWY+HmKkpaABQex/UCuKjf0fdsRr7SHE3MQ2j4vbSabKo+LD9mdyeQt1vDGpiu1uWbq/Em0HVEEWxTTTAuySuo/cV34xa4On1Ju8LjUaaF2+Bf5udktCf+/EzzVZmGWlyWqbMmw1mg1D3UcSsye2IBiD0FpjDzRiqsweHRoqfESL6XuL5XZ1ka2oipiN4t3DtkIf+QncvSElMm4lxyOnqDR2HDcuQuJKsi9NtuXbZoyJ+rgdfbHAmKsT1hrywjk08aBI56JBUQvVv1ClKq5gRplDRscxlj4CYeksMayW8cHjxqchUEtPdqzOvvjbS/fS1hzEwplaQbYqkEINUSxCx0llT5023uwSMcZXFuPPzEpuu9L91zI1EwBYIjpIeUti2bDG+RtseCcdp8TQh6Ygwqc8Ne5HDzYQHrWqEQRSuurZp/w7+tES8NlAAmPSCPoPLyyKG57uvaWKysmRr3bL1jPdVS+Wqo0WbUMvrS6xEwYle1qvnK/6bP3JeaMhnriq6xTJiMDBplL21vOC7qwvA+sQgu/R/w7q3qcYFre9HbXipFTWY4x8QOGv/JMAf9YSSHmDYUsIKt0Rh3Ow6AJhJjC4bjem6QKpuznLwwRlWcv0sJaF0LtibH/z2bwKs6Q4OozajwS3aJ9YupJT1NcNBOdf0+9R3zZEENOghm8mbLIN0YIkSZXepR/gzn8D7fAt3Bh7gihZvZHReMytPWL3Hjoev30HO8ehBLGbJrpe+gkoxsnbU/zQT40ucy3Vp1KlbOCd7aGGSKqWvlFxbz+EraunwiLtp6gqML257CdGa03iZFKu9joOS98uSzUf3CRn9A28cbgHPvLTQ4UYj00TBb8v04uW6Kv1s0VCm0kZDt1V6moMlFGXu592B6I0aDBkWEr6/uKX1UymIsRBm3Wj5oWXVf8VEvDOYExMFJtHmUJg/z3/KUJASjoX+LAENQO8k28vlWh8b41YTVkA3sB06SZIRGoCVXcEs6+IJgqvuLv58OvZrfK20gSdGEeYdEWwy+w+4zJeaL3OZNbDJZIHCBRRvruSqiXG0OdKT2QnknrJ9otReAc/mN8E4wPwciDUsKV4278gWSZrFWuIPERcf7xxwmbxc/gXCE2bf84V+khN2YH15WtGBDErRNAbVfEwQdrAYzyGKiy3CaoxIIbOn/wR6WPFnImdzMlT2zcIlhLgTHCGo+5186vOk1M/AWsUyah36Pf0eQW3aCtb/nweENd/aGWqSaFzX+L4BHYuKSsT7stFc=\"}}","sig":"5358909a435dd89d34a1e61e94e5294945eb1eb021242dac22067aac7f0652228d9b4a7793a2b9956f879d41cbe70793eb2ff79088470ee3b6af3b01e99d136b"}
|
||||
{"kind":5,"id":"6e783cf2000cb5793a94ae2b09162e1d3f1304be6eb7c774b852e66b59fd521d","pubkey":"1ec71c39a30373cbb10e91d6efa6ef1e9dad0756d610c1a4e337df016eeaaff8","created_at":1785676831,"tags":[["e","1f4d0d3d55c0fd387950ea4e0de7e973457039bfb03b824cc71b13bbcd39f293"],["e","3aed713425ab4a0459176d4ba589876e6a313d879fad18152a11347c22c1114a"]],"content":"","sig":"8bbc6c7ee40ccec7f402c48a5230f71bad3240599ab841e46a3e155841953edc52de47f96fd5b4dd35f8f784e1cc4fc9062303395d6d049d2c78744bb5c176ef"}
|
||||
{"kind":5,"id":"df31df8ea137659a43641ec7aa14f85f6935907ae71e0ac42d5196f1c7f3022a","pubkey":"a6cd35843a1471debb1b174b5bab472d9f5a2e2391e92207c2279468c3e9ac9d","created_at":1785676831,"tags":[["e","3aed713425ab4a0459176d4ba589876e6a313d879fad18152a11347c22c1114a"]],"content":"","sig":"fcbe7b0f5cf5fe044cd295ce6ae5970ca9bcea40e0584b212c027426a1721c3f15c60e387b6f390c7568e7c68e6153512302fc3898a27b0094c2062409788dbb"}
|
||||
{"kind":21059,"id":"bb18168cfcd10c7cfec63ae32e39d5c01ff248531c05ed8d42851751c56a8c85","pubkey":"99f289641b017b67d71e948bad494b63bcd016724e95e425bba176bc8cc03cd3","created_at":1785676831,"tags":[["p","29d1d9e11edbdbf04538d90d053b7b2d32c1c253fc3df1893c11b68826630609"],["expiration","1785676951"]],"content":"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","sig":"3504f1566dc03ab9fc19e597da5baf4a3734fdcb2f7a24316d0a5f43c37bfcd54e6f9bd1d4a0d8960d1ab5d38d77d7078ee990a2c874db0960300731266e1937"}
|
||||
{"kind":31991,"id":"f8a2a8a05db114a7096435a285c45498846a0306d9538e7362b9c9665032b6db","pubkey":"537f2bbfdce17c83ee7338dc26229edd9b26226a2f258b578f91f4213611afc3","created_at":1785676831,"tags":[["d","537f2bbf-v1"],["s","available"],["L","agent-reach"],["l","heartbeat","agent-reach"]],"content":"{\"status\":\"available\"}","sig":"09a021823e02d5c2ae3ddda7d05c22e05033012645617cdd6313b5b425b491cc32c61d849d704c7cd9ff294c757d8e0ff26d553f457cd3d7e26c158a2651552c"}
|
||||
{"kind":22543,"id":"75e596503238aa0f8c242cdb2011667c813515e0f02b006c34026105f67dc2c6","pubkey":"146c70d40e1f4f96528309629258f8dc97e9a61aa53e54e13b999ba5d2276968","created_at":1785676831,"tags":[["x","456a1r2o456h222f3g036k594s5x2333l2v45"]],"content":"{\"peerId\":\"9IVDCiG4hlib9t5iG017\",\"offer\":{\"type\":\"offer\",\"sdp\":\"36,99,139,51,68,73,226,255,159,72,228,209,82,242,77,19$m/DD2pfpEe+VV4XvRyouNbCVzG2hxkrSt+3zBRI1H8ihRyklrKo5mkvQvvG97YeFy79GxjZhneAlrf1ZzwSoxO/KsE7AtZiuYI/onBlne1ueaqNZca0ZLs/eVvLA3nksV0gf4IMc8g7zJ/IXHGK+9Ha2cSW81dPPlnIsL/7DPyzvtOTpTqENqXYwkpOe5yYa/lOhEF7XNWHDcJCiDonINlMc9JFvXqd+rXlBmrXMsI2De1l4EPGHAk0hnY04uLbpE9j2AFHNMU7JaLLfYyAB2hL4GEjxCqGXuCETm+oJ6hGfsmMeF1dHFfVj+JqsVZAy+pWYr81I5F8xzzhIuLI1DN0mmC0hVV+dDTQw9AzNSoSR/ANICZxkDD6OLeepNkhLZ/h7p5sd/ue5BWONH7mBtKFZ84e1c/OTwJyteTPTokoifMWS3AS1CLAau6Uy6QFXtFz/WhmtVj5MQ1axmzM9asKaJghl4dOi7ScPYLXTluWuAJH9azpjrw9qL4PR9nJG6chRoJAbkRYAodXhT5LmVe64CyWS8GDrAjGOgqY5rmWMJQJgjPJEFVh7xX5yP6tok8z/7K53Rj2XtsCXE5yM+7WI1/l/GSv0Pv7A5LRt/8mndt7tUtg2ez8UyfFsnuZDzPlWwkWCO3jLHLSPvLxYK+X6CiPHKqcZDuvGqNQUTYC0kT0Dhv7ZBPZvVDYgvooA9KgPYT2J1um0MPctIgIzk9TmXCT845IL4aKWOwwMPFkiHc49btdDzCPmEJ9IAI++yUb1QYcnXRhe02jcMcj2t8x9Bmdu4cW7c9syePqWYpytfgsAhCnbT9gfqOoLkrPxmvNP86lbTYLq1KcFFIYIqOrG5dmV6kQQlvbzQbaP+zIk1I3ACOh2KYd1CZpE2FiSPZ9yq7dZ5LZdKd38tM75/LPDQwrLNKvg/yvm5CAMXWNpEeCSfLYUvhSKmFgYVlBLd1aUODOma7pWuRH9A+3V2Sg3rqn3ux6yHASkqvVZN5zQZ38lwvHgfc2SsoB5OkAXwAKPKC7YajsoU9p3VNHvdf6vfL12udGeFODqGqcKbTHTMJC4Q/U4/Ch40HMFbnWdTIK7+Cr4bdQVsML5kUNEqxFSoIO1mcADBxXFP4rIG/tB9GzyQZjmSHJ3bnKvBtvVih+vZZMju8cxrFtW5qedAcDw2qJhhN0dkDRQPOdbq7KkgPktbqe/j1D7NbetdGH7qJ4eeCVb4W7MZkWoNJdXCII16vh8Wv6nzZBK2ItYyY+sKGv0LHR/g76c33zyNzkGOV6AeKb8/wMHfrq1/cqut2T9E8vAPLU=\"}}","sig":"e8418147619db01eacb6f22e5d363226a5b650b2df0b2facb3c33b8c93951c08d63f76a2441beac1facb213e569ce0ba3675907d8d2348d9f1631b568aaa6584"}
|
||||
{"kind":22668,"id":"d05164ec247e35c2dccc14ae8700bcbcf5355d1f9fb589b97939d37f97f7b4ad","pubkey":"c938fb345106fb08fe6680f7bbc7b2e635967c636e763f6579accb3d0627ca73","created_at":1785676830,"tags":[["x","3h4b5840o6s3o6aq23294k3l3u32544u3s7266"]],"content":"{\"peerId\":\"LE1qO6qizx5jMA2erFhj\"}","sig":"708e7d3c91e43ab8f65630208c294307d2a0472ce5c8e57cc6ba0d548dec4a0ad6ca5858b5de1f98bf52ad7f9c5ff86b61b2c80775edad0a8e251d24d1f0c9ee"}
|
||||
{"kind":22668,"id":"f10a1eaab979692852318eade7c2fcf8ba3cec9f659867011647580bea0bcd99","pubkey":"129614faaeaf11f6606d45e39a591fd02f1a3d297cf5911c39a007c7c7f3cedd","created_at":1785676830,"tags":[["x","3h4b5840o6s3o6aq23294k3l3u32544u3s7266"]],"content":"{\"peerId\":\"ZZEfCmLfVXsZXTgS8Wil\"}","sig":"fc92eda249f298ad247000192e68a7260e25ee237429cfec40245d4c674568b6938bd9a3ee9795a432fe81e5565425802a037f2bbaeb66d83d46977c968021ea"}
|
||||
{"kind":9735,"id":"80ef4548d68d36095f62d0c6081b02a021fff27d628262cf4bfce334f8dee039","pubkey":"be1d89794bf92de5dd64c1e60f6a2c70c140abac9932418fee30c5c637fe9479","created_at":1785676830,"tags":[["p","e4146d1d7fb2f7f6e6b3c799eaeaba6f7446fd28ccea2592671cb239a13f4d81"],["bolt11","lnbc100n1p4x73qupp563fjv7p2j9qlh4cmkqhty5808avtjhxvr90mc4rhqxtpfyly8ysqhp5qq5hwkrnpgm97lt4sfh7gt82ccspge9mvwjrr45y9ej6a80tsnmscqzzsxqyz5vqsp59kuq05evhglk4j8efpcklc78pudrs3tux6slfjjnk2pzdgam343s9qxpqysgq25yxnew6a0humrzhg4fym7xtrxy8f4s23vfjert7wq4rkp88pf8qhe9kpagpt9qaf37w0z3ugfnjeqg2pqew0y2keythw36l6f36t5cqvu99dn"],["description","{\"kind\":9734,\"content\":\"⚡ AQSTR Reward: Btcnews earned 10 sats for like\",\"pubkey\":\"6c27a5aa02b769c6b51fd7edd80c5b21b9ba32c16d913b2bc8e1617fb4573680\",\"created_at\":1785676828,\"tags\":[[\"relays\",\"wss://relay.bullishbounty.com\",\"wss://relay.damus.io\",\"wss://relay.nostr.band\",\"wss://relay.primal.net\",\"wss://buzzbot-relay.bullishbounty.com\",\"wss://at.nostrworks.com\",\"wss://nos.lol\",\"wss://libretechsystems.nostr1.com\",\"wss://btc.klendazu.com\",\"wss://nostr-pub.wellorder.net\",\"wss://nostr.bitcoiner.social\",\"wss://knostr.neutrine.com\",\"wss://nostr-verif.slothy.win\",\"wss://nostr.cercatrova.me\",\"wss://nostr.einundzwanzig.space\",\"wss://nostr.wine\",\"wss://relay.westernbtc.com\",\"wss://nostr.roundrockbitcoiners.com\",\"wss://nostr.land\",\"wss://nostr.mom\",\"wss://purplepag.es\",\"wss://relay.lexingtonbitcoin.org\",\"wss://relay.snort.social\",\"wss://nostr.semisol.dev\"],[\"amount\",\"10000\"],[\"lnurl\",\"spritebeet37@walletofsatoshi.com\"],[\"p\",\"e4146d1d7fb2f7f6e6b3c799eaeaba6f7446fd28ccea2592671cb239a13f4d81\"]],\"id\":\"6e64b14ed5da47c6d4ee3caf4649dba7e9259ff2173fe9a092d46f838dcb4984\",\"sig\":\"08396838f0645989cba3c7ac753aa5a39cd7ea113ce588f4ca39b1061f1c17cfed46206b91545912de5470ee556d08fb2218f34593cc8abc2f7e317961407dde\"}"],["preimage","833bb4c5c573dfe24cea6306294aec8ee1bcf903c4b1af0af174aab14bbe91ae"]],"content":"","sig":"64460054919c2703eac063ff7dd4807610f123dfa6a3a5c838e87ca7686e9d8c697f5f135dbd4088d1688caf0f79869603b80ccca2b6c7a8f32d6622554d8651"}
|
||||
{"kind":22668,"id":"e93ca07e3919f3f216dcf0a2e0a96a016840eebf41e5fd706773903af39c84e8","pubkey":"dcb7a55095f3761726ad6d5a53209c3ac46cf9be9c8e5013313fce6de948ee33","created_at":1785676830,"tags":[["x","3h4b5840o6s3o6aq23294k3l3u32544u3s7266"]],"content":"{\"peerId\":\"qLShkXb42nycV1mZOj3N\"}","sig":"de497859d5a80968957b9cf61624e6ac7451d71249cca0a3f2945e888453946aaaf1d42844ab01e620f27c0c1f612d8eea41395449b4354def8eb6f1db91997a"}
|
||||
{"kind":21059,"id":"6275550f617b1e838bb333227f5567e49c5039508ca2fbe67392df600352fc4a","pubkey":"b6e091b72c36a10e1b33f22e798bc2c497fddaf4334c8b90d9064cd40c969da5","created_at":1785676830,"tags":[["p","2e26907e7e535fadfdadbb3c5c2ca41f39c3f86a78143642fd0e435a4a6da6e4"],["expiration","1785676950"]],"content":"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","sig":"c80ff23a16b2aaa5607fd4930c15fc2b5dc99f5e56d4cb38e4f17d1322fd9f337eb2e82573fd6cf79f7dd1effb1facbed1b429cca561500052474979e5b87050"}
|
||||
{"kind":20004,"id":"a44cef5e7a3d808548ac3300b5b214d2307c957b1b02c106bce6988fe2a760e4","pubkey":"4e8ec641f5340254c1228c02d69995ca9246c7b3b0295328cd6ac418efbbd9fc","created_at":1785676830,"tags":[["p","04504ed6eed7a46e07b708e8805dcfc2189a49108e3f42ff1137d879f21b6824"]],"content":"zDcS1eEbhLUg6zfwDZ0vRCaLCfKkltMD0OL-e69jva-BPkKQrHIrpJITgSq36FBl-cTK9wyojnUUzld76_OJDBzin-8fJSU?iv=CZo2CiPoKnVD_9S8dF11mtAOomcyZYQn","sig":"cf941df89b47a2144d2650a8c6313c976845e42d856136be7e932ddb5de816eb84ccc725f9237aa4f0a6d46f7148422bc8e956d133022bbe021ddf4f50a71fb9"}
|
||||
{"kind":21059,"id":"5d90f55f4d87f435f650e0da26e501e7d2376c74b56e259ab807ed3d89f4b313","pubkey":"90e84244c692310d3b93fde994d7a25112a00613f7e6ae8d18f141e66930ca8b","created_at":1785676830,"tags":[["p","08e99116ad58c5aa5e6e7dc40668d5d7f2c080fc9fd697ec0aeb76880cf54bd9"],["expiration","1785676950"]],"content":"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","sig":"c1ddfe11c41e265d28ad6787a6f81d5bcbcb0038367424bdf047c78dbd349bb375c6c4a758a89644faecaf94b56d8851da1006e7259a255a42cfd539268a5abc"}
|
||||
{"kind":1059,"id":"6293744ffa82db6aa84f749cf1a40f069297865f4f47e4b9fa998afdafc91d62","pubkey":"1ecbd9f1a29cf784475500f5bb060692c168beb8a73e7857b90ca4e9e39235ec","created_at":1785676830,"tags":[["p","15df570d3edadf50eefbe7d46ab9896356e52b7464774cfa865262f912cfd577"]],"content":"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","sig":"dc3abfc7a4d9a7689a82a945cd48dc7ea1f315254928111ec8a477f108fd28b59220c76377174082a5311790fbafd13d58018394399e28f6d949af95c4e59f25"}
|
||||
{"kind":21059,"id":"6b85fbd7cd052c7f39df3de5dfa3ab7959f2a7b2131c22c9f1d03b9f3d11cbcd","pubkey":"61612c62844bb7bb89a96d59667be268c8db7f5a6dc4dc1dc915769929704f93","created_at":1785676830,"tags":[["p","48092008b3f8aedbf147268ae9a191bfd003e97d3521f706d738494d55a05079"],["expiration","1785676950"]],"content":"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","sig":"0c74c118a80bca7ee3ba466eea0cd2ba45c1877f8cfce631185524e2a40b7bbea4f01fd2a4728c1ab4d503ec6d2b5d4438c74314ae18a7e506f7dd804f86f59a"}
|
||||
{"kind":5,"id":"e004071b98835065bd79466e9694e922eca9fcaf1a9699756da6ff7af1d50f9a","pubkey":"f32f0405b1976474d2eaa74ecd15c257dc7c5854e405996526023a7aef7f9ff0","created_at":1785676830,"tags":[["e","c3d841341e03f0f22b2e6e7cd0811954f7590ff69c785965c2afe1e91cc6558a"],["e","e7558455c28020c88895334d03cfa2567922e7010873686a5d988b73fdc412e1"]],"content":"","sig":"1931a895da1d66d643a2c3ea0e2d84f7c84b75be0c480f7900db9925ad0ad939efcf188d443ecfdf318649b5c5485cba9630d283a285416fc9b137153c4a52fe"}
|
||||
{"kind":13194,"id":"a3fe853699b7641349db48aaa2f100a6d3c1c4cff0f7d6fff89fc1647d6a2a32","pubkey":"d03ca1662e2bebb12d280299b09a07a9c77450b7c5b6eacb357e3bacde1e14b4","created_at":1785676830,"tags":[["p","d03ca1662e2bebb12d280299b09a07a9c77450b7c5b6eacb357e3bacde1e14b4"]],"content":"pay_invoice multi_pay_invoice make_invoice lookup_invoice list_transactions get_balance get_info","sig":"000f134426656ad3b8b5a4c4b1cd2a208bebf2392dee1763a339d76ebf4585d847ff8fdb0793fb8fd7aed2cca83a78ec21d57635447d353ba5c528a351974123"}
|
||||
{"kind":22668,"id":"c705e88ba63b117f281ef394600d2f33a03c72dd67c22b8517c689e00853d722","pubkey":"651ef346f974c18f3a781247a39ad0c1812f7817f52c3e1e48d09fb277c62751","created_at":1785676830,"tags":[["x","3h4b5840o6s3o6aq23294k3l3u32544u3s7266"]],"content":"{\"peerId\":\"gnZTneCwL6Qb5ZD4UewN\"}","sig":"85550bc17c5328cafd4f1172106e4e7af93122861b8ea3be462271b6747e64b5baaa6c952ad12c2f4d7160b6431aee4dd3df77e850b45212292816f1177c1a27"}
|
||||
{"kind":5,"id":"1e8a289daa492596bbe1d34fc8486cfda8f284883d0007599c21655e1ef7cb01","pubkey":"c3d2d513091f404497181534e7965d2b80da38f82ac76bdc8faa2ee9b20b7fe8","created_at":1785676830,"tags":[["e","b7e189df82207c6e3c837afe4900dbbcdbed7e8a962fb24bf3a9ddd2158729ab"]],"content":"","sig":"824d9bfa8b1860acb395c869895e1a950b8d067336265f28f164cfa11ba00dbf398913d00e2acde7f9ac4f81c34f13dec78394ad37376e916c28cd9df6574e60"}
|
||||
{"kind":5,"id":"504765ce365092825d7185424246b11b1b510ae68c663424a47117e64ce896f3","pubkey":"92e744f3d9e8ca5888da31ac871ef9eed2a0b198ba08f417937cbff3030b0000","created_at":1785676830,"tags":[["e","84780070c1d4646031d9d096b035b73fbc5f1c8e8cf88708b0ee5260dba22e86"],["e","b7e189df82207c6e3c837afe4900dbbcdbed7e8a962fb24bf3a9ddd2158729ab"]],"content":"","sig":"f15d8a5be186bee060ed55fb432679cfa829a5e28f7f142b4004d5ed3c5e06cebb8cea9813cea8c391b541131aac750e4c9c3d189451de67068dddf6ef946603"}
|
||||
{"kind":31990,"id":"b982613c77be9bd1202a48c630833a7949f07ee83fb76d879d4686af2704d8f3","pubkey":"867a67b1f464d9099e009e73f93ef6e5df8091be0b149bd38c85a88d29af7cf0","created_at":1785676830,"tags":[["l","hello"],["expiration","1785677130"]],"content":"","sig":"88bd7ab0d68817ee099e8d24673091a41f817f1f3c8bf849d2c91d672a35a3b191dfc52ddd485b889b6a6fe8c9654d95ba31591e32029f4490bbdd222526429c"}
|
||||
{"kind":22668,"id":"22af285ccb3f6287cdcf363ebb06b648add8ebdda93d4ad49a40330abf8250b2","pubkey":"f50ddc7a8ab4a5ae2abc2802f7e33afc40f32acc157c749665cd6b78454690a4","created_at":1785676830,"tags":[["x","3h4b5840o6s3o6aq23294k3l3u32544u3s7266"]],"content":"{\"peerId\":\"MUzRfOSvVHCPwAQ1zQlC\"}","sig":"77518b61f5756b7fcaccfd68a9c63164deea9558b0bf9fdab40d79fd9036b946848fc85241dbc797c11762d24b62265da569fcf91244c571cf2b070e53c8dbbf"}
|
||||
{"kind":37195,"id":"784c21c5b8d1ae8569d4b663711c9579bc92e6417daa76b160ce8fb764c7fae7","pubkey":"522bf69c8bcc74bcf6e8ba3dd4e2322fce057892ad9b9f81ce93f05e65ab7564","created_at":1785676830,"tags":[["d","iris-chat-device-sync-v1:fdacc68213faacb25010d10c2c6bf9770a3a6006696a8282c906c6bc538315e7"],["protocol","iris-chat-device-sync-v1:fdacc68213faacb25010d10c2c6bf9770a3a6006696a8282c906c6bc538315e7"],["version","1"],["expiration","1785676838"]],"content":"{\"identifier\":\"fips-overlay-v1\",\"version\":1,\"endpoints\":[{\"transport\":\"webrtc\",\"addr\":\"02522bf69c8bcc74bcf6e8ba3dd4e2322fce057892ad9b9f81ce93f05e65ab7564\"}]}","sig":"591246b446dadbe3a2067fd458b72edcd7db27fa9889b22a5b032137bcd14c814c8039041d7ebc1678bb73fc0b8baf5285e54ea09276db25ad1c713ac48c4ae4"}
|
||||
{"kind":22891,"id":"c4f37c58db11bd3c2d90196f859b88254d8953e85ea2e319b7367755c825ebe6","pubkey":"146c70d40e1f4f96528309629258f8dc97e9a61aa53e54e13b999ba5d2276968","created_at":1785676830,"tags":[["x","6y2v464t15574k2a276u1z5o2kw4m6i6d222e1a"]],"content":"{\"peerId\":\"9IVDCiG4hlib9t5iG017\",\"offer\":{\"type\":\"offer\",\"sdp\":\"202,14,200,159,96,222,82,153,64,34,246,116,22,182,211,172$FIiGiFA+45swhd9X7BA8TJjG/LGiO079N5BFevU3Otgzgz8iB+/cHqfFuKfuzApWtHPEqlVp06wXUEaLjvnbAkR6EBEaZP9ImobFwwLkw70gvM0zegLQCxJNxFDUOCvZtONUTjyFneKIqKkM06DTRhxOMKiuYKPR0C1RpvTIwfCnZv89I4+bQPyc56SdHLrAVX20SZO0YHJqe9c6cf7BGLlLHythEawKUNuqs9KK+8KLzQ1THHOBWjYBkvho8bBAzChGkx/tuqt58JsBjkCDbrV1QbhV2sfA6e0ypFMR29KLBU26mQLbMllAgdv8YCY3ceD6a3pLQ5njmMZrQyIno5GC0OWO/14efdYHF88iDknVdgprL2zhL00emLviW14b+lV1UnuedFROYBbqzidDIadnNIPoJO3bxuUIf/Kb+P3oKV+etfnz0/86cY3vuno28op6ixoNjt93v+3bsdZtNTVto6v41qRWj9H2D8Ap2TYpqnAyvZNCl7F67K53ONVxqw5lC2DooGfsUP7nbPBztZrkWHqH7pZ8y390FqEBM+QoqlYT3p562xAM64LYUe3ynEd+cUVOdJn9WjD5qIbk0dvl3N6ykV/IPb6lhWBN6zDrldR+gbZ6muhmJf/LOogRZtEVmYqvy/ObJIJukPBqTCL2TEVgPlmhNgH1FXzl7tIRlp1mI+aIHJwXdaAL4w7pbxP/QxNKru1WUAB9HJI2gasx0NEuFLwD16noWeZeSZfbZSgmKE7qQgHLIRRkp5qWk5AIUaUG0YTiHAaTaH4HakK/pEx5+/i2Ybz4BqdlADCDCHH7ys9/D7l7Kt1UoEKL2dbwrSFjAM2kCyVy8EHz6A0ikXv6Db8yEVLKgfc5dYGAgoe9wtHxxFmAuOq8yq0yVMKDvXoJCN5FlVNh0V62GXE+2My/BY9j/VxgOGYnXbRPEEaMTGqTX4RH1+a5hM8aDivK13BIXMC8j0/F3WMZOW8yP9WDGugWAlMb9Q8yTwVy9upG1XMXFJtCUSGHEhx00GDr3nJZ4QHrjpu/zAIvrBwXWxA2HNMumhbx0lYXUa6Ldpm7CoZMDQIXcSEzypxi/DD603pObMSPJE0pAyLIDdlTJntl9DW9Qmsff3ywVTAlc5dZEBaDmurZeretP7VGP4Q4dx2kpfHrUH0Bm/sNJLRZJIFuLseaOOxDn3s82f0eHNBrrNPorNEUOo0BHixswtEcOO7sYfYUvLVeD239zw47wVvYD3l3oPx22sbNG4i8d4v2B5QvGZYzdS0RTJUKgfJwIoYauUCYIzvhkwZskQvyKIlXcg==\"}}","sig":"292aee436ed0aa9625cc416ad5aa90e2b01729a096d66a13b31d7883fb8cc40167b6f12b90d6c206559d03812b347f85c64cdc00bd91692279b8ff0189930ce5"}
|
||||
{"kind":1059,"id":"92d46f9c73844d0e73a4da9678fba013135470043952ee249b0a1b36189768bd","pubkey":"af36a76eabe37abb29d257916b8004817163931e8d7acb6e14ee83150b6b4b7b","created_at":1785676830,"tags":[["p","f6ddda433221cd4512a1dd7ed37eea610422964044cb96a739ef15f568670367"]],"content":"v2:5D8IFWcX1XB94nMgs75pjKMWV-qH7kJKJ7cp922s7b6dnXZNRUjTXSY07Zf5cDRkU-NUGfrixmrKSeCH_9m6Oboo65haHfHck4IMZFVikRtsb20ZmDKWmFz_IchtRETAbjUBrVFCA0Pz1M_VkVtH59RjK4E1J7ij4gw0lUacIKVaBau-0ujZEouYRLXtEPKVLuxXI780Gya2OONw_m352_AU638i_KGasfa9SMQZZdlR5E1YcYJi6-sSuonmpYdqrq62EXOue5ovHujxiTxC3Ra8P2xvcMH_VwI4-_e8dt_EQ0EG8WkdqQTEwETT3h_eed-KkuCDXda68mqpbywpJSzJD_R7ys79x5vEwkvjUiEFKHiixaXDAm-s6ssYxTVc7J7vPkEFkYIaPqi3ClS5Tbnf8Iv4eLngmFrABUtjGip1XHZ_2QVVv56-2qIjra3-4BBKMSq7qm2eQslTJBgbnuh9zxdjfhqAw7yefff4-hVCn2VBTr3EQdd2bsILheXzWOEj0vePQ-OAG1WPqWD3ruiXBsJPyJs7VWsPP2_PyBfrGWCvamVadPdekc-vPjPrX1qkJustPn1m5AOTW_pFmC8p-zVe-HTPTyNvtkXZe4oOIDBTK2sctviWcrrLF_3gQewIlOD7_KRFPUA6LSMXcK3Ns7saa-jhVfxNIz0nYeW7VgxLbhgveozh7B9b9kHTgTHOcQe6_XEAa3wSHXosYYRJUe0NVMwUN5OC-mmzwCYniyDnWbinTqOdx_EqVQBOoX1VPh8eMqEv499HWnbALCn4iNcY0FA1Qe9KanHpfC-VF8Hz7hz0KB_ZaqNCUSTl0SC_vHmoeEnx_h7Shyn7vdloBXvdaaZjgDfp0otcrC_oa6ERCZg2YEkwqnmytmHOVf6zoY7OsOoRFTTQtpvd4cintjIqVg-V_WvN9M6Bth6g7iTL8Uh1aTDq2efEOeto5GHVGIQftL_uMwSjAAlphCv17a_EreXQM7V55f056Z5OIQAbOS-tXkoZ0O9SRgQurDFsc5mC39H1GoVrpPofIGUFFAgnCTB4mbuw-V3Y8xm0_MJG-xEE4fr7ymp2syDpgCedy_QkFgU9-0fv5FaDH11uWs7ulJlZ1o_WHuzC02ydpOUK_2FseAWTYw1KhN_9ddes8d7xBRF8Ta8pLPbVBNYwOitHb17cspuv1LSind9bjT0bH6dBx0vD22tHRIvkieIuHjtypcz8U5NRVmbchmw4WhpvptvWUoVqySxibpLBNTbUVqlBxXJole6_qkpnDOn1qkGuJTN-tWqQfzZyhXCNULWZSlZ1NYpBrSgTQTO6QBh_tr9oe8Fc-oip7_c7o9gxcvYtmTgghqW7meYhi_tb6dO9b4JM8VAj9VoiFPd6gBXNSWTJ2ej36aqqzF_d_KEgpVr8a01-4owIZMPTsefZCMLzoMux-q_aYfvtvhs3wM7YYHWfyIw","sig":"52aa16a82ed4922de3a8c78fcf5be1066a328cd99ef0b2268e3133e9cf575605c3c23b42d6c5921c00e19718ad446eea051d4fa601527694f01257fc53f830c4"}
|
||||
{"kind":20001,"id":"0008627e93710f902251efbebea4f25418fb8263eda4cf113ce40d49100593e6","pubkey":"d4dd33c3e92280a7cc8a4bd65e5b3876a572218902921df450db07badb1bb00b","created_at":1785676829,"tags":[["g","td"],["t","teleport"],["n","Boob"],["client","glub.chat"],["nonce","1534","12"]],"content":"","sig":"5175c979a4127301f00119c041ddb30a0b2836485a1d05d824aa933c84a4775ef163588118cf8d9a09f805860341df300ee4a8e9471443544946972497e0e80b"}
|
||||
{"kind":37195,"id":"b3848e2644e70a784d948eef64eca608ce57ba1a8a75ae5e26565ddcaa9bb8f3","pubkey":"14b1d34a9d862fa6073e2f9ad689ff11af8411751f71f10e5440cde3876c6710","created_at":1785676829,"tags":[["d","fips-overlay-v1"],["protocol","fips-overlay-v1"],["version","1"],["expiration","1785680424"]],"content":"{\"identifier\":\"fips-overlay-v1\",\"version\":1,\"endpoints\":[{\"transport\":\"udp\",\"addr\":\"nat\"}],\"signalRelays\":[\"wss://nos.lol\",\"wss://offchain.pub\",\"wss://relay.damus.io\",\"wss://temp.iris.to\"],\"stunServers\":[\"stun:stun.iris.to:3478\",\"stun:stun.l.google.com:19302\",\"stun:stun.cloudflare.com:3478\"]}","sig":"be31af4686ebfe3d850c516be763e74f2c5588a19427dcee1577b9a3b6dba59da5ac920fc6c6a524631e9e9bc32161b8de01116f34758055101c7cbf406c6995"}
|
||||
{"kind":21059,"id":"7e8ac972c6a94ef4fd8a07ced607d6229065d421d6c480fc13e7a40979f981a0","pubkey":"7be527855bd9034f673f08570a74b91411141a1c07b20f0d096386f1f2552a91","created_at":1785676829,"tags":[["p","4571e6236c45bb75ca1bf6c142b996d9d451ec6c3fa14ce279dd53a827b6525d"],["expiration","1785676949"]],"content":"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","sig":"8af0bb1316d7577439f261ad76875b1babedb47262565eb2a8276dec88691a80dd64e2a894dbe78562a4b69696141d860ec6c9f890a14c84549a1225a38fe47b"}
|
||||
{"kind":22795,"id":"b0806a8559de7756b708116bca32573e9a11d6bbdf0a51fcff4cff7628d7a6df","pubkey":"984094d4207e9130fbb6c28bb438e2cfce471ae19c71046d6950fd57f20179cd","created_at":1785676829,"tags":[["x","s1c1b5i40406k26b1f1f5y3s3f5o4x4l534s24"]],"content":"{\"peerId\":\"5LAzUDGlviJBcbB5kzJl\"}","sig":"eee99b6279b298bf32d5bd110c24176560e6144d36d134fb2c981eba9c8bc803378ccd154a31620938d1d90a9d9dd248be70321ebb4943d1e96019d40244d190"}
|
||||
{"kind":21059,"id":"27bc4a662ebbc319927530f64000150760e270bdce69cb12b442529ac33ca680","pubkey":"73399d3a149703031fa0d4701ea9e319226c2979343e89c4915230a533572656","created_at":1785676829,"tags":[["p","fe3cf170bd88be377f684d98d098aeffe3438882eb2a81013ddc4e66ea00dc46"],["expiration","1785676947"]],"content":"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","sig":"4813c3412e748c9d99e4ec4ccc6b667a4140714a094914df05d111025e442bd30a594714f03cb0df3537ecc82653c7045b98531bbc0cf49faec2bd67a107c175"}
|
||||
{"kind":21059,"id":"e323e7671e52fa1f93b1c38b74d9045f0e7e0c57c5eb64f0dd9dc0aa4cb7e9f2","pubkey":"42dcdcedf8f9fb5a343aca2f324985960a296f89a40b186ab2663ae544649098","created_at":1785676829,"tags":[["p","db4332cd601e12593fbe239cc5af98f27401d46012c778694c22cb147ae3efdc"],["expiration","1785676949"]],"content":"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","sig":"269bdd6b0a63d8d7842c04b8f6e743848caea5442047c3bf9aef46d389be02b61d6b43a2377b33f6ed6b199c64f2775120447c2281560ed6cdffd14c33192476"}
|
||||
{"kind":21059,"id":"80b6cea3ad0b0abedd667b18d3804879c9b053bd309d388e58aad701d3c4e129","pubkey":"764da1376080b4c50b442e8682283e911a211675ac019a354eb4abcb3e6febf4","created_at":1785676829,"tags":[["p","c90adab9315b97f7bdd9bff861bb026c9c454be1f1fb3a9d64812b75ac5e2bcd"],["expiration","1785676949"]],"content":"ApFrplGKRegai0HKJh05GfZpgK1tEFKqlMh5fp5yHMcyopN4QL18kX9qiVsfry08clgYtdpqV/YJ7OltdiqiEU1jf2RFWN0Ac5mYYmpHZjFqOvlwcePB/XinLPKILe7u2ISg+AY5/Y1KS0r5ZCGzbKQBXB1Lz/jV7Hq4XMVnDHSt4ruW/MpBMLsQxkIYBe+AwoB0RaW0d9FhZeDiiGnCWUUpx8P+K4a8vnXnYKPjKl1RJxJ1Q96ZOvitcZanJLzdGpK9ex6dxFqakdWLwo5iCiSHlZeZfVfhDIGn58F3658X1jmxZe6vomkLx9Iz2N0reOgq2OoudogwXLyXxULOPYHd4lKg45DptZr19MOmZ56oi7FeH3rz+dt9pf+vgVU75mMNAuTXRFO9Z1bcZjtAbiqM57d2PgcVNbKqau/OuyhM36Gdvm24XWvgxxK1epuLuzSLrVZa3ZWYI3TiOzQ8p8CpNCDuFG5gt4lieVjSiwCZ3+8ZHI8BNtMHXXtN7lVI3sUaUyH2d5q9V27adk3zV1V/kSeMs7dmJgdA2i+CiP7Ywt8sxJztN5vfkmcejTYJnI9BzKHUKJW4hixPzPl5AN8T8tISvDjNW2zW50yjhI8aIAtEoQWUXgj/VoHfYqIImwenFTH+GDJjLWxs7nQSj8HP3xbSPJl2R9/P1UpAzBL1ZvFNtJ9KK4i/4WWgyDPPMwDW3iFUEFE60kK49SWmQecv2HyfylwkMqBzbMD+qR6/G1P0vnLPfvZaTGIFuU8m5adY/ta55WtaAnlBFC9pQWzzj+Mw47G2uX1nzf/MNheDBxhQWax7cBRhFu+9Mk7Fw/SuVz5qVZC9txnmEleyFrnlW9BvLBRlifj+j1OW7k3pAKX3jXB+bn11C20EDDI0cTHmdH/XcFQ52adGmlNz+UHgNhTwwvrnNuhoeJKGieQ+t9f8FHDL5m07waV+FMgk+wQYAjCvONsicRe02SxOtVFN8AoXy5+zMvteiAkE77XveWAICcXwDnAsyQNAS5j7Ivlrzp0RSKl1zzE3LNb/SrT/II0SOly//Fl5hiPBHHIvtcPZzpt4kzKeXBLy47pZ90gY00r3nxDXKikMLG0ueF5UyxM8e+tJMFngdJd5e6yi7PpOEhx0inj18fFix6BoJfJirzDTGtRyV7pfvimLysXQ4GTD4lUDL3l6YN2Z8RPHZj+nun+dv/qCIohchCN+S8+jjz2+98ojwpT3PFuwe8Tcb1gRxpDsbu+yYzNyz6uep/+U1s/0Zl53LhnkBKNpBmsVXlddBuncW+eDdbYJVAw2r88aeIFLgHzOgI+R3evXfjRjCvIm7w+SxPs0S+aVUbl5hdmAtnDspDzzlNWuim87mlgD+Zj/jF5XkyEz7x6Q4HTSJbScZ0gSkRwW2S1a265Mq572mHSKUvwTh4q/PnguiFDeY0xmaNuICosWYaotNEbqkpEbrn3amZhi46ypCP9WWn4uVaTyLQH1rKw+usVhhYIsYCQzc/ycBAQYZQxmSk0nOD81jUZf2mU63C0Igobvbm0+Miul1SJNmFsuiGpkwRwp1jaCTPHjI/ymZnbDMpLX6RHy8Fdx4k39VJv2m8XA4c2Ke35HQNDMhQpPQixRKv823CCWmWtzTAgNYi5FIetUS07TbwGNilQrLttlRZiAHKIdjxpzTyHLVlpdObLxv/gQNIG6tzOyGtoXco6DwzZjTdpzsoFofAZyGiEWvTaGGAjU0XFcyF+B51JViu8b9Ww0YPU6t6/k/ZbrZYgrfoXxMRpyzXQC6tl9lWHOoal5AnAsZol5JV4/DqLyPeSm8BPNyf6xuUx/EtiSQRiQbal2C5Wu+kXcjPv/VS5iQ0r35z6CCdK9BPKGHIFdpF/NkC6K/2hXZCAJDzlgSYG6c6nVuf1BC2M/zzfQ8WB8ZFRqAoTDexp4trTpVvKaZOj3uRR5ESNGajmCJWrfn8yuHIA1cEVKLtsSebj1iWYujiw6UH0U2F3PRsnK58M5FY0FLi7/xd81SQgeLNkZ8s9209C5x0tpaZQpCFa702VZcFXle+NpZLHUTExxOT06SAQu4GpzMUGT6fPK5vCCRrmgSF7sokxvIfv0QO9hb5pMPAHqCjfKdpZUAG5ygSPTq5lSKxdCZjjVOlSExlS4WkSIzEmdZkYAhW6Xa+t5bxmNFxaNKhI/p9ogxfmpppsGm/rKpy6vL0xiVJxb18C3gT5EttPnicWiudparv3oKRR+upI95MPOk281dXnyKChky/RkF5vU3sISIMyDBycU1X1A8y1q267zkmJqDoxzbOEqK+9I0PGTXGUd9cB1iSOxeqDPn4gVJf//vcuwuvR+opRjKTX9pj9k7htmIsbOjqVhEiWAHqL6+AEDqnjPAun/zJnWoVWwPo3tGgSd//xgEnRv/soEQJYZQia/ngKdF5lBme2MXjw3N2HKY1zUmyBqNoiatgzBwZnhU5VkLFHBm6ienJoqyqE7euC1NEmfFHshhAwgAYgZi9c4C8NlWPLe6D+ZQNyLE5KvV52fMAOiZpvNbtWAMFf/kk1mv/8p5EbuvHSlp8YdIzOYlkvXstBUMeFAH66RMK4rXoomhax5U5oiqpdbYMFjzhnNmayvuxFNRECWlo2StIKCBr41QjjpzQaX86lKU3c4xuzP02u3e4Dy9ew16Cf2lkNZIeCgVBK22MwQMe8W0a5zeVEgkLPzd63Do2+wxpvbb4jgaKue+kllInNUbKBqTgXK3augpjX9ZiFdqsxdrS3hC5hRSqzLx+ESG8rUKwpElPhqXQSdzeVHp9UjAVNFotKG5DSi/gMsWFRN","sig":"30e2bdf73205825bf3a19ff6d5b0fffe49b2d427470d7670e9464628f58791f491b41f78ac8a137ebbe64fb0d603c1b516e857ce8561c8812e53c04e313cb3d5"}
|
||||
{"kind":21059,"id":"7d821dae2407dc0ce17b7be76558fea2a7b42332a80fa26a775bb481e7ab4936","pubkey":"51ab81dee29a9a2cdf3adaa4820d00f4018cd540d6c4b6f5b7cd70a155193e7d","created_at":1785676829,"tags":[["p","4571e6236c45bb75ca1bf6c142b996d9d451ec6c3fa14ce279dd53a827b6525d"],["expiration","1785676949"]],"content":"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","sig":"d2ecfdef11672886570bb8da9f00e89ed488351faa377f7cfd9625455b752d6765a1415ef351bce454bb4c8506e9a7795572fcd0ca3799a5e1c88a96ad164287"}
|
||||
{"kind":22668,"id":"e5bd8d0ba4903407e15dccff8c3847a142403fa8808f08d48927eb1989630530","pubkey":"011290d507f716e7e28b78431c6dacaef737ed0c296eea006b3aeed76162aad2","created_at":1785676829,"tags":[["x","3h4b5840o6s3o6aq23294k3l3u32544u3s7266"]],"content":"{\"peerId\":\"p57BF10Qa2QR5CWwRPwk\"}","sig":"bec46000893446903a21a2cc3c153fd0caeaa2863d420f613d5c86eeeea86252a977c415c08782e52af2dd68e12ede07786e437f4b4e5995d3cc9dab901715e4"}
|
||||
{"kind":20001,"id":"0f03ec93ee1b132d83fe87a2a11488a2457ee29c32d012ef86d6499be2b6aea2","pubkey":"b5c861e028296358eeda540fdc4bf0a55620fcfbc8402c2aa6c0e374ca4caa93","created_at":1785676829,"tags":[["d","781ea0904b118a95"]],"content":"{\"e\":\"🐝\"}","sig":"8c1f43b54758888bab77b247e125d39cbd0f851a9a866e8cea094740fa972dc3545245e97c3b013a10c4ec85ddd162698c377e4335b17f9e3c5e4c834e5d8469"}
|
||||
{"kind":21059,"id":"efa8558e04b1018251c1ca9f75ade84c3665236ac0dd4e7531a5aa4ac50f382e","pubkey":"61e46286db0f8b3a657c97a18b24f941c2bfcfee82e4dee7c43a27dc73d9ea9b","created_at":1785676829,"tags":[["p","62cf088f0fa0f198b341ce6c3c4d16f1bf06c4c94b11b54e5e7ca6290e22e94f"],["expiration","1785676949"]],"content":"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","sig":"6d06c924a3cd1d73deaccc52a86ab472a3a30975ab54311f5e3c83d0896f18abb7c921e5726317532de6382bec35f2237c4c225c03abb8cdd52fd143a1c0e93b"}
|
||||
{"kind":21059,"id":"cac1ddbfca49abfed7106b5e8b35799e803a7323c88f4ab9311c55904dff8038","pubkey":"cc06b791544dbf3924fa4839b43e6db9df75329b67278fd32963cd19e9cee582","created_at":1785676829,"tags":[["p","f3d5c038e4ce5015ff2069c5984c8a47571a427b40e120d5c412e6ae6647744d"],["expiration","1785676949"]],"content":"AtWLWd8t7Lfg66OkM0mNV1mPWLAygcu3aP1HUPZHfDfgDo6jCLKRQa4J10KW2N88bTLec2d4g91rCwdH8iX839iQz14dp/Y8hpH2DLk0usBwSoE7d89RU8F3UnGGsPce5erOPGm7VC2piPXuhZDCEi+NozbQbXmexkM8aN6wzamSdCUFv1F0E+Rb7sjPCNpAz0uYiJZUuLsuX8rvnhkBcpfLqXru/3VSymqYrTeOKu2Qr8OGoHVTsvMlsJPgqq/5rLy8s+dhTibcUR3PUyQ/REzyuwcrdBfQmnFcHO3XN4fHcV9UFUdo0IbCx2NSwDKwIWUmMyWZ4r2tcWrsXG0UiVKcb+2bhTvRNS0ULKW6kGVEQQ6Ov/ci+J9StABft/eStxe+lSazjzv3AK+scg3fXwqiGhN8Xjf4nemcW6n7vZ872TJ8aEg552bbCRGZVPOsd7yk6noAG91cEcpBDPfvXwtOPMkW6dnj/yriE1+O3PrSihi9j7JtkNplfT1lQpTbh9lzVIQd01dCP6b+esvs/4V/UsfrWZ9GHnAUIOmg4qWaTUGRKc8s5+LlRpsunhzv23NiU98zE+RpGiYiZWOCHA++kpSXFjU0Itmad023YECzTTQQqyCTAVBzsQyDbHdYazhxbkn0oR5RtkJkIb0DSEXzpAHd0s/nI2prZmn/J6iRvMp2aIxr/VxZOwdqPQIlW6iZP94kg/rmXs+x0k68W3uxKq5pAhAdApSasaRGg6uFQGTZDH40c3BkHDrDLle/TpHjirhylbG6vcWDNwdgapjAMu+CJkTO3pyPQTRnXqgxvBP7+9exQSlqHM76DNN4Tu4VTqRBa5XM8C5cjcBERCNNLENTP92A6EneksBCUsAlcgVycWAAtVyd0Qptl/H33XcOmu753v+3voVDG1JnflPKF+f4k4UVDDWlB3sU/x4bRyXmVQ4mJEANOJKZNDiALaxOkB1qGPWtLKYYpERWIDnavqgxd8h2nOvHfAbRKd9pwlhDtbqydr4senzdE1dXU6i+1XeCF6RczMA9iJlAH1tBz39UYhAkEanQUnDCrhCQN8IBCwNd8yu1pM+y98eBT99OlhPzRIMYC/hwrt/SzQdPBp0P2E1eOaxUbd95WJx4XlisOeqQOqbhnbiufLg5xyVz6bcyTwv1GU8o0YawLmx0L2uvAUbgW4iA6eL33Z25GGrAx4GSV0/Yam3JaS22qlxAzDFmIZ4lyKX7xrtPg4lHssvvOzq+f8fXksX8KGI9OCmFkrvflIyEILiZE1Z81kQ8WEpTFGtQkclUKTUf5rDz36YbDZ0KsQopk23BUe6w9PvaJFBiDag2PN25KhoCuTpCl54/HtEIyy+ndOp5l0eM1zKlFLsnT/vCZ4InyglCIscxCkx73IBnvKIT1dAJT1ByCWYrA6LgFyDGUoMKksGkPzRpMd3mQoOlm2YQUmIoV/TIy75OKfmTS4eUvRfIkZoMN/fyrCylzOhi711dt+80AfwwoDEz+/LvdUTjIffZN5wfk6eziL3p8yu7pjOxzlPY171A4LZ5XVRB5WrBIuEPo3H9TSv015DsZFPhjGD0WPsN9EDas+9DPOxgH3nJyhRWZad3Io6mqarfjf2Vk9smsyip3+ZmdfJVzU5JTvZGkIBWsQITuaaf+6wYZ4+z+PKfYjv+vPoxU54VRknFPjqqsSxdjpCnY8mYwOVcWEwDJpj31TgVaufq63ZDTod+/flNHXEpkNbBv2Ep/7dP4q4BEmL4IgGPqKJFDSZ2XCFeTBocG3xUzfxCPEdEeefcHlkeOIYMqhpzGan6je6ift44wAGg6KQpD3FQq7AgcywmhGDJjBZy0WnYQLd6/Ugf7psWBqrbxiA2+ZtBWXsjhP77uGxRfryMQir6Rr4cibaGsGuHeGZKexMFKhu4Vu4og7MZ/+JSR9LsbWlI/iDkJnAT2JllrUddlOOxcVoSAHu+BzAEeShmuAYrplP1h96sOGwCB6z+nT558LbAtw99BmENZz+TSZoYYN3Iu32r1bFD7+5V67Ip/L5tKMfk7rLzU7PSxNoCJ2ERAbBuibsUZWwu62qd1BW2UZ5PJQjxEWFhXBTWB5KOOF+fn6mhUhvg0Gqohdgm0XAjsF3u0a3o7Xcp+vHqduEn5w9n/I2CJQSyfhShV57SnVcbMg0xes3EuOM0+0sqn+J8HSNXKL5RF9d1LMf5ehlPkmBvEGCP2nuseehmd6zJ1Pu+Z65oMxm3Tuy8H2R6eRGfSL0N61/wrR39oY9PC9NZd4AvQVOuIYPJCfZOj8hrotJJFdmFz+5/1r5pzvnKjT9qFRX9r5eoV4n+YeeJ9TASGs2BlB/RwmqXMnPFYDzqGw6wQrRUxh3a9Pa9lahf7670CktkDlR6/WBkJZVfli2K4X9+GyL+dA0bH3bzyoIQRSFIVGpqqPln91qkx43o3Ov9MeREVURSg8G8MQOlZjOzpwlWCrBZoiEkh7s5xtg6EU9JoclZZ0cK4ivLvZT4HtIJLTavDe51h5edf8IC9IVHa8oC9kcySxYMjf31eL7j+Y5ikiDKAyRObATKm+ieckR+z+NhItX2poZp+7OyC/PKEktd4GQPHoXc/oEPAG7xGF6XwsHTZ5V1RhvIewJW1fXF+VtU95UEVDCAtR2I0QdgXzW5GPpECwEYGMC6nR9RbkQFFFYP2Q2Yl3MQeysTVMVZGgmo50RD6CRhR10VHZ53Md+3kffpSsRnbAixkVgepvCjQiRdKIGw9si7XWAQyYQjpECaTZ/vg7uw2BW6Ll+c9ncXRy4GTDldIDXEnJ2Wwk5lv1q/9+hjqcVp","sig":"0648a3e97630d479672873ddc45636b50fda69d79145c6cfed77d518a27808417169dc87ed861eb0e6ca1a8bb274dcd8cf970b37cd3f0d42c09ff7d71be20e4b"}
|
||||
{"kind":22751,"id":"cc1b2bbb1bd8ef560837d280d1510d93d5199aa019673d00a871aaa14bf4c848","pubkey":"3d5ce431f2987ab0f0ea0745e5703bac780ea9384e90c8a198ed5dc8978f1ea8","created_at":1785676829,"tags":[["x","5bb4v4t492d291p6m82o5g2eb2m4w1iho1h"]],"content":"{\"peerId\":\"KInutrde21v4Es53GmBx\"}","sig":"b3875007e6999506f815c52162492680a92f5323dfa51358a5481174692a5f53cee4f8b6bf295f0b69704c777c2d15963bc2fec70d5cb1238569e3189d1097a3"}
|
||||
{"kind":21059,"id":"ce16cb9b2bf391663f91c94f158745bc94760d383dabdc35ffe728462aba63e6","pubkey":"d5bccb32f8efc4810802306118e3a2e2bc39b690f6e1defcc06e007b3da9e591","created_at":1785676829,"tags":[["p","2651be916e121c6baa67236dc6882371562f2dba151ddac18948b8edd88c1321"],["expiration","1785676943"]],"content":"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","sig":"67272aed2ffbe1417bdeb2362a9d49e6535253b5792ac600ea3992395b7fed7cae545a5e14ed4a0f037390707f5d0e50c6132b07a480249df008e13e724b8954"}
|
||||
{"kind":13194,"id":"3c0da6d6cfaa5f198bf2dfda454096968434028808a2e29e760a63a824de62d7","pubkey":"18ab43661d7848e6e3843a09c6aaafb007af2ce2ff3481f81469ddae1e8e8fb3","created_at":1785676829,"tags":[["p","18ab43661d7848e6e3843a09c6aaafb007af2ce2ff3481f81469ddae1e8e8fb3"]],"content":"pay_invoice multi_pay_invoice make_invoice lookup_invoice list_transactions get_balance get_info","sig":"29c9cef993fd1012c2a21691671afd32f057f9364eed31b40f0906348ddcc6606aa5b2e4ef8aaf9198e8cc97488cd4133ae650763a3b8da3293e72e07c9801fa"}
|
||||
{"kind":21059,"id":"38274f3cf136f9a19359e866d55b86e661b9c1da65c9e826c08f7669e84a7337","pubkey":"931128665954f1a3f0fa09a5e3f371ab192fe840575daaf43040453d838285af","created_at":1785676829,"tags":[["p","2ec845714f95e64d1de364181734c2e58d33e0534c33402d2bce2c0c10a53b65"],["expiration","1785676949"]],"content":"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","sig":"77927d477d07993c9ccf912e488b3384d69aba61b70f13c85cfbfffc2cb3fab7d384ddc4b377470bef2a93ad4635b1ebb74d05dc0c6f3f21aa15d4b6385ace43"}
|
||||
{"kind":22668,"id":"4d59c8963f927fa9ea3c116a710049275033c52fe5eee1c2d970b1e55a021f34","pubkey":"146c70d40e1f4f96528309629258f8dc97e9a61aa53e54e13b999ba5d2276968","created_at":1785676829,"tags":[["x","3h4b5840o6s3o6aq23294k3l3u32544u3s7266"]],"content":"{\"peerId\":\"9IVDCiG4hlib9t5iG017\"}","sig":"7a569489f112258890c563d4924c4f7344537aef198f64a7cc0b9f32b96ec7306ea98cfe1fff4fa6ac2a162ffa4944ba3699cf2751bea61b765ab32b90122651"}
|
||||
{"kind":21059,"id":"5e5b504bc37e7a30f376cf1ecc6884e31163dae41f5ca3af1c7d5462e972dddb","pubkey":"fd5a12fdce164794145f3a5c4b35d798def92f98242ff4609673de9214f2895e","created_at":1785676829,"tags":[["p","1ec71c39a30373cbb10e91d6efa6ef1e9dad0756d610c1a4e337df016eeaaff8"],["expiration","1785676948"]],"content":"Ago9Otymd+H9Ya+y4nGl9Jf7O0Rlm+YhcvjJFxFCBaFn7g9AQ3StZD/q/Qj+bDIkvrfzlKtSQe3h2fKhYPr7e49WGjFuPl41XBIvnOZmKrez85E9dYB4TwC78ieZmx0qgTececaven/kpCZ6puHVz1b8ssT3aIYGD+scePu45m0O1m/7UtwxlsQwU4NzPGeyEz3qca+Z9KdlPiJb+CNu/OK6SYArWvd7pDRAgWyOvPc4iN5UgcYodV1ycf2nZRkLtTr8WwR7w5d0QZb7RjU0vxESeDmTLsDjw1VMLTvV8X3I1bgmOc3Wby0VXEvA7+zTnEel33/7WIVF5IEGh+DF8AHTDOREbHBXpmIokicFxmyOFZAbJFucJ2FCbSRqETYl8anpPbHVPlXtB8WW0AfzdqQ4EtusSz6B4iuYX5Ax7Uu48wzPnnKJtNe6mTixvWWxFafGKJwuV8gJqAqPa/jJUGm+ZUGaHFo7a+y4dyIVkW2hdEL8uLcCr6iG3btcer5i0UdlIFP/TzB300JQDzaEY4ZzLAjU209BUlLkh4AZtqXm4k5T5TTxZ/YQDES+qZhR+RWX1hEJEDPYbrfYYgaPdiklyfUkh0oN5ZvLz2WrfheP+IQ2twnEpVKsZrSI4GFIRHoDBbr4PlNDbZqU1gTBItCtDoaoU/Kh0xK02zw6zI4r9j1MQcuaCioc9dPHVzNEiHqDfZ3vuIfoSTf8Ny1l+D/szKFoXsL8PTB9Ke4AKt0IQEw7R2XivGc9zTeN5ffuTHsseLgKmRSXGuhc9y/rCX0TRrbKRPlnHX3JfsnXXFwRuY3PXL55d4Qq+PDnwtlAdL9O503pnMB7noA0f5ZemaPemQzZ8rfOevmdw6yqvMON8ITgjQ9/5w8odZpzkg33RR4MFomhkPZRcFLPp5eDqF8KykyXH5mpgnu8TG1tqZXqxG1h/P5L/28zlzD8o0xmKTxOG/S92FyWGf+cCtOhcDtcGuCO+MSCzKLAJaEe2BMwgYMhV4rNwDO3JErsVOxPbEMym8+/1WefSLAxIy7jNPjQklVphNKbqTgrFADBHnPP3vDPS67TaDeJMwiBDoX4C8aTp/o45Fdw/iXbbc69rZy9vVBBJ5fqRcAAgFBWsDZydo1EgYJyxPGGmJ0d8bNzByL4ZeRC8rl8NPsSXt2sOz8QtAxt+4uy+1R4kxOJ0jjTTS0myIbh8+kIQ8aromXuhfM0AGYv1M7ygZzpkdB+sIZW33FQWQFLycpSRgwB7vHKV/XlJAZRIWL3TJRDutX6YXMq1cAvNT25d6fK/m94BeyMM1zfOUGq7peIPuQcSmZcvGi8/rt7sEq+ZmwhBEkRpWE3XueymeiMEiq2tKul0kX4a6S70OADZZPLeGR3GYBkdm5fpgxa3uaSjcotiuaE5ELP06CzPrM2HY9e9DipQq4CF6pes4HHFDF8dodoob3ByxOgdN4BuhtIcoNSZA2uLN+4/gk0MWvdw57S2Ty+bs98oMu+987GUh8pbo69a2haP3QitFWnqtLPDOjc6RHkpzVZwtCZlKMmsLZNS7LLFFm759Nkx54yIBmP57uR8td2kyJcet+EB4fNIiLlLseRDJpWLWLHFELKVpzC+QUu5u6G2KRwBKKC92z2fN7hqeWQ5kFA+E3VKbWcDr9kKqyJfMseL3kd7nT0CqWEQzxEWR29h4bL/rYa0pjNP5PVJDdDbrZzCaJ7G/ykmXvmm4cREn8korzpJPNblSdoMPlWORh4Y/wR6CB2xYY0RJdtl7zFL9FTCXietLZL/AwjZt9HM4kzxTyjw5ADbS07PRdudT81s8YwhHNFW8eiakM+bgjrG3bYDYz9Cciu9Q6WcGdCtd70zUFx0nOs8JY4RO2MlMLTM1mbENKxGn7k9cihJl5XsmAAfkJUwHYl0yKRbMhEXNBUVJLJ/09xp/OPeXq37x9ce9U4NrGQLJ3sQvGl/zW6twc8Xo8gEXMDoJr27wThTdOGsa/GYRUHb3btn3lQf6R6JTC+ISQoD6j01l9PntXU6NEnZsVvwhNi9maP4DsPNz0Te1mx2ZT1Dm4QRl6xvoylUqQE8lwFKsMLIucvhbw77i68PyBsjVIoHkWpPRsDJjN9pDAnoll9xhEX64yKwCrDC7GN/G5vcUdiAm/jofyNrgxwbUn0aPTPp4PgeQD1NaSPCojFxAXTr3DG90566ioSbGR1oIPM22SIPqSjhp0Abn+pwdGnNLAw9mMn+A0IZPTjq5Ps2gHCGQ+fw4DmxLMUu75x8riEvdwrt0r8JHeAiS5sskAcT927j/xS6a+RpsQWZUYRgxHHYPuCOkeEv6hqjIMeYT/rxYOqOeLqWwpKfW3DYzaaV+j+j7iBBzqbsVSerQLg4k1OouWM5ijXT60gz310vNUtG5LvnYwWBf1bseJ8hFhNXn/4O6jh4rNfyDL27aaUOqgsEb6ZJdjOv+LvYy2v4ww781Otztqb3jTQiMRZyTnczdtbX3WNe4SKPrd7mgoMOr+PrDffxRiNmcGS+6hQwI/mI1UYgi4ZEluuiJ2V91EV54O5frkIW+/SZgciNIo25R995EW5M8DpxuiTAbANhX1CODrnvnbYR7d3SRlFbXbBrztvBgQhnFE65WyBkI/zF8sKgutOAouroqWL//YBR/asdNYBgwzJOsnApIB1fG+HXayFASV5mnr2JucYj2vG164+oxIXyVd9VYbZL6mYLbJXPrgvCtEGF90kV4UxvnDcrKGxsUFU5o+soRUdqk3prnnv934r/5Skarh6UB2Ey3yGrAEzgVmworGzyOPkEfZJJ+M+/6N52DSv8voAbNOgPGqONkdOFLuV/gCEKnky/sfkFwDDG3IIn+yxraQblGGwrPRaNNLHzCBL9kmaX3vrIASi7x5JcnoMxu98lSx7gwmBPrx48bNSiHYCu7beyy7rpNz68ISvy98tB6zuN/mOH/VT2xMheOVlph3puvqZvUJxFqMQ0r5f+H0qB2EitgFFhHNFEtVYxgq6/XvxO62ylUOqXnvOmW6sd6oMF4KyHX18Ic+pulqWPSCLE3G5lXLh1JSp0jXC6RyZpabYcRQSg2jwVFbRIkT1+wFj9q2Fi19AN0InIFHgIC5sVDw1V5nztg0Uu+oX1gn0y6bKG5QmeE/nG7kBCUouHq+fqCl6SXSHMeeg5Z7bDbsCU+SnLGn4wshA5CbdAmsYAIZKC/R+JPdEWhTVMR0CqJ5NjGqPzZod0jAl9QiBSyaeXQGN8JfrVJjOOLgYJ7NuJCZ5cCn46ha+jc4npO9ZWftoqWMwqxT1jj4V0ycT2+6HKdn2RdBIZvMFc1ClY7WutdsjAk/PdV+odq/01FI6ZB0MD1CgReQSI/o9H6qJHH+awk+VRaq4FHgYZLVDMf9mnKhsoAb+Wf+iuwusqg1J5VM+hjKWot9Z3EazbdHC8S7KRMhmyU3gMueHLwGbhp5akGeBgShHHMQC7an9BoUAR+iGg3TI67/udKnWN1Exnwg7/E0=","sig":"dd1e19594cf2758b966c27f773e20c5f1ce5127e7a6c046f40df32587a6294e23ce91cbcf789f25ce93ca17408ba16d17a82449d734c80d328ec53f096047e74"}
|
||||
{"kind":5,"id":"782cd31915d712063037d3948ee8e7aabfd7560dd332227d502ef641cdca1ce6","pubkey":"b454400c0f61af322680e46825a10c69aaa4226be2f474dc21fab2c7271d4ddd","created_at":1785676829,"tags":[["e","9aa8c8f7a20f62091f9b3ba3ac8262c9c2bc1a40d87ad1c75f0683c0e757a983"]],"content":"","sig":"ca9858bbbd3a7d46a9930122981ad8402cb302dd4a1802df2270c115c12971fff8cbe9b740898d5f618f3f0a9ddcf79ff8f3fbfbefebd21d60670ce15982bcf5"}
|
||||
{"kind":21059,"id":"3aed713425ab4a0459176d4ba589876e6a313d879fad18152a11347c22c1114a","pubkey":"842130f8fe9ce8aac0eb1e1f310de93b32e6968a5553dfd63eb5d8eb7874e0c3","created_at":1785676829,"tags":[["p","1ec71c39a30373cbb10e91d6efa6ef1e9dad0756d610c1a4e337df016eeaaff8"],["expiration","1785676949"]],"content":"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","sig":"aee0be687ade030557e86ba811b5d03c590fe6cd2a62085015cbb4391960b6a24fd0d0caffc5ebc5ba765006c3d98a5c847b15bd81ef38617d491a6a11cb6705"}
|
||||
{"kind":5,"id":"137d08e7ffb7fe1cb7bc8b2be596e6b65d5699f7cd64f13a23bf390f70807c90","pubkey":"29d1d9e11edbdbf04538d90d053b7b2d32c1c253fc3df1893c11b68826630609","created_at":1785676829,"tags":[["e","810bde802c36ad6d9aa0e017ac0f8bbd6e66ad80df5b9419c0313be8054f2d48"],["e","9d28fd6286648d315a0c47db82e20b67e985a54f10eef09745d5cf0241b85e28"]],"content":"","sig":"bc21735717ac3f284a372f2bc72ca9d15badca8f7fd8016ee89015ec19d9a212f528fce8b16a98b62cb5108f86b5ae2698b0049eca59f70b710eecc303765544"}
|
||||
{"kind":21059,"id":"16bdf72f80f5945fb5e08e5f50701615cdf8d9f016c8f48a6f8f22993da33080","pubkey":"7255fdb4025a1afe269132658221bc6e698108cf7b43571e929cfaa712063ebd","created_at":1785676829,"tags":[["p","1ec71c39a30373cbb10e91d6efa6ef1e9dad0756d610c1a4e337df016eeaaff8"],["expiration","1785676949"]],"content":"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","sig":"e113e7856c06159dc5cedb6262892bc5014d0cb5fb21e749eb23509413548dc8df95cda93e1dc8833a3987e5227bf51c578fc990f3689e7c0fef9da250230350"}
|
||||
{"kind":21059,"id":"9aa8c8f7a20f62091f9b3ba3ac8262c9c2bc1a40d87ad1c75f0683c0e757a983","pubkey":"8f3f5b88fc7641fc8cba3f85d31023c07562c05290bd8dcda72efbf444f69926","created_at":1785676829,"tags":[["p","de2474ebae76da5fc0dbbfde5128465ece9adb6174dc5210014f277e2c54a093"],["expiration","1785676948"]],"content":"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","sig":"857148777b63e5e0ee1eeb98b12539466cbcd35b21514484fad507c6230b9e71d3d565af406cd8b97b0966f7e83bb212ae21eaf8a57162b2f47bcac7c293e427"}
|
||||
{"kind":24242,"id":"443bf61bd52ead74bbf7f3e0d147845f0ed9edf680334029c1252c41a58caa4f","pubkey":"0214d7edd25fe949a9978de3b36f90f7a4ec432dc9753087044be638e7f2d3a8","created_at":1785676829,"tags":[["r","2145c86a56b377b435b1a17888dd93707e0991ed524c613f9ba73541c94e14f0"],["t","P"]],"content":"{\"t\": \"P\", \"d\": \"VeNHJfdrPLMeFtNrqqVREOclr1Pj8K8tan/m+4DPgHeYoq1KI2ryYNcOurYaDy13Cq5YEJGD4EZtB0CxAl4Su48pTzXdmuSs1IHm0lBYtkHuxEhUZigIGi9aNYY=\"}","sig":"c350662d3c997e8238be51564efb0172005507fe2e73f882bae32108fa272d6c4fa2edc55866d899b01ec3944578133092220e5451cbad4d5ac171827ab1744c"}
|
||||
{"kind":5,"id":"22f5949ec55c1ed8ce97c6d7d2bac71992efccff6b5eec37d4329c5f44b79f4a","pubkey":"a104303328d41ca62add479f54d19467aaf0969ce09024e0d46dd577706c9bae","created_at":1785676829,"tags":[["e","958d7a6b0092f0d0e331b2dbb7f197504de75ba442b7fea806be2098c7c2eb2a"]],"content":"","sig":"dce8d65f9939f32c404db12b3ac29ebf01d28bea8a58346a8d886cd174e799e46d945c97d96bdc0ba4345c5ca44b6e9827cede44ac10efb931bb3f831e8935d2"}
|
||||
{"kind":22455,"id":"173ac3706d5caf2f883cede799f54e93a1b89dbb4cafa1885703562208a2350a","pubkey":"146c70d40e1f4f96528309629258f8dc97e9a61aa53e54e13b999ba5d2276968","created_at":1785676829,"tags":[["x","i10614r6s6x481r3l6875fg1631u55a564j"]],"content":"{\"peerId\":\"9IVDCiG4hlib9t5iG017\",\"offer\":{\"type\":\"offer\",\"sdp\":\"214,198,243,224,5,154,106,180,224,102,15,15,79,30,115,171$ff2wqB0tK5EY9LkoZ8yHi/oyz+MfFpi/6sLjRP++zumM+33SIHLHt5lk9bEZeCZGnWaJm/xGeBLkAjrIvGLeCU4T5FZ3vuFvQUWJmo2MmdbCPISD6scgXXpVx854ExqWcJjRrTa6eFY1/2bhJZ1/9gxjPZ+gX4NoXcQpk5FbTFI9scY+tokJCGS/VWIt9on3dKA1ABXvfHUaV49hlTi2VmR1/RZsz6UEzSdz4RJ1erFZer0R12CGhJ5QAg8YTAcfbFe7D1gKQPb2RnFUMNyBEHbJNys9jPnq5sF3QoA8JnxgSZgDs0nttXfmuTtywGqY9zvCNp3kV/n0BatZUlAyzhcPgAqlkA+I6L82hT2vY6Z2uUJOYRi/yiAswm7BU8PaV5vkgViODnqANVnnOHHyDpRrMhWEKmFuenxp5cBs505WkauYI5gSIuAJCE2aWhcQs1jX5uGMU6UsqJkUv83FdEZ6Syi4EEVxT9waIZmBuNE6XOKn2WG7DhY56FZoquzH9b+Nh1yeJiYkBldP5AMQhmzUHK0oP0iF1EfmxW8D6sJEWYhR+3mNkOF+cITYdVbwotN6Ijpitj07yP7/QtzeaWENsEJ4hEz9vODuSkgiFVNX8bwSjwHoreD6O/71DSsHve5WUe8Tld9K4xMv7+Qwe1pnbLea3F8qxEfBAnJVVpVXUZ1u97NuO4bsQ1TduEH+ie2cFE3MKZq16IIz3+8+fjMa0DO0UrxaBa4dX1au6Yxgd0EV42gCEu6uGqSnf6VzTjBwMoGdQsDK4PswZ8M6052ik7MBBYbq18VMm0eqBfhN19R2IFB6s9k7P20gzQYd+r4no4ynERuOyJrGKD9RrSJ8L9Ta8n+5ssFcHOFrFAehxoD82XWUtv2tviwLvjKUlU0ocvbiHAOssJ60cFha0Bt+zJqlPjhjH93MciW6Sk3FeaFsFZteilwQI1sn0f3rmk5p8xXFG7An21gswdcCEXnssKxLi5dQ5CsBD3+qz7sNzxHALi2KnVWZbqhi347XZ8HMcXeGE3HM+bKkKJ/RkJ6c0ofhqAwp5ign3Njtey6hLkFKz6sF9Oh6x6e80ec58nAsIQxRApzLgojJ5lUKVCb7dyhtJpkeGrCNVuVqiwe5dttQVNeWk8HHsbBznLF65OKy7tJ9CjVRibeybSLpNNZPDyFk2H4UGC1jSbwRWQM9kymWRruuIGrUdLLtvHtbakA+RVDItKHh+tuchA3ghtsBw+0x1YTzNg/uewokU6Ts6g1xcYn34PKCuoEbAm7B0xijw8HRaUA7/1lSb6XupDcddAMsdXDR\"}}","sig":"b4df17fe73796261f380dbf59cd4c253691f7df7c5ed02ea7ce17ff08ece4e1244ae692d384577c3d5a4b3a52ed1823f4e21a3b709fb8228966e01fd9cd96446"}
|
||||
{"kind":22795,"id":"51840075a161979e0960dee2cf985dcff29ce8024542224f1e8d270f05d266dc","pubkey":"146c70d40e1f4f96528309629258f8dc97e9a61aa53e54e13b999ba5d2276968","created_at":1785676829,"tags":[["x","2t6r5t3g2w4ke3c5q5fe155b4733m3m4d204h"]],"content":"{\"peerId\":\"9IVDCiG4hlib9t5iG017\",\"offer\":{\"type\":\"offer\",\"sdp\":\"223,148,124,74,154,14,67,150,164,85,250,22,207,70,113,66$GQ31axJJQOIow+lfqV1YKLNxUh+V1rAioseBNHgVEhYONSeICwYKTUGHaVGQjflxRs1atY42oGidpCqpxjDXdpUgIQb3/EzXDCEydaqqyLy5l3m25dy5k7ufZFX15VcXR8wcDi0RYRFN/iGE9mSHsLV5w6lQqv3jpTsKAeFYqwCkvzh5WnUwM8PvmR+PYFTXbb3HXYwJp76QGR3POTyJxvijjtjkP0Or3V1JrPLxMDJIeNlNjWi4r5CzFzO79ymTE2/5b2IBlN5FaZbTYxRvICaKVA42gztpDDUFUaOfsS74xCun+wQfnwf4cefm7h8HochY45m/43oZ+B69kHmQlXdzRDtxPyW4Nlhakp4+fpvMuaO+AbAjLuJeKxOXbBdheXjQ8WBJyJU6xXgDmUy/x8cSJtMfshnAR86ENlKSe5TNR4ZGEkDGt8ZibqtHzr3U0lUFhfCNTnqdGhPKPFCr89W6ifbWkY6Ap+8DsiqzBZdS9Jm/rj6dBpADWXu1eCH95TNRUhA344wAGCdLITq+5HFEG3U1+F9e9Kv9anp+QXFRo1DSs9sBdKIzH2GOoYgvv/amzP0t/ujF0jVC50YbJ+vcD2Mk738T/RoSw6fenLHR+vuSo5GEQZKfIqsDnLol9MuHwilistA/EiTl+g/5oVoZfFz9Ka+paRsyE3jVx/r9q0/XqGqCIVGPuq8Zq8Q9upXxHZJ6GDWWDnkbW/Jdh7lzkPEgPk8A6mhv6tKVo9yKPGQvcRC6ir65pvnpr8LkcmGD0ZcmyUJZgcS7QYtHdFr5nEm97uOkDEcjWNsEY4BGuZLquE5YXA/FEKT9OfF9IGANGeFCejUxYC6wmfBgNKPHn4y8dwF4O1VS2dyzvIEMeQOWZfLX18Rfzwer2DUqhy9Vug0UlH85Zg7BO3xsd7HckWkGhaQe9/OoYc/J7qu7kgGGaJEot4tkVx1jqodqfQ8231pFSFYAPzqO7ARdk5Iah+4o5leT7/3etL+NGI0P5NRngirLDwDf3usWIoP8rZHH3X80VvUdSaXfNNVIfGtVtVEoldpJdLMgBjjrZN4bSfw0Vrxq8ARXPF1XhziTKhhUknepY9kinMynYwebwmr9jxFJhFOvrh40Pm1SNAEegoMxrBoz/BfSUuFlo4ZUOdT4H29npvGYrQQ6icPfu3ksOI/a1jEzIlf3Mi97gW3q+rVj4vNVx3PoqOi6Ndbp/vSqa3cMNJXXPfTQ0V8w+4SW/PwyVqnhIl01kqxjNdtdis4EMQ4ceGJ3MDbgCdLA6lG6tGvogy4V9/esn71GfC/fD1Wz\"}}","sig":"88644bb037cd5b75c311efc06f45f39c6e8100615abcc08ed0f285ec9e282733a88838369e318af75e2687b7bdd6d0904a4bb90fc2f16027755d3d060f5e30e7"}
|
||||
{"kind":38501,"id":"bc1428364c22cadcdda9e97f47a30dd3da07d32bef447c987e007e6cf33b7cbb","pubkey":"8b46fa734a7230497197cb033e6f10e55fa400e90447cfe5651c9ad30a9f7b4a","created_at":1785676829,"tags":[["d","btf-descriptor-2"]],"content":"{\"created\":1785676829,\"enc\":\"97f504ab5a031b93d29a813de02ccbec80f0345b11ade65b66cc0f89c8470920\",\"meeting_node\":\"90.156.222.107:8434\",\"pubkey\":\"8b46fa734a7230497197cb033e6f10e55fa400e90447cfe5651c9ad30a9f7b4a\",\"sig\":\"eb1094bc2e5aa1c3d49bb21f9ccd24b96a8066e1efe7400d649c97a03c7e599b1f5c820dd700a3502b675c52513bd0f2bea34a4dc41fd4c101dc621e4971378c\",\"v\":2}","sig":"2053e323b44d3fdff3f956edf9a61ceb3651ee517eea4bf11adbe7e4438fe63234aa7304ed3cf5e13455ef6037576e89c6587a771e514540624b2f4157531e27"}
|
||||
{"kind":20001,"id":"6c2fac4c1a3d24f3c83db08fd810cbdb92e47b48b9b0bb3e54ff7081882250f5","pubkey":"bf5ceea34cb45bd0d4903e83c62a49ba1c80d589934d83fd4b2c616aa7c3df57","created_at":1785676829,"tags":[["g","u3"]],"content":"","sig":"ad150f48ecf1ccfb096cdcde24a846a8396d1f8586e238a778916836c78a56752070c2833ec655350d9241cabb4785dc4e48501dba5ee1b35ee442b80f677de5"}
|
||||
{"kind":7,"id":"c138c6daa6626d75a2621f1c15729f63abbc682773bbfb278412b6545131ac5f","pubkey":"e4146d1d7fb2f7f6e6b3c799eaeaba6f7446fd28ccea2592671cb239a13f4d81","created_at":1785676829,"tags":[["e","f148576d2a0f9754d8006ea10f31531c600ca6abbbb64f92b13146ab32316e12"],["p","c79200d36c345e41d46c135b30077b2f15d43cb286069f1e4f2e65c09162a900"]],"content":"+","sig":"f02914b8b9345f45f4ee7cbdf7e058e3a15c976436df11b71ebbbb7f62d08bfbb8398cfbd202095bf9dd3d4bee6ad597d9289d12c8bf32a8b57323666ccf5028"}
|
||||
{"kind":5,"id":"05a69cae2f6f03f85d49ce912ffb234405ebd40b4619afd0f48e79f4c9afaf8a","pubkey":"3b6b4b29eb5b65aedb5d5291ed382d64dd62c555911380bd0dd27f160446a025","created_at":1785676828,"tags":[["e","64b710cf656b37c7d2df8935752af4914b88f8bb1ce3536c1315da43b72b6820"]],"content":"","sig":"f62372888a6e0ecc9b865ea00c18425f46984212a929441def9ca841e7216f95e4ceaa6eb39e25dc8a533d3455dbc1191450c053e894cd7a6a752b3026694d86"}
|
||||
{"kind":22850,"id":"d502724e18c11af192ee65a8798828a5839de91251fb80dde196e09751600622","pubkey":"972698b75bab763abf02e914c05ab10ba92946d949e44994914bc8ec0f0c8356","created_at":1785676828,"tags":[["x","154a6xc4s1134333k6j1w3i5z2u4x2g27363w6q"]],"content":"{\"peerId\":\"E4BBrrzMaIncSQjB5BIY\"}","sig":"ce077337ae276256eb927f006fe5ebd9062272852330909b8e372176ac17e9cde6c75f95a91a8a31971fd50e39d3f09bb78a8469444feaf934e220ffe295b1cf"}
|
||||
{"kind":21059,"id":"c70dc8831fdbe3c9e881ec501b0164baad462fb4cdf966b232771faa15faf8d1","pubkey":"f6618de562d05fc1544e473cd2de7d19172886a84413f09be3580091b0c6166c","created_at":1785676828,"tags":[["p","d71691e02c10d3564530a86b51598532eef5f3d62317ff93cea2c3b9c4d4526a"],["expiration","1785676949"]],"content":"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","sig":"15cb4aa077947993d94481c3ec275fb4905a66a0b0309ed2962170c104900322ef9cebdfb10c28f55e91d2ea1c5ab66682d570f8146db4b1e35ce71eb465ba15"}
|
||||
{"kind":5,"id":"4465287c1593ab85700231ff2bdb75b84cdcd7f1110333bb4d615fad2d73b147","pubkey":"fde8ca9b4a9d1f5d2ed8b82ea13766c37bdbf6cb50bd272d642eaeacc713563d","created_at":1785676828,"tags":[["e","5982eb4b4dc892cdaeb1a37d3329c3b11633be2b19401d1e0f2881309be0616b"],["e","64b710cf656b37c7d2df8935752af4914b88f8bb1ce3536c1315da43b72b6820"]],"content":"","sig":"806cc8d8fb44a1b2fddc62950e525f42bcc3dd184ded730235b0c4bc36c13017e86a512f98a3d005c20affd8a546fcdb99ec3c90e4550a47e1dc2034cd86cb16"}
|
||||
{"kind":21059,"id":"638a053daeb7e0a7a0f36a2e2b1c0e2e36d25c58142139f99f706244fc7c09d8","pubkey":"1a54ab43a4bdcf983de90f5bcb7ec25cb61b7cee8a5a719faa7c7f0abdbbc88b","created_at":1785676828,"tags":[["p","92e744f3d9e8ca5888da31ac871ef9eed2a0b198ba08f417937cbff3030b0000"],["expiration","1785676948"]],"content":"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","sig":"134ad847b73bdec6eb45c66e2971175bedd00fb7a6c1a6c708beaa65fe8d4089fdb58e3c347631cb298e209df1a5183a0b84513e271bb8fd1f7a20696da68c66"}
|
||||
{"kind":22668,"id":"ddc1eb28e2625a90f93416b40326661d5f5b627056519d83e58625ea117a5a67","pubkey":"645d864f8e4df2e7961010c726ca1dfee79c1f849e89981f38c67954ab27ab44","created_at":1785676828,"tags":[["x","3h4b5840o6s3o6aq23294k3l3u32544u3s7266"]],"content":"{\"peerId\":\"XLa4RppouLPlwZlPEN1L\"}","sig":"9bf8af313f3c5596cb8f4d0696b8d72cd268af14bfaa38b831caafe1248eb58a40af81fb3a43fadd6491b086f811f18fa6c4422548ec58c37fd3d157f4bf8eb3"}
|
||||
{"kind":5,"id":"0b34123c6c388de6d35d821348dcc9651adb2eec495f020f9bf29e32a9ee5282","pubkey":"a6cd35843a1471debb1b174b5bab472d9f5a2e2391e92207c2279468c3e9ac9d","created_at":1785676828,"tags":[["e","8290a6025d0f18c48f30f52570181ff53bb29b44cb2af6234857b7792650cc17"]],"content":"","sig":"a00555524925631aa1e50be3f5bb87518191259643f46806d55e13a5c791a3f073eb82e8e442b0979f269eaf323c846b8d3e0bb6185f622c1f734eeb444c4216"}
|
||||
{"kind":5,"id":"290ae3e79db0ee20be75bb4368fcd1ca3e4e97fce13390c135f5a00e24daab6d","pubkey":"f562b3ec661872d7e53a9babc2e75aefcc3d1d658aa32070d7a6e3948dab2af2","created_at":1785676828,"tags":[["e","c75edbfe2657b06d905d775d476618bc97a68398447ed36b5b53e381ff34b99b"]],"content":"","sig":"ad8cb04b8a8d861e079d122c5e459fb9d505a4e024fca20d606df2cb0cd5a5701fff566d0b52e22d978e76eb2bfa8b115a207a1de074dbb307bb8b8c1b0bb614"}
|
||||
{"kind":5,"id":"da568c14b08dd42c0455f01d8239aade88c77ce1994de16260dd198b308a3421","pubkey":"b454400c0f61af322680e46825a10c69aaa4226be2f474dc21fab2c7271d4ddd","created_at":1785676828,"tags":[["e","098b11ac3a658a5f260afe741b1e702b6ceb795073d0fd67f2b39893c9f5f1a5"]],"content":"","sig":"860316ca6bfbf5032c9086ae56d89b65085e4adb6c083f0f2a5b369cdf4951673b4a4dbd565190b071d12681f11e55495b3a354a41b85a19f68c064d3f010bc8"}
|
||||
{"kind":22668,"id":"2e19b89f9daadb9436e59f893fbe4cfb06d233052bb1aa2e8e2a5f2ded14bd1a","pubkey":"983451ee5aa44cfd054418a4b4d61389f6cacfe5bc8ad63f247040506a7bc8f1","created_at":1785676828,"tags":[["x","3h4b5840o6s3o6aq23294k3l3u32544u3s7266"]],"content":"{\"peerId\":\"MOfdN8BFCzSXK2ClbLZp\"}","sig":"7a7fa69ff865ca2548336fe3bb0c8fc72033822efc524f28f0056654fd8f70ddf0c4d0bf6266bcea2d320204fd7e87b9304ebfddbbb46dd528816e7a5adbd93d"}
|
||||
{"kind":21059,"id":"c76184eeacfdd807619fc4cfea4d898e87cd44a25b4f534f22f4de068974a659","pubkey":"756284430945b4e12636df19fb8892364d6b685f15724c3cd4cf8089aebce8e8","created_at":1785676828,"tags":[["p","c3d2d513091f404497181534e7965d2b80da38f82ac76bdc8faa2ee9b20b7fe8"],["expiration","1785676948"]],"content":"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","sig":"8a7c9e47f5e301802cb6eddf0c11109a161c7873aebfc4bdfb6660dd4da3d772d4c9f13ed6708a6726770a19a931b0d912ad7ef9b2289e1471e0503b64a9de9c"}
|
||||
{"kind":22734,"id":"c4eb84f16a0b91da08b80674809ff770cf2fbbbea535222f71a6f70b1afaae2f","pubkey":"62131eedf03e285f05e7327cd868d6cf04567658e72f09f6a027a2cb526491b2","created_at":1785676828,"tags":[["x","2n2c211h5a65204bmik1t4y663e1k2jq1j2w"]],"content":"{\"peerId\":\"5JyB3m4D09Af6swaeL6g\"}","sig":"b025b0f3d0f2d5de0256a1401816a8393a3109bdb2446b4a4986fde228438a1837a54a3b0d9debda4528c9e840e6acd458daa7d7e88d45c735ebe0149868160d"}
|
||||
{"kind":21059,"id":"f8bb284d3b89bf6edc85ac8157f4fe146b1fe1201164a094e85dfdd6bc9004e5","pubkey":"8a67ab6ff23ea573d894131bbee2f3b49dddd2cbbe9c532b0ea8bab5dde6c27e","created_at":1785676828,"tags":[["p","2b794b141e7490a4f53e23d41286cecdecdc1bba9aac19dc92ddc3984d361992"],["expiration","1785676948"]],"content":"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","sig":"726a670d5ca1bd6ce671f3c34ec0f4102cf8a9253380154b0621849290fe856b805fb69b772e55cee187879f4a4759e044e679c03455e513764ec7dbc50bdcf5"}
|
||||
{"kind":22734,"id":"69a3ed5c758ed45a82812314ef3dac047107069f56f1f938dc6e26a0d87ea86e","pubkey":"fe577acc08542c36add5fd831b6ca9e248d98f2a24f9648ec71f42947e289710","created_at":1785676828,"tags":[["x","2n2c211h5a65204bmik1t4y663e1k2jq1j2w"]],"content":"{\"peerId\":\"FjdIMX0nehvvfKeE8uS3\"}","sig":"8c52eb4118de1f91350941bd08b6953d6681afce8158c4fdf2da1addf2e15e07454a671bfb8b5600bccb4544380b3f2ff49161d22330a1138943781392a1ff75"}
|
||||
{"kind":38501,"id":"8bb6cd8e927c497c1d0d43380fae119b3e1de4bbed9df532ca8c85b956508b14","pubkey":"be43349f0292354b71e5857cd3ef5577e4d8882b50d5853b8d0d2e6f33cb9b17","created_at":1785676828,"tags":[["d","btf-descriptor-2"]],"content":"{\"created\":1785676828,\"enc\":\"ae5076051e63594c2bbaca4fbd1dfdeb661276f7bfc325f7b6e6e227068e6248\",\"meeting_node\":\"90.156.222.107:8434\",\"pubkey\":\"be43349f0292354b71e5857cd3ef5577e4d8882b50d5853b8d0d2e6f33cb9b17\",\"sig\":\"9199cc8116a79d3de74e28e1171a5f88f8ba0d3ee58fd620a9bc06b63652f85b9b03e583b4a3f5960a2d56a1f4d9c3eb2731def42d75bd28ee6ed7c65609b4a1\",\"v\":2}","sig":"de12e3a0b7ca656aad163076e2f32e5de2878a55b163e7ddad075e6e8ae9d98d4aac1502bb76f69c03086d4e7350f5d32686dba1295788ceb9dfd4049cc657f2"}
|
||||
{"kind":24242,"id":"967ecb7f628c4c40e6142b01d1e4fcfc021af09ceffabdf3e6e5616acebbba13","pubkey":"a975b6d0b2376a560d115745432db9828936b586e85baab34b0faedc1ec69cc9","created_at":1785676828,"tags":[["r","5ae4bcc88c92069957e24564ee8f8f0bbc50aa0ec33740fa6df513c5b4261c58"],["t","P"]],"content":"{\"t\": \"P\", \"d\": \"i22abIUK979JGbf+XiW0SEkynRl3oeD+ub6fdvXs9e1HiuSYhHzExoBu9kIDplEXnBZLQ5GckxdvfPVMCI5wLRruGhCQ8FyJxZMN3BOlkS7ExKGTXSCX7ckXAro=\"}","sig":"9ae34fa8b69db93c5469d472d3fe3e357370412926cbbd161c1c65ddf8a01531b0cbd184f46531169d738dc97f9ad647a8ad0eb0b8f768bc1bd05b21e424e086"}
|
||||
{"kind":10011,"id":"9fc9a8ddbcea381b42dc97807b9eda3e22ef405d389804ad1ed86e2c72f39534","pubkey":"5de310432a95a13ba1905b5c78b511b931fa7efa86bea15057ebe16424cb9273","created_at":1785676828,"tags":[["t","relay-monitor"]],"content":"[relay-monitor] health check at 2026-08-02T13:20:28.031870+00:00","sig":"aa3d24c702a8172c6a28e59ab84ef4e831c7ebe2153f19dea71f92cdb8d4c35495669bc5eb80df2c9c7eea273d919fbce1e26fc226ab22cd4cfa202aae6e0aef"}
|
||||
{"kind":5,"id":"a9a5a2840cdedd585ef53eb3fb086119b09d6ec97614a19e7014edc8e9fbfdd8","pubkey":"abb85588adc1f9fc70c07c2d6119c7ea8483e05674d85e89fd12fe26f37d7b80","created_at":1785676828,"tags":[["e","6baaf169c5a412c48bc05796ae31420fbf0abf7f4425030a02a5b5fb6e89095f"],["p","abb85588adc1f9fc70c07c2d6119c7ea8483e05674d85e89fd12fe26f37d7b80"],["k","7"],["client","Amethyst"]],"content":"","sig":"49e4211186e0ba933c513078fad6bc0e40c496573adef997be03e343ceff2dc309616a22f44b110ae2d7ce840f969140ac83dd764d4afb0c7e52fcd47442aeeb"}
|
||||
{"kind":24133,"id":"65468cf8859c2651655aef77fc73e162475671a1b9fe78507a75e8e1b0fce9c7","pubkey":"adc534e19063daed4a5fcffafcabac5c69ea92781fb870b800ada248494388e8","created_at":1785676827,"tags":[["p","8bf629b3d519a0f8a8390137a445c0eb2f5f2b4a8ed71151de898051e8006f13"]],"content":"AnvGOKiC2qxlzPRhokNkl7/Mv18NnRtNUDK3VpuOS8rGYCpUPhpICdZpq+OUZWQ12gFqaWNWEinqLyR8FXRCGKxeJ5iArhWFMF2+IpFe4mCj3Kg/bdu02V3waBzg0T4rAOaRWqsWQBSUz8ENTaeJUUhAyx11INFOWvh4MEh4ablqPY1ONZrMlfOrK5h/rqNQ0b9zbbzoeocfSUKrblTU/TcAa7bm8EnCOGjkyvfkW0PHbIND12NZG/zOBmvQIUTOkCkC","sig":"2e56dfe53f064ddcd45d09ef9211fb7d685cec414fd75537504a023be2fb8ad13b7c2ff34117e1b467902ec7fb207bd5bf17f28f83569ecbbe724e484a560767"}
|
||||
{"kind":20001,"id":"828803cdb45f3fe3f1d3ad30cec52a0a608cd44aa575eb61e4781236d206dac6","pubkey":"e1ef740bbab4a0d7fa489084a5dc41bd3c829bfa80cacbd2c3fe104ef41b258c","created_at":1785676827,"tags":[["g","u2sh7"]],"content":"","sig":"e3b6b73b3d9583c71795ed5d9a73375cca25202a48f9083c6e2fd001951ab60fbdb03f30ae4958570dfb62999d8c776d5cbe6e3f0278591873ebabf0e260d40e"}
|
||||
{"kind":21059,"id":"add2aaee09d5b4616d2688c3c1acd0c093f8f3e609676adb8433e7a4802b3d80","pubkey":"362e1183392e4916b8c309fd22d11b54ff7f50fb31f775c4ed7cb6c6da4cb9c4","created_at":1785676827,"tags":[["p","904d65c28c1bc185277f9e60de40e9044650b0c59e2729a4458e3c4ab6ba4efc"],["expiration","1785676947"]],"content":"AkhKMxO79qb4V9y/vsLNDafQDW+aX/gcjZVe4UG/YK68ci8NRJ7KtAEX/NZCywsAXgg9gGIiXkl7HGvsGNa7RB3RFmpgoyW1aygnhzIOjsDJp9XVNtwXAKVHrjKdgBGvLNhXZdS4u9iEuzRSXSZANa9CgV8MHL4rW65wxl+bxPZzRfpNguU+d51GMNI61MemB0+rtqlSjGGL5oprK/ymgUM/aZVywWTsVul947HZedRRTH0n9Aw2MZiIEzeZxA+UUN2gVWrlDirrV32MfMl2qv9IngRReBI2TSJSCysO/3gMlwi2ES8SHxslrw09S1XDOe7I72EneqG6RzM9pfcWavRwR7cdLGVeeAa0f7cN6i70beEpPscRz6Oit7laJoBRmpprXDvWYceqyCrJqEtSkXaAp2CGEXrgilS8hOpqW3sI/qWfK8ISFudzfRBYso4iLRNMTn/6zpkQ8beoKnqjOcirZqmtv716GTqts7mJ9RV7BNAzms/O+f+Z4UGk4ecnA6ZFjEZT3hBqR+3jL/mBKm87WGvCFqCdmOh0cHHCaUBp2QexfoJC+nB7VGmbWxXCtcT71FBlK+dQUWkPR4rqrabth5kHMJ939n7eNyDVl+g/SZ9cD76Mf6akPciHlyjqCXbuWazbEtJ0+HDx4kDd0OW2zgpyN1zbkPIcAOCRSKS5iBU9b8GUwwHSe0mg7dxHAUspZx1sU8uV6gLVkHYMVN+aSMXGVreK16BIM1TXTTvPQpXuGY9eL5Qc7jbr4RH79fusb9g6gtSantskzixWjcBq9+kiEKu4PdfKLipDOgjqPmiSkWo+9UzhJL54L2VZjScn2O3E2w7funrvZ7/JXrkY/T5b/u+7TFcPcCuu38k3eiZflDRN566SikF/ugnycNjdcsDY2XLA32AzztPsoNgFG2+Qa50SPrJw+hq6Ty5eCkZHmai2hSWlI4q92+3aUi/2mlBU5ZYxls87gZiSqppmSxD1Jb1F+Hjv4pFB6jnBXTnQm0033F+D56EzptnEHYRUrR7wzjlBn0ft7yct++g6znqC2DGpr2aCHt48Hw+FEIrfpOQmyToMAOCCxKXdq3jqE/bqKea16WauBvxQpMBkVZmf30JUBTBfSBmjUxcjs0e3NGKU6M0vT3MntpGj5YBLC8XADcl2RNPzEvw784rDtRqOwsJ0aDFLTErekDfqqRdlaHaHQ3BKL+KU1XiuRZGQuslpXfckHukeKANhMwyX2ERk1uGChU/GMsEdFIJ6n4BcSywAJpZig8QtlYSuquX/Hz8LF/czC8SMSorGl01hZPEM5zHLr9CjHGyX19GQ5dGXfqGJ5b1t3B3HnJ4ZDYQWCwrJh3FHkDbs6ka1MW/gaqARuY3iJicbn4l17yCI/OMtOjAUT+/sItGVkupzZq/WcsqzexjF3SAHAE73Vp2AY7CEdzlHmMQjIy5amYueCNne29O0P5MgOFA4Ecd438oDrsWpL8hx4MWoI0UTRJV9T3Pd0obLwexWBajEjEeSwKj/bBFmGEFb8dG21MfGQdFqNdDtAWnSNgNmg2s4NKHCGYtOZqS5EVjIkoBM4zeG/pxhaCA7TaNY3B0VWsfIENpThA3DdfogUPXYLCAVzI4mDw7ESNBIx41JeAw8GIgofBRDxXrNm9V4kRFq/e4AlgFr2SRvQl3rHTnMKENwq4nkng3+6baXpP0AhK+zKt8NbL+Sp58fW7nitvMH5KkT5nuXANCU2H5ZEKo+kZGDSRzSrYh5srSAOuumCLTxV9rOOyKYfhjn1iBKMP6FXdj82Ppscx01ugLkmD34vpnsP26NVKlhl+ur7xj9buLGrzuaPXIumYZHa6fr3HdPsPSDm8MmJjpu8NPF/ALRcPZLh2Ji4mpA2dwKv0Yy0dZuvhE5D2CklHoy8108HSoaVuNGQvvzTIm4Ji0DcbaUG1+/yQmG/TemCpRFB/kkQEVrOcvkExDITQpIXyX0n8pvCCe064x3nZScMUMgjI6xsJm+OHWVw52aF48QraO/wNdFRVo5SH/vkZPj1JY6s3k6P72SKn9oCfuLPX7FdDVi9zB+jmSM11mKdw2DmWLW2bCrm93AXkMRSVD3e+3tDUYrtf4Pb1I0tbr/Zp7i49lF0EZTmv+at1p04b6Kfuqm7bjs68Ew6Q3Tb9Pb2fvW2E871YPjSj0fYYRprKap3x1Jppu7E9COGSG5/xE7FAwgAHv6dbHjWgyz2CbrpXWaNjPrRRDRUfQdtwnNGyo0vMn43n5ryvn+ZGYeJ3hQvqciOoip7K24AK0WK9jjElYSxFNb2bKEs5Xe1mVl2SUVZx95+w1JLHFPpOKt5IfP1x5BQ/w0ZBnsgOTcvPh+YIqE+Z/vc4j3uKX0BIPM49oOb7eBbNDKdEjMMHLWF3tYO8ma70Urb8VlZ31cDWVgMSfbYuS3wWkJzB9+giRa1IY0lj1xunB4JNQKQR+HaXVqRP2URwYdJlelrCuIYMJZAv8lhnF34KSff5LzIJLBRZpRTLjVd9IH4sVTFYTg5yCFJo3+FzKCuoAUMww1JalkeGbe0pUpwceZWVdlVUEJVTKr1NJKyMhjEFmb2p3nQHYEXxxe0PmZVAgiaFqbtvfnBu5Hd21p+ARYhWuhG0zYD74W7lI+d1bqQgJaaTTdfLZgpP778jL7BLp+3EOrJlziLnq/ZOhoLnJJt2qr/zEsrR0dmLQzi07F8lpdKEhBHVL4DZPvO6QgO2kc7D4lv9JhCGIAhqaCFN+x+FagxsSTBPO6aGDzoFBv/+NGzdoPDBU5eN+jW0nv44tCiwfdMOryPgtC0WGj1ZoPgYLl","sig":"0b358a00881890d1170b455ad5f23800a8620026939af6e98fa1d12bf5ac052b57347ce0cb15acf46c2b800be9a1e4f4ea331ef3a6186920db69fc9c43c0172b"}
|
||||
{"kind":5,"id":"8cb0ebc4d6307a3df82ac8e660e4ef9e7988cea03fde286f21277ab17e67991f","pubkey":"0a4f177b087b133099e52e5b50456f0d4c832db60c0f35d3269a6a055f25522a","created_at":1785676827,"tags":[["e","ad604a106024742fe765459c43b7f45f2c7cc3123454d4d517d34c3c539686f4"]],"content":"","sig":"217950b519bd5343ca498e48b4b04637ce09ec405d211913d85201bdc76561d61b6628424ad33dfb607c0150fe63b5197230b66991ce011b8dea3734cba0b66b"}
|
||||
{"kind":21059,"id":"c3d841341e03f0f22b2e6e7cd0811954f7590ff69c785965c2afe1e91cc6558a","pubkey":"608696506aca54466d337ef6dccb9cc714dd94ca1f88e91939fabec7d3114024","created_at":1785676827,"tags":[["p","08e99116ad58c5aa5e6e7dc40668d5d7f2c080fc9fd697ec0aeb76880cf54bd9"],["expiration","1785676947"]],"content":"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","sig":"887844fc5f7ce096fe528ed0a1891992556d30ae6f3e9a06177ce638f2a0dc21433678ad30483ddef40584048986d2d0cc3090975b9c96e13d8ad163b5aafbff"}
|
||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -0,0 +1,774 @@
|
||||
/*
|
||||
* cache_all_test - feasibility test for "cache everything" approach.
|
||||
*
|
||||
* Connects to configured relays, subscribes to ALL events (no filter),
|
||||
* logs verbatim relay responses, tracks kind distribution and event sizes.
|
||||
*
|
||||
* Usage:
|
||||
* ./build/cache_all_test -c cache_all_test_config.jsonc -t 300 -d 3
|
||||
*
|
||||
* Output files:
|
||||
* cache_all_test_raw_relay_<ts>.log - verbatim relay responses
|
||||
* cache_all_test_report_<ts>.txt - summary report
|
||||
* cache_all_test_stats_<ts>.json - machine-readable stats
|
||||
*/
|
||||
#define _GNU_SOURCE
|
||||
#include "cache_all_test.h"
|
||||
#include "config.h"
|
||||
#include "state.h"
|
||||
#include "debug.h"
|
||||
#include "main.h"
|
||||
|
||||
#include "../nostr_core_lib/nostr_core/nostr_core.h"
|
||||
#include "../nostr_core_lib/nostr_core/nostr_log.h"
|
||||
#include "../nostr_core_lib/cjson/cJSON.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <signal.h>
|
||||
#include <time.h>
|
||||
#include <unistd.h>
|
||||
#include <getopt.h>
|
||||
#include <errno.h>
|
||||
|
||||
/* ------------------------------------------------------------------ */
|
||||
/* Forward nostr_core_lib logging */
|
||||
/* ------------------------------------------------------------------ */
|
||||
static void nostr_log_forwarder(int level, const char *component,
|
||||
const char *message, void *user_data) {
|
||||
(void)user_data;
|
||||
if (level >= 5) {
|
||||
DEBUG_TRACE("[nostr:%s] %s", component ? component : "?", message ? message : "");
|
||||
} else if (level >= 4) {
|
||||
DEBUG_LOG("[nostr:%s] %s", component ? component : "?", message ? message : "");
|
||||
} else if (level >= 3) {
|
||||
DEBUG_INFO("[nostr:%s] %s", component ? component : "?", message ? message : "");
|
||||
} else if (level >= 2) {
|
||||
DEBUG_WARN("[nostr:%s] %s", component ? component : "?", message ? message : "");
|
||||
} else {
|
||||
DEBUG_ERROR("[nostr:%s] %s", component ? component : "?", message ? message : "");
|
||||
}
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------ */
|
||||
/* Shutdown flag */
|
||||
/* ------------------------------------------------------------------ */
|
||||
static volatile sig_atomic_t g_shutdown = 0;
|
||||
|
||||
static void on_signal(int sig) {
|
||||
if (sig == SIGINT || sig == SIGTERM) g_shutdown = 1;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------ */
|
||||
/* Per-relay stats */
|
||||
/* ------------------------------------------------------------------ */
|
||||
#define MAX_RELAYS 64
|
||||
#define MAX_KIND_TRACK 256
|
||||
|
||||
typedef struct {
|
||||
char url[256];
|
||||
long events_received;
|
||||
long eose_count;
|
||||
long closed_count;
|
||||
long notice_count;
|
||||
long error_count;
|
||||
long disconnect_count;
|
||||
long reconnect_count;
|
||||
int is_connected;
|
||||
} relay_stats_t;
|
||||
|
||||
typedef struct {
|
||||
int kind;
|
||||
long count;
|
||||
long total_bytes;
|
||||
long max_bytes;
|
||||
} kind_stat_t;
|
||||
|
||||
/* ------------------------------------------------------------------ */
|
||||
/* Global test state */
|
||||
/* ------------------------------------------------------------------ */
|
||||
typedef struct {
|
||||
relay_stats_t relays[MAX_RELAYS];
|
||||
int relay_count;
|
||||
kind_stat_t kinds[MAX_KIND_TRACK];
|
||||
int kind_count;
|
||||
long total_events;
|
||||
long total_bytes;
|
||||
long max_event_bytes;
|
||||
int max_event_kind;
|
||||
char pubkeys_seen[65536][65];
|
||||
int pubkey_count;
|
||||
FILE *raw_log;
|
||||
char raw_log_path[1024];
|
||||
time_t start_time;
|
||||
long duration_seconds;
|
||||
time_t last_summary_log;
|
||||
cr_seen_ring_t seen;
|
||||
} test_state_t;
|
||||
|
||||
static test_state_t g_state;
|
||||
|
||||
/* ------------------------------------------------------------------ */
|
||||
/* Stats helpers */
|
||||
/* ------------------------------------------------------------------ */
|
||||
|
||||
static int find_or_add_relay(const char *url) {
|
||||
for (int i = 0; i < g_state.relay_count; i++) {
|
||||
if (strcmp(g_state.relays[i].url, url) == 0) return i;
|
||||
}
|
||||
if (g_state.relay_count >= MAX_RELAYS) return -1;
|
||||
int idx = g_state.relay_count++;
|
||||
strncpy(g_state.relays[idx].url, url, sizeof(g_state.relays[idx].url) - 1);
|
||||
return idx;
|
||||
}
|
||||
|
||||
static int find_or_add_kind(int kind) {
|
||||
for (int i = 0; i < g_state.kind_count; i++) {
|
||||
if (g_state.kinds[i].kind == kind) return i;
|
||||
}
|
||||
if (g_state.kind_count >= MAX_KIND_TRACK) return -1;
|
||||
int idx = g_state.kind_count++;
|
||||
g_state.kinds[idx].kind = kind;
|
||||
g_state.kinds[idx].count = 0;
|
||||
g_state.kinds[idx].total_bytes = 0;
|
||||
g_state.kinds[idx].max_bytes = 0;
|
||||
return idx;
|
||||
}
|
||||
|
||||
static int find_or_add_pubkey(const char *hex) {
|
||||
for (int i = 0; i < g_state.pubkey_count; i++) {
|
||||
if (strcmp(g_state.pubkeys_seen[i], hex) == 0) return i;
|
||||
}
|
||||
if (g_state.pubkey_count >= 65536) return -1;
|
||||
strncpy(g_state.pubkeys_seen[g_state.pubkey_count], hex, 64);
|
||||
g_state.pubkeys_seen[g_state.pubkey_count][64] = '\0';
|
||||
return g_state.pubkey_count++;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------ */
|
||||
/* Raw relay log writing */
|
||||
/* ------------------------------------------------------------------ */
|
||||
|
||||
static void write_raw_log(const char *relay_url, const char *fmt, ...) {
|
||||
if (!g_state.raw_log) return;
|
||||
time_t now = time(NULL);
|
||||
struct tm *tm_info = localtime(&now);
|
||||
char ts[32];
|
||||
strftime(ts, sizeof(ts), "%Y-%m-%d %H:%M:%S", tm_info);
|
||||
|
||||
fprintf(g_state.raw_log, "[%s] [RELAY] %s ", ts, relay_url ? relay_url : "?");
|
||||
|
||||
va_list args;
|
||||
va_start(args, fmt);
|
||||
vfprintf(g_state.raw_log, fmt, args);
|
||||
va_end(args);
|
||||
|
||||
fprintf(g_state.raw_log, "\n");
|
||||
fflush(g_state.raw_log);
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------ */
|
||||
/* Subscription callbacks */
|
||||
/* ------------------------------------------------------------------ */
|
||||
|
||||
static void on_event(cJSON *event, const char *relay_url, void *user_data) {
|
||||
(void)user_data;
|
||||
if (!event) return;
|
||||
|
||||
cJSON *id = cJSON_GetObjectItem(event, "id");
|
||||
cJSON *kind = cJSON_GetObjectItem(event, "kind");
|
||||
cJSON *pubkey = cJSON_GetObjectItem(event, "pubkey");
|
||||
|
||||
if (!id || !cJSON_IsString(id)) return;
|
||||
if (!kind || !cJSON_IsNumber(kind)) return;
|
||||
if (!pubkey || !cJSON_IsString(pubkey)) return;
|
||||
|
||||
const char *eid = cJSON_GetStringValue(id);
|
||||
int kind_num = (int)cJSON_GetNumberValue(kind);
|
||||
const char *pk = cJSON_GetStringValue(pubkey);
|
||||
|
||||
/* Dedup via seen ring. */
|
||||
if (cr_seen_ring_add(&g_state.seen, eid) == 0) return;
|
||||
|
||||
/* Calculate JSON size. */
|
||||
char *json_str = cJSON_PrintUnformatted(event);
|
||||
long ev_size = json_str ? (long)strlen(json_str) : 0;
|
||||
free(json_str);
|
||||
|
||||
/* Update relay stats. */
|
||||
int ridx = relay_url ? find_or_add_relay(relay_url) : -1;
|
||||
if (ridx >= 0) g_state.relays[ridx].events_received++;
|
||||
|
||||
/* Update kind stats. */
|
||||
int kidx = find_or_add_kind(kind_num);
|
||||
if (kidx >= 0) {
|
||||
g_state.kinds[kidx].count++;
|
||||
g_state.kinds[kidx].total_bytes += ev_size;
|
||||
if (ev_size > g_state.kinds[kidx].max_bytes)
|
||||
g_state.kinds[kidx].max_bytes = ev_size;
|
||||
}
|
||||
|
||||
/* Update global stats. */
|
||||
g_state.total_events++;
|
||||
g_state.total_bytes += ev_size;
|
||||
if (ev_size > g_state.max_event_bytes) {
|
||||
g_state.max_event_bytes = ev_size;
|
||||
g_state.max_event_kind = kind_num;
|
||||
}
|
||||
|
||||
find_or_add_pubkey(pk);
|
||||
|
||||
/* Periodic summary log (every 1000 events). */
|
||||
if (g_state.total_events % 1000 == 0) {
|
||||
time_t now = time(NULL);
|
||||
long elapsed = (long)(now - g_state.start_time);
|
||||
double rate = elapsed > 0 ? (double)g_state.total_events / elapsed : 0;
|
||||
DEBUG_INFO("[STATS] %ld events in %lds (%.1f ev/s) | "
|
||||
"%d relays | %d kinds | %d pubkeys | %.1f MB",
|
||||
g_state.total_events, elapsed, rate,
|
||||
g_state.relay_count, g_state.kind_count,
|
||||
g_state.pubkey_count,
|
||||
(double)g_state.total_bytes / (1024.0 * 1024.0));
|
||||
}
|
||||
}
|
||||
|
||||
static void on_eose(cJSON **events, int event_count, void *user_data) {
|
||||
(void)events; (void)event_count; (void)user_data;
|
||||
/* EOSE doesn't carry a relay URL in the callback, so we just log it. */
|
||||
DEBUG_INFO("[RELAY] EOSE");
|
||||
write_raw_log("?", "EOSE");
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------ */
|
||||
/* Report generation */
|
||||
/* ------------------------------------------------------------------ */
|
||||
|
||||
static int kind_name(int kind, char *buf, size_t bufsz) {
|
||||
switch (kind) {
|
||||
case 0: snprintf(buf, bufsz, "Profile metadata"); return 1;
|
||||
case 1: snprintf(buf, bufsz, "Text note"); return 1;
|
||||
case 3: snprintf(buf, bufsz, "Follow list"); return 1;
|
||||
case 4: snprintf(buf, bufsz, "Encrypted DM"); return 1;
|
||||
case 5: snprintf(buf, bufsz, "Deletion"); return 1;
|
||||
case 6: snprintf(buf, bufsz, "Repost"); return 1;
|
||||
case 7: snprintf(buf, bufsz, "Reaction"); return 1;
|
||||
case 13: snprintf(buf, bufsz, "Seal (NIP-59)"); return 1;
|
||||
case 16: snprintf(buf, bufsz, "Generic repost"); return 1;
|
||||
case 20: snprintf(buf, bufsz, "Picture"); return 1;
|
||||
case 21: snprintf(buf, bufsz, "Video"); return 1;
|
||||
case 445: snprintf(buf, bufsz, "Encrypted group msg"); return 1;
|
||||
case 1059: snprintf(buf, bufsz, "Gift wrap seal"); return 1;
|
||||
case 1063: snprintf(buf, bufsz, "File metadata"); return 1;
|
||||
case 1111: snprintf(buf, bufsz, "Comment"); return 1;
|
||||
case 1984: snprintf(buf, bufsz, "Report"); return 1;
|
||||
case 9734: snprintf(buf, bufsz, "Zap request"); return 1;
|
||||
case 9735: snprintf(buf, bufsz, "Zap receipt"); return 1;
|
||||
case 10000: snprintf(buf, bufsz, "Mute list"); return 1;
|
||||
case 10001: snprintf(buf, bufsz, "Pinned notes"); return 1;
|
||||
case 10002: snprintf(buf, bufsz, "Relay list"); return 1;
|
||||
case 10003: snprintf(buf, bufsz, "Bookmarks"); return 1;
|
||||
case 10050: snprintf(buf, bufsz, "DM relays"); return 1;
|
||||
case 13194: snprintf(buf, bufsz, "NWC info"); return 1;
|
||||
case 21059: snprintf(buf, bufsz, "Gift wrap (NIP-59)"); return 1;
|
||||
case 23194: snprintf(buf, bufsz, "NWC request"); return 1;
|
||||
case 23195: snprintf(buf, bufsz, "NWC response"); return 1;
|
||||
case 30023: snprintf(buf, bufsz, "Long-form article"); return 1;
|
||||
case 30078: snprintf(buf, bufsz, "App data"); return 1;
|
||||
case 30089: snprintf(buf, bufsz, "Chunked data"); return 1;
|
||||
case 30315: snprintf(buf, bufsz, "User status"); return 1;
|
||||
case 31989: snprintf(buf, bufsz, "App handler rec"); return 1;
|
||||
case 31990: snprintf(buf, bufsz, "App handler info"); return 1;
|
||||
case 34550: snprintf(buf, bufsz, "Community def"); return 1;
|
||||
default:
|
||||
if (kind >= 20000 && kind < 30000)
|
||||
snprintf(buf, bufsz, "Ephemeral");
|
||||
else if (kind >= 30000 && kind < 40000)
|
||||
snprintf(buf, bufsz, "Addressable");
|
||||
else
|
||||
snprintf(buf, bufsz, "Unknown");
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
static int write_report(void) {
|
||||
char path[1024];
|
||||
time_t now = time(NULL);
|
||||
struct tm *tm_info = localtime(&now);
|
||||
char ts[32];
|
||||
strftime(ts, sizeof(ts), "%Y%m%d_%H%M%S", tm_info);
|
||||
snprintf(path, sizeof(path), "cache_all_test_report_%s.txt", ts);
|
||||
|
||||
FILE *f = fopen(path, "w");
|
||||
if (!f) { DEBUG_ERROR("failed to write report"); return -1; }
|
||||
|
||||
long elapsed = (long)(now - g_state.start_time);
|
||||
int hours = (int)(elapsed / 3600);
|
||||
int mins = (int)((elapsed % 3600) / 60);
|
||||
int secs = (int)(elapsed % 60);
|
||||
|
||||
fprintf(f, "=== Cache-All Feasibility Test Report ===\n");
|
||||
fprintf(f, "Duration: %dh %dm %ds\n", hours, mins, secs);
|
||||
fprintf(f, "\n=== Global Summary ===\n");
|
||||
fprintf(f, "Total events: %ld\n", g_state.total_events);
|
||||
fprintf(f, "Total bytes: %ld (%.2f MB)\n",
|
||||
g_state.total_bytes, (double)g_state.total_bytes / (1024.0 * 1024.0));
|
||||
fprintf(f, "Avg event size: %.0f bytes\n",
|
||||
g_state.total_events > 0
|
||||
? (double)g_state.total_bytes / g_state.total_events : 0);
|
||||
fprintf(f, "Max event: %ld bytes (kind %d)\n",
|
||||
g_state.max_event_bytes, g_state.max_event_kind);
|
||||
fprintf(f, "Unique pubkeys: %d\n", g_state.pubkey_count);
|
||||
fprintf(f, "Relays: %d\n\n", g_state.relay_count);
|
||||
|
||||
fprintf(f, "=== Relay Summary ===\n");
|
||||
fprintf(f, "%-48s %8s %6s %6s %6s %6s %6s %s\n",
|
||||
"Relay", "Events", "EOSE", "CLOSED", "NOTICE", "Err", "Disc", "Status");
|
||||
for (int i = 0; i < g_state.relay_count; i++) {
|
||||
relay_stats_t *r = &g_state.relays[i];
|
||||
fprintf(f, "%-48s %8ld %6ld %6ld %6ld %6ld %6ld %s\n",
|
||||
r->url, r->events_received, r->eose_count,
|
||||
r->closed_count, r->notice_count, r->error_count,
|
||||
r->disconnect_count,
|
||||
r->is_connected ? "OK" : "DOWN");
|
||||
}
|
||||
fprintf(f, "\n");
|
||||
|
||||
fprintf(f, "=== Kind Distribution ===\n");
|
||||
fprintf(f, "%-8s %-30s %8s %6s %14s %10s %10s\n",
|
||||
"Kind", "Name", "Count", "%", "Total Bytes", "Avg", "Max");
|
||||
/* Sort by count descending. */
|
||||
for (int i = 0; i < g_state.kind_count; i++) {
|
||||
for (int j = i + 1; j < g_state.kind_count; j++) {
|
||||
if (g_state.kinds[j].count > g_state.kinds[i].count) {
|
||||
kind_stat_t tmp = g_state.kinds[i];
|
||||
g_state.kinds[i] = g_state.kinds[j];
|
||||
g_state.kinds[j] = tmp;
|
||||
}
|
||||
}
|
||||
}
|
||||
for (int i = 0; i < g_state.kind_count; i++) {
|
||||
kind_stat_t *k = &g_state.kinds[i];
|
||||
double pct = g_state.total_events > 0
|
||||
? (double)k->count / g_state.total_events * 100.0 : 0;
|
||||
char name[64];
|
||||
kind_name(k->kind, name, sizeof(name));
|
||||
fprintf(f, "%-8d %-30s %8ld %5.1f%% %12ld %8.0f %8ld\n",
|
||||
k->kind, name, k->count, pct,
|
||||
k->total_bytes,
|
||||
k->count > 0 ? (double)k->total_bytes / k->count : 0,
|
||||
k->max_bytes);
|
||||
}
|
||||
fprintf(f, "\n");
|
||||
|
||||
fprintf(f, "=== Raw Relay Response Log ===\n");
|
||||
if (g_state.raw_log) {
|
||||
fflush(g_state.raw_log);
|
||||
FILE *rl = fopen(g_state.raw_log_path, "r");
|
||||
if (rl) {
|
||||
char line[1024];
|
||||
while (fgets(line, sizeof(line), rl)) fputs(line, f);
|
||||
fclose(rl);
|
||||
}
|
||||
}
|
||||
fprintf(f, "\n");
|
||||
fclose(f);
|
||||
DEBUG_INFO("report: %s", path);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int write_json_stats(void) {
|
||||
char path[1024];
|
||||
time_t now = time(NULL);
|
||||
struct tm *tm_info = localtime(&now);
|
||||
char ts[32];
|
||||
strftime(ts, sizeof(ts), "%Y%m%d_%H%M%S", tm_info);
|
||||
snprintf(path, sizeof(path), "cache_all_test_stats_%s.json", ts);
|
||||
|
||||
cJSON *root = cJSON_CreateObject();
|
||||
if (!root) return -1;
|
||||
|
||||
long elapsed = (long)(now - g_state.start_time);
|
||||
cJSON_AddNumberToObject(root, "duration_seconds", elapsed);
|
||||
cJSON_AddNumberToObject(root, "total_events", g_state.total_events);
|
||||
cJSON_AddNumberToObject(root, "total_bytes", g_state.total_bytes);
|
||||
cJSON_AddNumberToObject(root, "unique_pubkeys", g_state.pubkey_count);
|
||||
cJSON_AddNumberToObject(root, "relay_count", g_state.relay_count);
|
||||
|
||||
cJSON *relays = cJSON_CreateArray();
|
||||
for (int i = 0; i < g_state.relay_count; i++) {
|
||||
relay_stats_t *r = &g_state.relays[i];
|
||||
cJSON *rj = cJSON_CreateObject();
|
||||
cJSON_AddStringToObject(rj, "url", r->url);
|
||||
cJSON_AddNumberToObject(rj, "events", r->events_received);
|
||||
cJSON_AddNumberToObject(rj, "eose", r->eose_count);
|
||||
cJSON_AddNumberToObject(rj, "closed", r->closed_count);
|
||||
cJSON_AddNumberToObject(rj, "notice", r->notice_count);
|
||||
cJSON_AddNumberToObject(rj, "errors", r->error_count);
|
||||
cJSON_AddNumberToObject(rj, "disconnects", r->disconnect_count);
|
||||
cJSON_AddBoolToObject(rj, "connected", r->is_connected);
|
||||
cJSON_AddItemToArray(relays, rj);
|
||||
}
|
||||
cJSON_AddItemToObject(root, "relays", relays);
|
||||
|
||||
cJSON *kinds = cJSON_CreateArray();
|
||||
for (int i = 0; i < g_state.kind_count; i++) {
|
||||
kind_stat_t *k = &g_state.kinds[i];
|
||||
cJSON *kj = cJSON_CreateObject();
|
||||
cJSON_AddNumberToObject(kj, "kind", k->kind);
|
||||
cJSON_AddNumberToObject(kj, "count", k->count);
|
||||
cJSON_AddNumberToObject(kj, "total_bytes", k->total_bytes);
|
||||
cJSON_AddNumberToObject(kj, "max_bytes", k->max_bytes);
|
||||
cJSON_AddItemToArray(kinds, kj);
|
||||
}
|
||||
cJSON_AddItemToObject(root, "kinds", kinds);
|
||||
|
||||
char *json = cJSON_Print(root);
|
||||
cJSON_Delete(root);
|
||||
if (!json) return -1;
|
||||
|
||||
FILE *f = fopen(path, "w");
|
||||
if (!f) { free(json); return -1; }
|
||||
fprintf(f, "%s\n", json);
|
||||
fclose(f);
|
||||
free(json);
|
||||
DEBUG_INFO("stats: %s", path);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------ */
|
||||
/* Main entry point */
|
||||
/* ------------------------------------------------------------------ */
|
||||
|
||||
int run_cache_all_test(const char *config_path,
|
||||
long duration_seconds,
|
||||
int log_level) {
|
||||
memset(&g_state, 0, sizeof(g_state));
|
||||
g_state.duration_seconds = duration_seconds;
|
||||
cr_seen_ring_init(&g_state.seen);
|
||||
|
||||
/* Open raw relay log. */
|
||||
time_t now = time(NULL);
|
||||
struct tm *tm_info = localtime(&now);
|
||||
char ts[32];
|
||||
strftime(ts, sizeof(ts), "%Y%m%d_%H%M%S", tm_info);
|
||||
snprintf(g_state.raw_log_path, sizeof(g_state.raw_log_path),
|
||||
"cache_all_test_raw_relay_%s.log", ts);
|
||||
g_state.raw_log = fopen(g_state.raw_log_path, "w");
|
||||
if (!g_state.raw_log) {
|
||||
fprintf(stderr, "ERROR: cannot create raw log '%s': %s\n",
|
||||
g_state.raw_log_path, strerror(errno));
|
||||
return 1;
|
||||
}
|
||||
fprintf(g_state.raw_log, "# Cache-All Feasibility Test - Raw Relay Log\n");
|
||||
fprintf(g_state.raw_log, "# Started: %s", ctime(&now));
|
||||
fprintf(g_state.raw_log, "# Config: %s\n", config_path ? config_path : "(none)");
|
||||
fprintf(g_state.raw_log, "# Duration: %ld seconds\n", duration_seconds);
|
||||
fflush(g_state.raw_log);
|
||||
|
||||
debug_init(log_level);
|
||||
DEBUG_INFO("cache_all_test starting (config=%s, duration=%lds, loglevel=%d)",
|
||||
config_path ? config_path : "(none)", duration_seconds, log_level);
|
||||
|
||||
nostr_set_log_callback(nostr_log_forwarder, NULL);
|
||||
nostr_set_log_level((nostr_log_level_t)log_level);
|
||||
|
||||
struct sigaction sa;
|
||||
memset(&sa, 0, sizeof(sa));
|
||||
sa.sa_handler = on_signal;
|
||||
sigaction(SIGINT, &sa, NULL);
|
||||
sigaction(SIGTERM, &sa, NULL);
|
||||
signal(SIGPIPE, SIG_IGN);
|
||||
|
||||
if (nostr_crypto_init() != NOSTR_SUCCESS) {
|
||||
fprintf(stderr, "ERROR: nostr_crypto_init failed\n");
|
||||
fclose(g_state.raw_log);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Load config. */
|
||||
cr_config_t cfg;
|
||||
if (cr_config_load(&cfg, config_path) != 0) {
|
||||
fprintf(stderr, "ERROR: failed to load config\n");
|
||||
fclose(g_state.raw_log);
|
||||
nostr_crypto_cleanup();
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Create upstream pool with custom reconnect config.
|
||||
* Use 25s ping interval to stay ahead of Primal's 30s idle timeout. */
|
||||
nostr_pool_reconnect_config_t reconnect_cfg = {
|
||||
.enable_auto_reconnect = 1,
|
||||
.max_reconnect_attempts = 10,
|
||||
.initial_reconnect_delay_ms = 1000,
|
||||
.max_reconnect_delay_ms = 30000,
|
||||
.reconnect_backoff_multiplier = 2,
|
||||
.reconnect_reset_stability_seconds = 30,
|
||||
.ping_interval_seconds = 25,
|
||||
.pong_timeout_seconds = 10
|
||||
};
|
||||
nostr_relay_pool_t *upstream = nostr_relay_pool_create(&reconnect_cfg);
|
||||
if (!upstream) {
|
||||
fprintf(stderr, "ERROR: failed to create pool\n");
|
||||
fclose(g_state.raw_log);
|
||||
cr_config_free(&cfg);
|
||||
nostr_crypto_cleanup();
|
||||
return 1;
|
||||
}
|
||||
|
||||
for (int i = 0; i < cfg.upstream_count; i++) {
|
||||
if (nostr_relay_pool_add_relay(upstream, cfg.upstream_relays[i])
|
||||
== NOSTR_SUCCESS) {
|
||||
DEBUG_INFO("added relay: %s", cfg.upstream_relays[i]);
|
||||
find_or_add_relay(cfg.upstream_relays[i]);
|
||||
}
|
||||
}
|
||||
|
||||
/* Wait for connections (up to 15s). */
|
||||
DEBUG_INFO("waiting for connections...");
|
||||
for (int i = 0; i < 150 && !g_shutdown; i++) {
|
||||
nostr_relay_pool_run(upstream, 100);
|
||||
if (i % 50 == 0 && i > 0) {
|
||||
int connected = 0;
|
||||
for (int r = 0; r < g_state.relay_count; r++) {
|
||||
nostr_pool_relay_status_t st =
|
||||
nostr_relay_pool_get_relay_status(upstream,
|
||||
g_state.relays[r].url);
|
||||
g_state.relays[r].is_connected = (st == NOSTR_POOL_RELAY_CONNECTED);
|
||||
if (g_state.relays[r].is_connected) connected++;
|
||||
}
|
||||
DEBUG_INFO(" %d/%d relays connected after %dms",
|
||||
connected, g_state.relay_count, (i+1)*100);
|
||||
}
|
||||
}
|
||||
|
||||
/* Log final connection status. */
|
||||
for (int r = 0; r < g_state.relay_count; r++) {
|
||||
nostr_pool_relay_status_t st =
|
||||
nostr_relay_pool_get_relay_status(upstream, g_state.relays[r].url);
|
||||
g_state.relays[r].is_connected = (st == NOSTR_POOL_RELAY_CONNECTED);
|
||||
const char *status_str = "?";
|
||||
if (st == NOSTR_POOL_RELAY_CONNECTED) status_str = "connected";
|
||||
else if (st == NOSTR_POOL_RELAY_CONNECTING) status_str = "connecting";
|
||||
else if (st == NOSTR_POOL_RELAY_DISCONNECTED) status_str = "disconnected";
|
||||
DEBUG_INFO(" %s: %s", g_state.relays[r].url, status_str);
|
||||
write_raw_log(g_state.relays[r].url, "STATUS: %s", status_str);
|
||||
}
|
||||
|
||||
/* Open subscription: ALL events (no filter). */
|
||||
cJSON *filter = cJSON_CreateObject();
|
||||
cJSON_AddItemToObject(filter, "since", cJSON_CreateNumber((double)time(NULL)));
|
||||
|
||||
char **listed = NULL;
|
||||
nostr_pool_relay_status_t *statuses = NULL;
|
||||
int n = nostr_relay_pool_list_relays(upstream, &listed, &statuses);
|
||||
const char **urls = NULL;
|
||||
if (n > 0) {
|
||||
urls = malloc(n * sizeof(char *));
|
||||
for (int j = 0; j < n; j++) urls[j] = listed[j];
|
||||
}
|
||||
|
||||
nostr_pool_subscription_t *sub = NULL;
|
||||
if (n > 0 && urls) {
|
||||
sub = nostr_relay_pool_subscribe(
|
||||
upstream, urls, n, filter,
|
||||
on_event, on_eose, NULL,
|
||||
0, 1, NOSTR_POOL_EOSE_FULL_SET, 0, 0);
|
||||
}
|
||||
free(urls);
|
||||
free(listed);
|
||||
free(statuses);
|
||||
cJSON_Delete(filter);
|
||||
|
||||
if (!sub) {
|
||||
DEBUG_ERROR("failed to open subscription");
|
||||
} else {
|
||||
DEBUG_INFO("subscription opened on %d relays", n);
|
||||
}
|
||||
|
||||
/* Main loop. */
|
||||
g_state.start_time = time(NULL);
|
||||
g_state.last_summary_log = g_state.start_time;
|
||||
time_t last_resubscribe = g_state.start_time;
|
||||
DEBUG_INFO("entering main loop for %ld seconds", duration_seconds);
|
||||
|
||||
while (!g_shutdown) {
|
||||
if (duration_seconds > 0) {
|
||||
long elapsed = (long)(time(NULL) - g_state.start_time);
|
||||
if (elapsed >= duration_seconds) {
|
||||
DEBUG_INFO("duration reached (%lds)", elapsed);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
nostr_relay_pool_run(upstream, 100);
|
||||
|
||||
/* Poll connection status. */
|
||||
for (int r = 0; r < g_state.relay_count; r++) {
|
||||
nostr_pool_relay_status_t st =
|
||||
nostr_relay_pool_get_relay_status(upstream, g_state.relays[r].url);
|
||||
int was = g_state.relays[r].is_connected;
|
||||
int now = (st == NOSTR_POOL_RELAY_CONNECTED);
|
||||
g_state.relays[r].is_connected = now;
|
||||
if (now && !was) {
|
||||
g_state.relays[r].reconnect_count++;
|
||||
DEBUG_INFO("[RELAY] %s CONNECTED", g_state.relays[r].url);
|
||||
write_raw_log(g_state.relays[r].url, "CONNECTED");
|
||||
} else if (!now && was) {
|
||||
g_state.relays[r].disconnect_count++;
|
||||
const char *err = nostr_relay_pool_get_relay_last_connection_error(
|
||||
upstream, g_state.relays[r].url);
|
||||
DEBUG_WARN("[RELAY] %s DISCONNECTED: %s",
|
||||
g_state.relays[r].url, err ? err : "");
|
||||
write_raw_log(g_state.relays[r].url, "DISCONNECTED: %s", err ? err : "");
|
||||
}
|
||||
}
|
||||
|
||||
/* Periodic resubscribe (every 5 min) to re-establish REQ on reconnected relays. */
|
||||
time_t now_t = time(NULL);
|
||||
if ((now_t - last_resubscribe) >= 300) {
|
||||
if (sub) {
|
||||
nostr_pool_subscription_close(sub);
|
||||
sub = NULL;
|
||||
}
|
||||
/* Re-open subscription with fresh filter. */
|
||||
cJSON *new_filter = cJSON_CreateObject();
|
||||
cJSON_AddItemToObject(new_filter, "since",
|
||||
cJSON_CreateNumber((double)time(NULL)));
|
||||
char **rel_list = NULL;
|
||||
nostr_pool_relay_status_t *rel_statuses = NULL;
|
||||
int rel_n = nostr_relay_pool_list_relays(upstream, &rel_list, &rel_statuses);
|
||||
const char **rel_urls = NULL;
|
||||
if (rel_n > 0) {
|
||||
rel_urls = malloc(rel_n * sizeof(char *));
|
||||
for (int j = 0; j < rel_n; j++) rel_urls[j] = rel_list[j];
|
||||
}
|
||||
if (rel_n > 0 && rel_urls) {
|
||||
sub = nostr_relay_pool_subscribe(
|
||||
upstream, rel_urls, rel_n, new_filter,
|
||||
on_event, on_eose, NULL,
|
||||
0, 1, NOSTR_POOL_EOSE_FULL_SET, 0, 0);
|
||||
}
|
||||
free(rel_urls);
|
||||
free(rel_list);
|
||||
free(rel_statuses);
|
||||
cJSON_Delete(new_filter);
|
||||
if (sub) {
|
||||
DEBUG_INFO("resubscribed on %d relays", rel_n);
|
||||
} else {
|
||||
DEBUG_WARN("resubscribe failed");
|
||||
}
|
||||
last_resubscribe = now_t;
|
||||
}
|
||||
|
||||
/* Periodic heartbeat with ping stats. */
|
||||
if ((now_t - g_state.last_summary_log) >= 30) {
|
||||
long elapsed = (long)(now_t - g_state.start_time);
|
||||
double rate = elapsed > 0 ? (double)g_state.total_events / elapsed : 0;
|
||||
int connected = 0;
|
||||
for (int r = 0; r < g_state.relay_count; r++)
|
||||
if (g_state.relays[r].is_connected) connected++;
|
||||
/* Get ping stats for first connected relay. */
|
||||
double ping = 0;
|
||||
int ping_samples = 0;
|
||||
for (int r = 0; r < g_state.relay_count && ping_samples == 0; r++) {
|
||||
if (g_state.relays[r].is_connected) {
|
||||
const nostr_relay_stats_t *stats =
|
||||
nostr_relay_pool_get_relay_stats(upstream,
|
||||
g_state.relays[r].url);
|
||||
if (stats) {
|
||||
ping = stats->ping_latency_current;
|
||||
ping_samples = stats->ping_samples;
|
||||
}
|
||||
}
|
||||
}
|
||||
DEBUG_INFO("[HEARTBEAT] %ld events in %lds (%.1f ev/s) | "
|
||||
"%d/%d relays | %d kinds | %d pubkeys | "
|
||||
"ping=%.1fms(%d)",
|
||||
g_state.total_events, elapsed, rate,
|
||||
connected, g_state.relay_count,
|
||||
g_state.kind_count, g_state.pubkey_count,
|
||||
ping * 1000, ping_samples);
|
||||
g_state.last_summary_log = now_t;
|
||||
}
|
||||
}
|
||||
|
||||
if (sub) nostr_pool_subscription_close(sub);
|
||||
|
||||
DEBUG_INFO("writing reports...");
|
||||
write_report();
|
||||
write_json_stats();
|
||||
|
||||
if (g_state.raw_log) {
|
||||
fprintf(g_state.raw_log, "# Test ended: %s", ctime(&now));
|
||||
fclose(g_state.raw_log);
|
||||
DEBUG_INFO("raw log: %s", g_state.raw_log_path);
|
||||
}
|
||||
|
||||
nostr_relay_pool_destroy(upstream);
|
||||
cr_config_free(&cfg);
|
||||
nostr_crypto_cleanup();
|
||||
DEBUG_INFO("clean exit");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------ */
|
||||
/* Standalone entry point */
|
||||
/* ------------------------------------------------------------------ */
|
||||
|
||||
static void usage(const char *prog) {
|
||||
fprintf(stderr,
|
||||
"cache_all_test %s - feasibility test for cache-all approach\n"
|
||||
"\n"
|
||||
"Usage: %s -c <config.jsonc> -t <seconds> [options]\n"
|
||||
"\n"
|
||||
"Options:\n"
|
||||
" -c, --config <file> Path to .jsonc config file (required)\n"
|
||||
" -t, --time <seconds> Test duration in seconds (required)\n"
|
||||
" -d, --debug <level> Log level 0-5 (default: 3)\n"
|
||||
" -h, --help Show this help\n"
|
||||
"\n"
|
||||
"Output files:\n"
|
||||
" cache_all_test_raw_relay_<ts>.log - verbatim relay responses\n"
|
||||
" cache_all_test_report_<ts>.txt - summary report\n"
|
||||
" cache_all_test_stats_<ts>.json - machine-readable stats\n",
|
||||
CR_VERSION, prog);
|
||||
}
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
const char *config_path = NULL;
|
||||
long duration = 0;
|
||||
int log_level = DEBUG_LEVEL_INFO;
|
||||
|
||||
static struct option longopts[] = {
|
||||
{"config", required_argument, 0, 'c'},
|
||||
{"time", required_argument, 0, 't'},
|
||||
{"debug", required_argument, 0, 'd'},
|
||||
{"help", no_argument, 0, 'h'},
|
||||
{0, 0, 0, 0}
|
||||
};
|
||||
|
||||
int opt;
|
||||
while ((opt = getopt_long(argc, argv, "c:t:d:h", longopts, NULL)) != -1) {
|
||||
switch (opt) {
|
||||
case 'c': config_path = optarg; break;
|
||||
case 't': duration = atol(optarg); break;
|
||||
case 'd': log_level = atoi(optarg); break;
|
||||
case 'h': usage(argv[0]); return 0;
|
||||
default: usage(argv[0]); return 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (!config_path) {
|
||||
fprintf(stderr, "ERROR: -c <config> is required\n\n");
|
||||
usage(argv[0]);
|
||||
return 1;
|
||||
}
|
||||
if (duration <= 0) {
|
||||
fprintf(stderr, "ERROR: -t <seconds> is required and must be > 0\n\n");
|
||||
usage(argv[0]);
|
||||
return 1;
|
||||
}
|
||||
|
||||
return run_cache_all_test(config_path, duration, log_level);
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
/*
|
||||
* cache_all_test - feasibility test for "cache everything" approach.
|
||||
*
|
||||
* Standalone test program that connects to all outbox relays of followed
|
||||
* pubkeys and subscribes to ALL events (no author filter) to determine
|
||||
* if relays will tolerate this level of data flow.
|
||||
*
|
||||
* Logs raw relay responses verbatim. Tracks kind distribution, event sizes,
|
||||
* per-relay stats. Generates summary report + raw relay log file.
|
||||
*
|
||||
* See plans/cache_all_feasibility_test_plan.md for full design.
|
||||
*/
|
||||
#ifndef CACHE_ALL_TEST_H
|
||||
#define CACHE_ALL_TEST_H
|
||||
|
||||
/* Run the cache-all feasibility test.
|
||||
* config_path: path to .jsonc config file
|
||||
* duration_seconds: how long to run (0 = run until SIGINT)
|
||||
* log_level: debug level 0-5
|
||||
* Returns 0 on success, -1 on error.
|
||||
*/
|
||||
int run_cache_all_test(const char *config_path,
|
||||
long duration_seconds,
|
||||
int log_level);
|
||||
|
||||
#endif /* CACHE_ALL_TEST_H */
|
||||
@@ -7,6 +7,7 @@
|
||||
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <ctype.h>
|
||||
|
||||
int cr_follow_is_root(const cr_config_t *cfg, const char *hex) {
|
||||
if (!cfg->root_hex_ready) return 0;
|
||||
@@ -16,17 +17,35 @@ int cr_follow_is_root(const cr_config_t *cfg, const char *hex) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Check if a string is a 64-character hex pubkey (no npub prefix). */
|
||||
static int is_hex_pubkey(const char *s) {
|
||||
if (!s || strlen(s) != 64) return 0;
|
||||
for (int i = 0; i < 64; i++) {
|
||||
if (!isxdigit((unsigned char)s[i])) return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
int cr_follow_decode_roots(cr_config_t *cfg) {
|
||||
for (int i = 0; i < cfg->root_npub_count; i++) {
|
||||
unsigned char pubkey[32];
|
||||
if (nostr_decode_npub(cfg->root_npubs[i], pubkey) != NOSTR_SUCCESS) {
|
||||
DEBUG_ERROR("follow: failed to decode npub '%s'", cfg->root_npubs[i]);
|
||||
return -1;
|
||||
const char *input = cfg->root_npubs[i];
|
||||
if (is_hex_pubkey(input)) {
|
||||
/* Already a 64-char hex pubkey — copy directly. */
|
||||
strncpy(cfg->root_hex[i], input, 64);
|
||||
cfg->root_hex[i][64] = '\0';
|
||||
} else {
|
||||
/* Assume npub (bech32) format — decode to hex. */
|
||||
unsigned char pubkey[32];
|
||||
if (nostr_decode_npub(input, pubkey) != NOSTR_SUCCESS) {
|
||||
DEBUG_ERROR("follow: failed to decode root pubkey '%s' "
|
||||
"(not a valid npub or 64-char hex)", input);
|
||||
return -1;
|
||||
}
|
||||
nostr_bytes_to_hex(pubkey, 32, cfg->root_hex[i]);
|
||||
}
|
||||
nostr_bytes_to_hex(pubkey, 32, cfg->root_hex[i]);
|
||||
}
|
||||
cfg->root_hex_ready = 1;
|
||||
DEBUG_INFO("follow: decoded %d root npubs", cfg->root_npub_count);
|
||||
DEBUG_INFO("follow: decoded %d root pubkeys", cfg->root_npub_count);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
+29
-8
@@ -593,16 +593,37 @@ int main(int argc, char **argv) {
|
||||
long events_fetched = live.events_received + bf.events_total;
|
||||
long inbox_inserts = sink.published_ok;
|
||||
int connected = 0;
|
||||
{
|
||||
char **listed = NULL;
|
||||
nostr_pool_relay_status_t *statuses = NULL;
|
||||
int n = nostr_relay_pool_list_relays(upstream, &listed, &statuses);
|
||||
for (int j = 0; j < n; j++) {
|
||||
if (statuses[j] == NOSTR_POOL_RELAY_CONNECTED) connected++;
|
||||
char **listed = NULL;
|
||||
nostr_pool_relay_status_t *statuses = NULL;
|
||||
int n = nostr_relay_pool_list_relays(upstream, &listed, &statuses);
|
||||
if (n > 0) {
|
||||
/* Build per-relay status arrays for the upstream_relays table. */
|
||||
const char **urls = malloc((size_t)n * sizeof(char *));
|
||||
int *codes = malloc((size_t)n * sizeof(int));
|
||||
const char **texts = malloc((size_t)n * sizeof(char *));
|
||||
if (urls && codes && texts) {
|
||||
for (int j = 0; j < n; j++) {
|
||||
urls[j] = listed[j];
|
||||
codes[j] = (int)statuses[j];
|
||||
if (statuses[j] == NOSTR_POOL_RELAY_CONNECTED) {
|
||||
texts[j] = "connected";
|
||||
connected++;
|
||||
} else if (statuses[j] == NOSTR_POOL_RELAY_CONNECTING) {
|
||||
texts[j] = "connecting";
|
||||
} else if (statuses[j] == NOSTR_POOL_RELAY_DISCONNECTED) {
|
||||
texts[j] = "disconnected";
|
||||
} else {
|
||||
texts[j] = "error";
|
||||
}
|
||||
}
|
||||
pg_inbox_update_upstream_relays(urls, codes, texts, n);
|
||||
}
|
||||
free(listed);
|
||||
free(statuses);
|
||||
free(urls);
|
||||
free(codes);
|
||||
free(texts);
|
||||
}
|
||||
free(listed);
|
||||
free(statuses);
|
||||
int bf_complete = 0, bf_total = 0;
|
||||
pg_inbox_count_backfill_progress(&bf_complete, &bf_total);
|
||||
pg_inbox_update_status("running", config_generation, (long)now,
|
||||
|
||||
@@ -1186,3 +1186,93 @@ int pg_inbox_update_last_event_at(const char *pk, long event_created_at) {
|
||||
PQclear(res);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------ */
|
||||
/* Upstream relay status tracking */
|
||||
/* ------------------------------------------------------------------ */
|
||||
|
||||
int pg_inbox_update_upstream_relays(const char **relay_urls,
|
||||
const int *statuses,
|
||||
const char **status_texts,
|
||||
int count) {
|
||||
if (!g_pg) {
|
||||
DEBUG_ERROR("pg_inbox: not initialized");
|
||||
return -1;
|
||||
}
|
||||
if (count <= 0) return 0;
|
||||
|
||||
/* Create the table if it doesn't exist (idempotent). */
|
||||
PGresult *create = PQexec(g_pg,
|
||||
"CREATE TABLE IF NOT EXISTS caching_upstream_relays ("
|
||||
" relay_url TEXT PRIMARY KEY,"
|
||||
" status_code INT NOT NULL DEFAULT 0,"
|
||||
" status_text TEXT NOT NULL DEFAULT '',"
|
||||
" updated_at BIGINT NOT NULL DEFAULT 0"
|
||||
")");
|
||||
if (create) {
|
||||
PQclear(create);
|
||||
}
|
||||
|
||||
/* Build a batch INSERT from the arrays. We use a single multi-row
|
||||
* INSERT ... ON CONFLICT DO UPDATE so all relays are updated in one
|
||||
* round-trip. Each row is: (relay_url, status_code, status_text, now). */
|
||||
|
||||
/* Calculate total buffer size: each row adds roughly 200 bytes. */
|
||||
size_t total = count * 200 + 256;
|
||||
char *sql = malloc(total);
|
||||
if (!sql) return -1;
|
||||
|
||||
char *p = sql;
|
||||
int written = snprintf(p, total,
|
||||
"INSERT INTO caching_upstream_relays (relay_url, status_code, status_text, updated_at) VALUES ");
|
||||
if (written < 0) { free(sql); return -1; }
|
||||
p += written;
|
||||
|
||||
for (int i = 0; i < count; i++) {
|
||||
/* Escape the relay URL and status text for safe SQL embedding.
|
||||
* We use PQescapeLiteral for simplicity. */
|
||||
char *esc_url = PQescapeLiteral(g_pg, relay_urls[i], (int)strlen(relay_urls[i]));
|
||||
char *esc_text = PQescapeLiteral(g_pg, status_texts[i], (int)strlen(status_texts[i]));
|
||||
if (!esc_url || !esc_text) {
|
||||
if (esc_url) PQfreemem(esc_url);
|
||||
if (esc_text) PQfreemem(esc_text);
|
||||
free(sql);
|
||||
return -1;
|
||||
}
|
||||
size_t remaining = total - (size_t)(p - sql);
|
||||
written = snprintf(p, remaining,
|
||||
"%s(%s, %d, %s, EXTRACT(EPOCH FROM NOW())::BIGINT)",
|
||||
(i > 0) ? ", " : "",
|
||||
esc_url, statuses[i], esc_text);
|
||||
PQfreemem(esc_url);
|
||||
PQfreemem(esc_text);
|
||||
if (written < 0 || (size_t)written >= remaining) { free(sql); return -1; }
|
||||
p += written;
|
||||
}
|
||||
|
||||
/* Add ON CONFLICT clause. */
|
||||
size_t remaining = total - (size_t)(p - sql);
|
||||
written = snprintf(p, remaining,
|
||||
" ON CONFLICT (relay_url) DO UPDATE SET "
|
||||
" status_code = EXCLUDED.status_code, "
|
||||
" status_text = EXCLUDED.status_text, "
|
||||
" updated_at = EXCLUDED.updated_at");
|
||||
if (written < 0 || (size_t)written >= remaining) { free(sql); return -1; }
|
||||
|
||||
PGresult *res = PQexec(g_pg, sql);
|
||||
free(sql);
|
||||
|
||||
if (!res) {
|
||||
DEBUG_ERROR("pg_inbox: update_upstream_relays returned NULL result");
|
||||
return -1;
|
||||
}
|
||||
ExecStatusType st = PQresultStatus(res);
|
||||
if (st != PGRES_COMMAND_OK) {
|
||||
DEBUG_ERROR("pg_inbox: update_upstream_relays failed: %s",
|
||||
PQresultErrorMessage(res));
|
||||
PQclear(res);
|
||||
return -1;
|
||||
}
|
||||
PQclear(res);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -162,4 +162,17 @@ cJSON* pg_inbox_get_authors_for_catchup(void);
|
||||
* the given value. Returns 0 on success, -1 on error. */
|
||||
int pg_inbox_update_last_event_at(const char *pk, long event_created_at);
|
||||
|
||||
/* ------------------------------------------------------------------ */
|
||||
/* Upstream relay status tracking */
|
||||
/* ------------------------------------------------------------------ */
|
||||
|
||||
/* Update the upstream relay status table with current connection states.
|
||||
* Takes parallel arrays of relay_urls, status codes, and status text strings.
|
||||
* count is the number of entries. Uses a batch upsert.
|
||||
* Returns 0 on success, -1 on error. */
|
||||
int pg_inbox_update_upstream_relays(const char **relay_urls,
|
||||
const int *statuses,
|
||||
const char **status_texts,
|
||||
int count);
|
||||
|
||||
#endif /* CACHING_RELAY_PG_INBOX_H */
|
||||
|
||||
@@ -239,8 +239,8 @@ static void compute_covering_set(cr_relay_map_t *map, cr_config_t *cfg,
|
||||
* Returns a cJSON array of events (caller must cJSON_Delete each + free).
|
||||
* Sets *out_count to the number of events returned. */
|
||||
static cJSON **query_kind10002_batch(nostr_relay_pool_t *pool,
|
||||
const char **pubkeys, int pubkey_count,
|
||||
int *out_count) {
|
||||
const char **pubkeys, int pubkey_count,
|
||||
int *out_count) {
|
||||
cJSON *filter = cJSON_CreateObject();
|
||||
cJSON *authors = cJSON_CreateArray();
|
||||
for (int i = 0; i < pubkey_count; i++)
|
||||
@@ -276,6 +276,44 @@ static cJSON **query_kind10002_batch(nostr_relay_pool_t *pool,
|
||||
return events;
|
||||
}
|
||||
|
||||
/* ---- batched kind-3 fallback query ---- */
|
||||
|
||||
/* Query kind 3 (contact list) for a batch of pubkeys from a pool.
|
||||
* Kind-3 events historically contain "r" tags with relay URLs (pre-NIP-65).
|
||||
* We use this as a fallback for pubkeys that don't have kind-10002.
|
||||
* Returns a cJSON array of events (caller must cJSON_Delete each + free).
|
||||
* Sets *out_count to the number of events returned. */
|
||||
static cJSON **query_kind3_batch(nostr_relay_pool_t *pool,
|
||||
const char **pubkeys, int pubkey_count,
|
||||
int *out_count) {
|
||||
cJSON *filter = cJSON_CreateObject();
|
||||
cJSON *authors = cJSON_CreateArray();
|
||||
for (int i = 0; i < pubkey_count; i++)
|
||||
cJSON_AddItemToArray(authors, cJSON_CreateString(pubkeys[i]));
|
||||
cJSON_AddItemToObject(filter, "authors", authors);
|
||||
cJSON *kinds = cJSON_CreateArray();
|
||||
cJSON_AddItemToArray(kinds, cJSON_CreateNumber(3));
|
||||
cJSON_AddItemToObject(filter, "kinds", kinds);
|
||||
/* limit=1 per author: we only need the most recent kind-3.
|
||||
* The relay pool query_sync returns the most recent events. */
|
||||
cJSON_AddItemToObject(filter, "limit", cJSON_CreateNumber(pubkey_count));
|
||||
|
||||
const char **urls = NULL;
|
||||
int n = get_pool_urls(pool, &urls);
|
||||
|
||||
DEBUG_TRACE("query_kind3_batch: querying %d relays for %d pubkeys", n, pubkey_count);
|
||||
|
||||
int ev_count = 0;
|
||||
cJSON **events = nostr_relay_pool_query_sync(pool, urls, n, filter, &ev_count, 30000);
|
||||
free(urls);
|
||||
cJSON_Delete(filter);
|
||||
|
||||
DEBUG_TRACE("query_kind3_batch: returned %d events", ev_count);
|
||||
|
||||
*out_count = ev_count;
|
||||
return events;
|
||||
}
|
||||
|
||||
/* Process a batch of kind-10002 events: parse r-tags, populate outbox entries,
|
||||
* publish to local relay. Returns count of events processed. */
|
||||
static int process_10002_batch(cJSON **events, int ev_count,
|
||||
@@ -438,9 +476,61 @@ int cr_relay_discovery_run(cr_relay_map_t *map, cr_config_t *cfg,
|
||||
free(remaining_pk);
|
||||
}
|
||||
|
||||
/* Phase 3: Kind-3 fallback for pubkeys still without relay lists.
|
||||
* Kind-3 (contact list) events historically contain "r" tags with relay
|
||||
* URLs (pre-NIP-65). This catches older users who never published kind-10002. */
|
||||
int remaining_k3 = 0;
|
||||
for (int i = 0; i < followed->count; i++) if (!found[i]) remaining_k3++;
|
||||
|
||||
if (remaining_k3 > 0) {
|
||||
DEBUG_INFO("relay_discovery: querying bootstrap relays for kind-3 fallback (%d pubkeys)...",
|
||||
remaining_k3);
|
||||
|
||||
const char **remaining_pk = malloc(remaining_k3 * sizeof(char *));
|
||||
int ridx = 0;
|
||||
for (int i = 0; i < followed->count; i++) {
|
||||
if (!found[i]) remaining_pk[ridx++] = followed->items[i];
|
||||
}
|
||||
|
||||
int found_k3 = 0;
|
||||
for (int start = 0; start < remaining_k3 && !g_shutdown; start += CR_10002_BATCH_SIZE) {
|
||||
int batch = remaining_k3 - start;
|
||||
if (batch > CR_10002_BATCH_SIZE) batch = CR_10002_BATCH_SIZE;
|
||||
|
||||
int ev_count = 0;
|
||||
cJSON **events = query_kind3_batch(upstream,
|
||||
&remaining_pk[start],
|
||||
batch, &ev_count);
|
||||
if (events && ev_count > 0) {
|
||||
for (int k = 0; k < ev_count; k++) {
|
||||
cJSON *pk = cJSON_GetObjectItem(events[k], "pubkey");
|
||||
if (pk && cJSON_IsString(pk)) {
|
||||
const char *hex = cJSON_GetStringValue(pk);
|
||||
for (int i = 0; i < followed->count; i++) {
|
||||
if (strcmp(followed->items[i], hex) == 0) {
|
||||
if (!found[i]) { found[i] = 1; found_k3++; }
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
/* process_10002_batch works for kind-3 too — same r-tag format */
|
||||
process_10002_batch(events, ev_count, map, sink, "bootstrap");
|
||||
cr_sink_pump(sink, 500);
|
||||
} else {
|
||||
free(events);
|
||||
}
|
||||
}
|
||||
free(remaining_pk);
|
||||
DEBUG_INFO("relay_discovery: kind-3 fallback found %d additional pubkeys with relays", found_k3);
|
||||
}
|
||||
|
||||
found_none = followed->count - found_local - found_bootstrap;
|
||||
/* Recalculate found_none after kind-3 fallback */
|
||||
int still_none = 0;
|
||||
for (int i = 0; i < followed->count; i++) if (!found[i]) still_none++;
|
||||
DEBUG_INFO("relay_discovery: %d local, %d bootstrap, %d none",
|
||||
found_local, found_bootstrap, found_none);
|
||||
found_local, found_bootstrap, still_none);
|
||||
|
||||
free(found);
|
||||
|
||||
|
||||
+11
-2
@@ -181,8 +181,16 @@ echo "[remote] Health checks"
|
||||
sudo systemctl --no-pager --full status "$SERVICE_NAME" | sed -n '1,25p'
|
||||
sudo -u "$RELAY_USER" psql -d crelay -c "SELECT current_user, current_database();"
|
||||
|
||||
# Verify public relay page is accessible (HTTP 200, no auth).
|
||||
PUBLIC_CODE=$(curl -s -o /dev/null -w "%{http_code}" "http://127.0.0.1/relay/" 2>/dev/null || echo "000")
|
||||
if [ "$PUBLIC_CODE" = "200" ]; then
|
||||
echo " -> public relay page accessible (HTTP $PUBLIC_CODE)"
|
||||
else
|
||||
echo " -> WARNING: public relay page returned HTTP $PUBLIC_CODE (expected 200)"
|
||||
fi
|
||||
|
||||
# Verify admin page is accessible (HTTP 200 or 401 = auth required, both are OK).
|
||||
ADMIN_CODE=$(curl -s -o /dev/null -w "%{http_code}" "http://127.0.0.1/admin/" 2>/dev/null || echo "000")
|
||||
ADMIN_CODE=$(curl -s -o /dev/null -w "%{http_code}" "http://127.0.0.1/relay/admin/" 2>/dev/null || echo "000")
|
||||
if [ "$ADMIN_CODE" = "200" ] || [ "$ADMIN_CODE" = "401" ]; then
|
||||
echo " -> admin page accessible (HTTP $ADMIN_CODE)"
|
||||
else
|
||||
@@ -199,5 +207,6 @@ rm -f /tmp/admin_deploy.tar.gz
|
||||
|
||||
echo "Deployment complete: $REMOTE_HOST"
|
||||
echo ""
|
||||
echo "Admin interface: https://laantungir.net/admin/"
|
||||
echo "Public relay page: https://laantungir.net/relay/"
|
||||
echo "Admin interface: https://laantungir.net/relay/admin/ (Basic Auth)"
|
||||
echo "Caching is NOT auto-started. Enable it via the admin UI when ready."
|
||||
|
||||
@@ -361,6 +361,63 @@ server {
|
||||
}
|
||||
```
|
||||
|
||||
#### PHP Admin UI: Public Stats vs Authenticated Admin
|
||||
|
||||
The relay ships with a PHP admin UI (in [`admin/`](../admin/)) that talks
|
||||
directly to PostgreSQL. It is served by nginx + php-fpm and is split into two
|
||||
URL paths with different access controls:
|
||||
|
||||
| URL | Auth | Purpose |
|
||||
|----------------------------------|---------------|----------------------------------------------------|
|
||||
| `https://<domain>/relay/` | None (public) | Public landing page: relay info + event-rate chart |
|
||||
| `https://<domain>/relay/api/chart.php?range=day` | None (public) | Read-only ASCII chart endpoint (aggregate COUNT) |
|
||||
| `https://<domain>/relay/admin/` | HTTP Basic Auth | Full admin UI: config, auth rules, IP bans, DMs, SQL query |
|
||||
|
||||
**Why Basic Auth is required for `/relay/admin/`:** the PHP endpoints have no
|
||||
server-side authentication of their own. The `nostr_login_lite` modal in the
|
||||
admin UI is a **client-side only** gate (it only toggles UI visibility in the
|
||||
browser); it does not send a signed event or session token to the backend.
|
||||
Without Basic Auth, anyone could hit `api/query.php` to run SELECT queries
|
||||
against your database, `api/config.php` to change relay config, `api/auth.php`
|
||||
to edit blacklist/whitelist rules, or `api/dm.php` to read DMs.
|
||||
|
||||
Only [`admin/api/chart.php`](../admin/api/chart.php) is safe to expose
|
||||
publicly — it runs a fixed aggregate `COUNT(*)` query with the only user input
|
||||
being the `range` selector, which is validated against a whitelist
|
||||
(`hour`/`day`/`month`/`year`).
|
||||
|
||||
A complete, ready-to-use nginx config including this split is in
|
||||
[`examples/deployment/nginx-proxy/nginx.conf`](../examples/deployment/nginx-proxy/nginx.conf).
|
||||
The relevant blocks:
|
||||
|
||||
```nginx
|
||||
# Public landing page + chart (no auth)
|
||||
location /relay/ {
|
||||
alias /opt/c-relay-pg/admin/public/;
|
||||
index index.php;
|
||||
location ~ \.php$ { fastcgi_pass unix:/run/php/php8.2-fpm.sock; ... }
|
||||
}
|
||||
location ^~ /relay/api/chart.php { alias /opt/c-relay-pg/admin/api/chart.php; ... }
|
||||
location ^~ /relay/assets/ { alias /opt/c-relay-pg/admin/assets/; }
|
||||
|
||||
# Authenticated admin UI (Basic Auth)
|
||||
location /relay/admin/ {
|
||||
alias /opt/c-relay-pg/admin/;
|
||||
auth_basic "Relay Admin";
|
||||
auth_basic_user_file /opt/c-relay-pg/admin/.htpasswd;
|
||||
location ~ \.php$ { fastcgi_pass unix:/run/php/php8.2-fpm.sock; ... }
|
||||
location ^~ /relay/admin/lib/ { deny all; } # DB credentials
|
||||
location ^~ /relay/admin/public/ { deny all; } # served via /relay/
|
||||
}
|
||||
```
|
||||
|
||||
Create the Basic Auth credentials on the server:
|
||||
|
||||
```bash
|
||||
sudo htpasswd -c /opt/c-relay-pg/admin/.htpasswd <username>
|
||||
sudo systemctl reload nginx
|
||||
```
|
||||
|
||||
### Apache Configuration
|
||||
|
||||
#### WebSocket Proxy with mod_proxy_wstunnel
|
||||
|
||||
@@ -185,7 +185,7 @@ perform_backup() {
|
||||
print_step "Database size: $db_size"
|
||||
|
||||
# Create SQLite backup using .backup command (hot backup)
|
||||
if sqlite3 "$DB_FILE" ".backup $backup_file" 2>/dev/null; then
|
||||
if pg_dump -d crelay > "$backup_file"
|
||||
print_success "Database backup created: $backup_file"
|
||||
else
|
||||
# Fallback to file copy if .backup fails
|
||||
@@ -203,7 +203,7 @@ perform_backup() {
|
||||
# Check backup integrity
|
||||
if [[ "$VERIFY" == "true" ]]; then
|
||||
print_step "Verifying backup integrity..."
|
||||
if sqlite3 "$backup_file" "PRAGMA integrity_check;" | grep -q "ok"; then
|
||||
if pg_restore -l "$backup_file" &>/dev/null
|
||||
print_success "Backup integrity verified"
|
||||
else
|
||||
print_error "Backup integrity check failed"
|
||||
|
||||
@@ -247,7 +247,7 @@ check_database_integrity() {
|
||||
local integrity_ok=true
|
||||
for db_file in "${db_files[@]}"; do
|
||||
if [[ -r "$db_file" ]]; then
|
||||
if timeout 30 sqlite3 "$db_file" "PRAGMA integrity_check;" | grep -q "ok"; then
|
||||
if timeout 30 psql -d crelay "PRAGMA integrity_check;" | grep -q "ok"; then
|
||||
print_success "Database integrity OK: $(basename "$db_file")"
|
||||
else
|
||||
print_error "Database integrity failed: $(basename "$db_file")"
|
||||
@@ -292,7 +292,7 @@ check_configuration_events() {
|
||||
local config_count=0
|
||||
for db_file in "${db_files[@]}"; do
|
||||
if [[ -r "$db_file" ]]; then
|
||||
local count=$(sqlite3 "$db_file" "SELECT COUNT(*) FROM events WHERE kind = 33334;" 2>/dev/null || echo "0")
|
||||
local count=$(psql -d crelay "SELECT COUNT(*) FROM events WHERE kind = 33334;" 2>/dev/null || echo "0")
|
||||
config_count=$((config_count + count))
|
||||
fi
|
||||
done
|
||||
|
||||
@@ -155,10 +155,64 @@ http {
|
||||
log_not_found off;
|
||||
}
|
||||
|
||||
# PHP admin page for caching service (direct PostgreSQL access).
|
||||
# Bypasses the NIP-44 64KB encryption limit of the Nostr admin API.
|
||||
# ---------------------------------------------------------------
|
||||
# Public relay landing page + public chart endpoint.
|
||||
#
|
||||
# https://<domain>/relay/ -> public index.php
|
||||
# https://<domain>/relay/api/chart.php?range=... -> public ASCII chart
|
||||
# https://<domain>/relay/assets/... -> public CSS/JS
|
||||
#
|
||||
# No authentication. Exposes ONLY read-only, non-sensitive data:
|
||||
# relay name/description/pubkey and the aggregate event-rate chart.
|
||||
# All sensitive admin endpoints live under /relay/admin/ (see below).
|
||||
# Requires: php-fpm + php-pgsql installed and configured.
|
||||
location /admin/ {
|
||||
# ---------------------------------------------------------------
|
||||
location /relay/ {
|
||||
alias /opt/c-relay-pg/admin/public/;
|
||||
index index.php;
|
||||
|
||||
# Pass .php files to PHP-FPM
|
||||
location ~ \.php$ {
|
||||
# Adjust socket path for your distro:
|
||||
# Debian/Ubuntu: unix:/run/php/php8.2-fpm.sock
|
||||
# RHEL/Fedora: unix:/run/php-fpm/www.sock
|
||||
fastcgi_pass unix:/run/php/php8.2-fpm.sock;
|
||||
fastcgi_index index.php;
|
||||
include fastcgi_params;
|
||||
fastcgi_param SCRIPT_FILENAME $request_filename;
|
||||
}
|
||||
}
|
||||
|
||||
# Public chart endpoint — the public index.php fetches this relatively
|
||||
# as "api/chart.php". Map it to the admin's chart.php (read-only,
|
||||
# aggregate COUNT query; safe to expose). Only chart.php is served
|
||||
# here; all other admin/api/*.php endpoints stay behind /relay/admin/.
|
||||
location ^~ /relay/api/chart.php {
|
||||
alias /opt/c-relay-pg/admin/api/chart.php;
|
||||
fastcgi_pass unix:/run/php/php8.2-fpm.sock;
|
||||
fastcgi_index chart.php;
|
||||
include fastcgi_params;
|
||||
fastcgi_param SCRIPT_FILENAME $request_filename;
|
||||
}
|
||||
|
||||
# Public static assets (CSS/JS) for the public landing page.
|
||||
# The public index.php references these relatively as "assets/...".
|
||||
location ^~ /relay/assets/ {
|
||||
alias /opt/c-relay-pg/admin/assets/;
|
||||
}
|
||||
|
||||
# ---------------------------------------------------------------
|
||||
# Authenticated admin UI (full PHP admin).
|
||||
#
|
||||
# https://<domain>/relay/admin/ -> admin index.php
|
||||
# https://<domain>/relay/admin/api/*.php -> admin API endpoints
|
||||
#
|
||||
# Protected by HTTP Basic Auth. The PHP endpoints have NO server-side
|
||||
# auth of their own (the nostr_login_lite modal is client-side only),
|
||||
# so this Basic Auth gate is what actually secures config edits, auth
|
||||
# rules, IP bans, DMs, and raw SQL queries.
|
||||
# ---------------------------------------------------------------
|
||||
location /relay/admin/ {
|
||||
alias /opt/c-relay-pg/admin/;
|
||||
index index.php;
|
||||
|
||||
@@ -178,7 +232,13 @@ http {
|
||||
}
|
||||
|
||||
# Deny access to the lib/ directory (contains DB credentials)
|
||||
location ^~ /admin/lib/ {
|
||||
location ^~ /relay/admin/lib/ {
|
||||
deny all;
|
||||
}
|
||||
|
||||
# Deny access to the public/ directory from the admin path
|
||||
# (it is served publicly via /relay/ instead).
|
||||
location ^~ /relay/admin/public/ {
|
||||
deny all;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -60,12 +60,12 @@ install_dependencies() {
|
||||
|
||||
if [[ $OS == "debian" ]]; then
|
||||
apt update
|
||||
apt install -y build-essential git sqlite3 libsqlite3-dev \
|
||||
apt install -y build-essential git postgresql postgresql-client
|
||||
libwebsockets-dev libssl-dev libsecp256k1-dev \
|
||||
libcurl4-openssl-dev zlib1g-dev systemd curl wget
|
||||
elif [[ $OS == "redhat" ]]; then
|
||||
yum groupinstall -y "Development Tools"
|
||||
yum install -y git sqlite-devel libwebsockets-devel \
|
||||
yum install -y git postgresql-devel postgresql-server-devel
|
||||
openssl-devel libsecp256k1-devel libcurl-devel \
|
||||
zlib-devel systemd curl wget
|
||||
fi
|
||||
|
||||
+33
-50
@@ -8,14 +8,13 @@ echo "=== C Nostr Relay Build and Restart Script ==="
|
||||
# Parse command line arguments
|
||||
PRESERVE_DATABASE=false
|
||||
HELP=false
|
||||
USE_TEST_KEYS=false
|
||||
USE_TEST_KEYS=true
|
||||
ADMIN_KEY=""
|
||||
RELAY_KEY=""
|
||||
PORT_OVERRIDE=""
|
||||
DEBUG_LEVEL="5"
|
||||
START_CACHING=false
|
||||
RESET_BACKFILL=false
|
||||
DB_BACKEND="postgres"
|
||||
DB_CONNSTRING=""
|
||||
DB_HOST=""
|
||||
DB_PORT=""
|
||||
@@ -87,24 +86,10 @@ while [[ $# -gt 0 ]]; do
|
||||
;;
|
||||
--test-keys|-t)
|
||||
USE_TEST_KEYS=true
|
||||
# Read keys from .test_keys file
|
||||
if [ -f ".test_keys" ]; then
|
||||
echo "Reading test keys from .test_keys file..."
|
||||
# Source the file to get the variables
|
||||
source .test_keys
|
||||
# Remove any single quotes from the values
|
||||
# Note: -a flag expects ADMIN_PUBKEY (public key), not ADMIN_PRIVKEY
|
||||
ADMIN_KEY=$(echo "$ADMIN_PUBKEY" | tr -d "'")
|
||||
RELAY_KEY=$(echo "$SERVER_PRIVKEY" | tr -d "'")
|
||||
echo "Using admin pubkey from .test_keys: ${ADMIN_KEY:0:16}..."
|
||||
echo "Using relay privkey from .test_keys: ${RELAY_KEY:0:16}..."
|
||||
else
|
||||
echo "ERROR: .test_keys file not found"
|
||||
echo "Please create a .test_keys file with the following format:"
|
||||
echo " ADMIN_PUBKEY='your_admin_public_key_hex'"
|
||||
echo " SERVER_PRIVKEY='your_relay_private_key_hex'"
|
||||
exit 1
|
||||
fi
|
||||
shift
|
||||
;;
|
||||
--no-test-keys|--production)
|
||||
USE_TEST_KEYS=false
|
||||
shift
|
||||
;;
|
||||
--debug-level=*)
|
||||
@@ -135,20 +120,6 @@ while [[ $# -gt 0 ]]; do
|
||||
shift 2
|
||||
fi
|
||||
;;
|
||||
--db-backend)
|
||||
if [ -z "$2" ]; then
|
||||
echo "ERROR: --db-backend requires a value (sqlite|postgres)"
|
||||
HELP=true
|
||||
shift
|
||||
else
|
||||
DB_BACKEND="$2"
|
||||
shift 2
|
||||
fi
|
||||
;;
|
||||
--db-backend=*)
|
||||
DB_BACKEND="${1#*=}"
|
||||
shift
|
||||
;;
|
||||
--db-connstring)
|
||||
if [ -z "$2" ]; then
|
||||
echo "ERROR: --db-connstring requires a value"
|
||||
@@ -238,6 +209,24 @@ if [ -n "$RELAY_KEY" ]; then
|
||||
fi
|
||||
fi
|
||||
|
||||
# Load test keys from .test_keys file if USE_TEST_KEYS is true and no explicit keys given
|
||||
if [ "$USE_TEST_KEYS" = true ] && [ -z "$ADMIN_KEY" ] && [ -z "$RELAY_KEY" ]; then
|
||||
if [ -f ".test_keys" ]; then
|
||||
echo "Reading test keys from .test_keys file..."
|
||||
source .test_keys
|
||||
ADMIN_KEY=$(echo "$ADMIN_PUBKEY" | tr -d "'")
|
||||
RELAY_KEY=$(echo "$SERVER_PRIVKEY" | tr -d "'")
|
||||
echo "Using admin pubkey from .test_keys: ${ADMIN_KEY:0:16}..."
|
||||
echo "Using relay privkey from .test_keys: ${RELAY_KEY:0:16}..."
|
||||
else
|
||||
echo "ERROR: .test_keys file not found"
|
||||
echo "Please create a .test_keys file with the following format:"
|
||||
echo " ADMIN_PUBKEY='your_admin_public_key_hex'"
|
||||
echo " SERVER_PRIVKEY='your_relay_private_key_hex'"
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
|
||||
# Validate port if provided
|
||||
if [ -n "$PORT_OVERRIDE" ]; then
|
||||
if ! [[ "$PORT_OVERRIDE" =~ ^[0-9]+$ ]] || [ "$PORT_OVERRIDE" -lt 1 ] || [ "$PORT_OVERRIDE" -gt 65535 ]; then
|
||||
@@ -259,12 +248,6 @@ if [ -n "$DEBUG_LEVEL" ]; then
|
||||
fi
|
||||
fi
|
||||
|
||||
# Validate DB backend
|
||||
if [ "$DB_BACKEND" != "sqlite" ] && [ "$DB_BACKEND" != "postgres" ]; then
|
||||
echo "ERROR: Invalid --db-backend value '$DB_BACKEND'. Use sqlite or postgres."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Validate DB port if provided
|
||||
if [ -n "$DB_PORT" ]; then
|
||||
if ! [[ "$DB_PORT" =~ ^[0-9]+$ ]] || [ "$DB_PORT" -lt 1 ] || [ "$DB_PORT" -gt 65535 ]; then
|
||||
@@ -273,7 +256,7 @@ if [ -n "$DB_PORT" ]; then
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ "$DB_BACKEND" = "postgres" ] && [ -z "$DB_CONNSTRING" ]; then
|
||||
if [ -z "$DB_CONNSTRING" ]; then
|
||||
[ -z "$DB_HOST" ] && DB_HOST="localhost"
|
||||
[ -z "$DB_PORT" ] && DB_PORT="5432"
|
||||
[ -z "$DB_NAME" ] && DB_NAME="crelay"
|
||||
@@ -361,8 +344,8 @@ if [ "$HELP" = true ]; then
|
||||
echo " -p, --port <port> Custom port override (default: 8888)"
|
||||
echo " -d, --debug-level <0-5> Set debug level: 0=none, 1=errors, 2=warnings, 3=info, 4=debug, 5=trace"
|
||||
echo " --preserve-database Keep existing database files (don't delete for fresh start)"
|
||||
echo " --test-keys, -t Use deterministic test keys for development (admin: all 'a's, relay: all '1's)"
|
||||
echo " --db-backend <name> Database backend: postgres (default) or sqlite"
|
||||
echo " --test-keys, -t Use deterministic test keys for development (admin: all 'a's, relay: all '1's) [default]"
|
||||
echo " --no-test-keys, --production Generate random keys (production mode)"
|
||||
echo " --db-connstring <str> PostgreSQL libpq connection string"
|
||||
echo " --db-host <host> PostgreSQL host"
|
||||
echo " --db-port <port> PostgreSQL port"
|
||||
@@ -379,7 +362,7 @@ if [ "$HELP" = true ]; then
|
||||
echo " Database file: <relay_pubkey>.db (created automatically)"
|
||||
echo ""
|
||||
echo "Examples:"
|
||||
echo " $0 # Fresh start with random keys"
|
||||
echo " $0 # Fresh start with test keys (default)"
|
||||
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 -p 7777 --strict-port # Fail if port 7777 unavailable (no fallback)"
|
||||
@@ -387,8 +370,8 @@ if [ "$HELP" = true ]; then
|
||||
echo " $0 --debug-level=3 # Start with debug level 3 (info)"
|
||||
echo " $0 -d=5 # Start with debug level 5 (trace)"
|
||||
echo " $0 --preserve-database # Preserve existing database and keys"
|
||||
echo " $0 --test-keys # Use test keys for consistent development"
|
||||
echo " $0 -t --preserve-database # Use test keys and preserve database"
|
||||
echo " $0 --no-test-keys # Generate random keys (production)"
|
||||
echo " $0 --no-test-keys --preserve-database # Production mode with database preservation"
|
||||
echo ""
|
||||
echo "Default PostgreSQL connection (when no DB flags provided):"
|
||||
echo " host=localhost port=5432 dbname=crelay user=crelay password=crelay"
|
||||
@@ -416,7 +399,7 @@ fi
|
||||
rm -rf dev-config/ 2>/dev/null
|
||||
rm -f db/c_nostr_relay.db* 2>/dev/null
|
||||
|
||||
if [ "$DB_BACKEND" = "postgres" ] && [ -z "$DB_CONNSTRING" ]; then
|
||||
if [ -z "$DB_CONNSTRING" ]; then
|
||||
ensure_postgres_database || exit 1
|
||||
fi
|
||||
|
||||
@@ -424,9 +407,9 @@ fi
|
||||
echo "Embedding web files..."
|
||||
./embed_web_files.sh
|
||||
|
||||
# Build the project - ONLY static build
|
||||
echo "Building project (static binary, backend: $DB_BACKEND)..."
|
||||
./build_static.sh --db-backend "$DB_BACKEND"
|
||||
# Build the project - ONLY static build (PostgreSQL backend)
|
||||
echo "Building project (static binary, backend: postgres)..."
|
||||
./build_static.sh
|
||||
|
||||
# Exit if static build fails - no fallback
|
||||
if [ $? -ne 0 ]; then
|
||||
|
||||
@@ -0,0 +1,441 @@
|
||||
# Cache-All Feasibility Test Program
|
||||
|
||||
## Goal
|
||||
|
||||
Build a standalone C test program that connects to all outbox relays of followed
|
||||
pubkeys and attempts to subscribe to **all events** (no author filter) to
|
||||
determine if relays will tolerate this level of data flow. The program logs all
|
||||
relay interactions (disconnections, rate limiting, CLOSED messages, NOTICE
|
||||
messages) so we can assess feasibility before modifying the caching daemon.
|
||||
|
||||
## Background
|
||||
|
||||
The current caching daemon subscribes only to events from followed pubkeys
|
||||
using `authors=[followed_set]` filters. The proposed "cache everything" approach
|
||||
would subscribe to all events on those relays and prune old non-followed events
|
||||
later. The key unknown is whether relays will allow this — they may disconnect
|
||||
or rate-limit clients that request too much data.
|
||||
|
||||
## Preliminary Probe Results (60s on 3 major relays)
|
||||
|
||||
Before designing the test program, we ran 60-second probes using `nak req --stream`
|
||||
with no filter (all events) against 3 major relays to measure real-world data volume
|
||||
and kind distribution.
|
||||
|
||||
### Relay Connectivity
|
||||
|
||||
| Relay | Events/60s | Avg Bytes | Max Event | Unique Pubkeys | Notes |
|
||||
|-------|-----------|-----------|-----------|----------------|-------|
|
||||
| nos.lol | 2,634 | 1,713 | 44,372 (kind 30089) | 1,228 | Connected OK |
|
||||
| relay.primal.net | 1,547 | 1,920 | 207,377 (kind 3) | 613 | Connected OK |
|
||||
| relay.damus.io | 0 | — | — | — | HTTP 503 (unavailable) |
|
||||
|
||||
### Kind Distribution (nos.lol + primal combined, ~4,181 events)
|
||||
|
||||
| Kind | Description | Count | % | Avg Bytes | Notes |
|
||||
|------|-------------|-------|---|-----------|-------|
|
||||
| **21059** | Gift wrap (NIP-59) | 1,063 | 25.4% | 2,574 | Encrypted DMs — large, noisy |
|
||||
| **5** | Deletion requests | 592 | 14.2% | 447 | Very common |
|
||||
| **30078** | App-specific data | 173 | 4.1% | 3,670 | Variable size, can be large |
|
||||
| **20001** | Ephemeral (key exchange?) | 253 | 6.0% | 849 | Short-lived |
|
||||
| **22580** | WebRTC signaling | 193 | 4.6% | 795 | Noise |
|
||||
| **1059** | Gift wrap seal (NIP-59) | 154 | 3.7% | 3,023 | Encrypted wrapper |
|
||||
| **22734** | WebRTC signaling | 168 | 4.0% | 427 | Noise |
|
||||
| **1** | Text notes | 58 | 1.4% | 812 | **Primary content** |
|
||||
| **7** | Reactions | 59 | 1.4% | 534 | Likes |
|
||||
| **0** | Profile metadata | 33 | 0.8% | 985 | Replaceable |
|
||||
| **3** | Follow lists | 10 | 0.2% | 43,077 | Replaceable, can be huge |
|
||||
| **10002** | Relay lists | 55 | 1.3% | 418 | Small |
|
||||
| **9735** | Zap receipts | 22 | 0.5% | 2,110 | Payment confirmations |
|
||||
| **6** | Reposts | 11 | 0.3% | 1,876 | |
|
||||
| **30023** | Long-form articles | 3 | 0.1% | 6,119 | |
|
||||
| **30089** | Chunked data | 16 | 0.4% | 43,907 | **Very large** (avg 44KB!) |
|
||||
| **30001** | Lists (encrypted) | 4 | 0.1% | 30,538 | Large encrypted content |
|
||||
| **30815** | Ephemeral large | 4 | 0.1% | 37,534 | **Very large** (avg 37KB!) |
|
||||
| **25555** | App data | 31 | 0.7% | 5,115 | |
|
||||
| **13194** | NWC info | 15 | 0.4% | 514 | Wallet connect |
|
||||
| **445** | Encrypted group msg | 22 | 0.5% | 1,452 | |
|
||||
| **Other** | 90+ other kinds | ~600 | ~14% | varies | Long tail of app-specific kinds |
|
||||
|
||||
### Key Findings
|
||||
|
||||
1. **Gift wrap (kind 21059) dominates**: 25% of all events are NIP-59 gift wraps
|
||||
(encrypted DMs). These are large (~2.5KB avg) and mostly noise for a caching relay.
|
||||
They have `expiration` tags and are ephemeral by nature.
|
||||
|
||||
2. **Deletion requests (kind 5) are extremely common**: 14% of all events. This is
|
||||
surprising — relays are very busy processing deletes.
|
||||
|
||||
3. **WebRTC signaling (kinds 22580, 22734, etc.) is ~10% of traffic**: These are
|
||||
ephemeral signaling events for video/voice calls. Pure noise for caching.
|
||||
|
||||
4. **"Social" content (kinds 1, 7, 6, 0, 3) is only ~4% of total events**: The
|
||||
vast majority of relay traffic is NOT the content users actually see.
|
||||
|
||||
5. **Some kinds are extremely large**: Kind 30089 averages 44KB, kind 30001 averages
|
||||
30KB, kind 30815 averages 37KB. These would consume significant storage.
|
||||
|
||||
6. **Data volume is manageable**: ~2,600-4,200 events/min across 2 relays. At this
|
||||
rate, a 24h test would collect ~3.7-6M events. Storage would be ~6-10 GB of raw
|
||||
JSON.
|
||||
|
||||
7. **Damus.io is unavailable**: Returns HTTP 503. This may be temporary or may
|
||||
indicate they block unfiltered subscriptions.
|
||||
|
||||
### Implications for the Test Program
|
||||
|
||||
- **Subscribe to ALL kinds** for the test — we need to measure which kinds relays
|
||||
actually send and whether they tolerate the volume.
|
||||
- **Do NOT save full event JSON** during the test — at ~2MB/min, a 24h run would
|
||||
produce ~3GB of raw data per relay. Instead, log kind/pubkey/size summaries.
|
||||
- **Track kind 21059 (gift wrap) separately** — it's the dominant kind and may
|
||||
need special handling in the real implementation.
|
||||
- **Monitor for CLOSED messages** — if relays start closing subscriptions due to
|
||||
volume, we'll see it in the raw relay log.
|
||||
|
||||
## Architecture
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────┐
|
||||
│ cache_all_feasibility_test │
|
||||
│ │
|
||||
│ 1. Load root npubs from config.jsonc │
|
||||
│ 2. Resolve follow graph (kind-3) → followed set │
|
||||
│ 3. Discover outbox relays (kind-10002) for each follow │
|
||||
│ 4. Compute minimum covering set of relays │
|
||||
│ 5. Connect to all covering relays │
|
||||
│ 6. Subscribe to ALL events (no authors filter) on each │
|
||||
│ 7. Log every event received (counts + stats, not full JSON)│
|
||||
│ 8. Log every relay message: CLOSED, NOTICE, EOSE, error │
|
||||
│ 9. Run for configurable duration (default 24h) │
|
||||
│ 10. Save summary report + per-relay stats to files │
|
||||
└─────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
## File Structure
|
||||
|
||||
All new files go in `caching/` directory, alongside the existing daemon:
|
||||
|
||||
```
|
||||
caching/
|
||||
├── Makefile # Modified: add test target
|
||||
├── src/
|
||||
│ ├── main.c # Existing daemon (unchanged)
|
||||
│ ├── cache_all_test.c # NEW: test program entry point
|
||||
│ ├── cache_all_test.h # NEW: test program header
|
||||
│ ├── debug.c / debug.h # Existing (reused)
|
||||
│ ├── config.c / config.h # Existing (reused for config loading)
|
||||
│ ├── state.c / state.h # Existing (reused for pubkey set)
|
||||
│ ├── follow_graph.c / follow_graph.h # Existing (reused)
|
||||
│ ├── relay_discovery.c / relay_discovery.h # Existing (reused)
|
||||
│ └── ... # Other existing files unchanged
|
||||
```
|
||||
|
||||
## Detailed Design
|
||||
|
||||
### 1. Config Loading (reuse existing)
|
||||
|
||||
Reuse [`caching/src/config.c`](caching/src/config.c) and
|
||||
[`caching/src/config.h`](caching/src/config.h) to load root npubs, upstream
|
||||
relays, kinds, and follow graph settings from the same `.jsonc` config file
|
||||
the daemon uses.
|
||||
|
||||
### 2. Follow Graph Resolution (reuse existing)
|
||||
|
||||
Reuse [`caching/src/follow_graph.c`](caching/src/follow_graph.c) to:
|
||||
- Decode root npubs to hex
|
||||
- Query each root's most recent kind-3 contact list from bootstrap relays
|
||||
- Build the `cr_pubkey_set_t` of followed pubkeys
|
||||
|
||||
### 3. Relay Discovery (reuse existing)
|
||||
|
||||
Reuse [`caching/src/relay_discovery.c`](caching/src/relay_discovery.c) to:
|
||||
- Query kind-10002 for each followed pubkey
|
||||
- Parse "r" tags to build outbox relay map
|
||||
- Compute minimum covering set of relays
|
||||
|
||||
### 4. Subscription Strategy
|
||||
|
||||
For each relay in the covering set, open a subscription with:
|
||||
|
||||
```c
|
||||
// Filter: ALL events (no authors, no kinds, no limit)
|
||||
cJSON *filter = cJSON_CreateObject();
|
||||
cJSON_AddItemToObject(filter, "since", cJSON_CreateNumber((double)time(NULL)));
|
||||
```
|
||||
|
||||
This requests every new event from `now` onward on that relay.
|
||||
|
||||
**Key difference from existing daemon:** No `authors` filter. This means we
|
||||
receive events from *everyone* on that relay, not just followed pubkeys.
|
||||
|
||||
### 5. Event Handling & Logging
|
||||
|
||||
The `on_event` callback should:
|
||||
|
||||
1. **Count events per relay** (maintain a per-relay counter)
|
||||
2. **Count events per kind** (maintain a kind distribution map)
|
||||
3. **Count events per pubkey** (track which pubkeys are most active)
|
||||
4. **Log at INFO level** every N events (e.g., every 1000) with summary stats
|
||||
5. **Do NOT save full event JSON to disk during the run** (would be too much data)
|
||||
6. **Periodically checkpoint** (every 5 min) a summary to a file
|
||||
|
||||
### 6. Relay Interaction Logging — Raw Relay Responses
|
||||
|
||||
**Critical requirement:** Log the **actual raw response text** from the relay,
|
||||
not an interpreted summary. The relay's own words are what matter.
|
||||
|
||||
The `on_event`, `on_eose`, and subscription status callbacks from
|
||||
[`nostr_core_lib`](../nostr_core_lib) provide status strings and message
|
||||
content. These must be logged **verbatim**.
|
||||
|
||||
#### What to log and how:
|
||||
|
||||
| Trigger | Log Level | What to Log (verbatim relay text) |
|
||||
|---------|-----------|-----------------------------------|
|
||||
| EOSE | INFO | `[RELAY] <url> EOSE` |
|
||||
| CLOSED | WARN | `[RELAY] <url> CLOSED: <relay's exact reason text>` |
|
||||
| NOTICE | WARN | `[RELAY] <url> NOTICE: <relay's exact notice text>` |
|
||||
| Error | ERROR | `[RELAY] <url> ERROR: <relay's exact error message>` |
|
||||
| Disconnect | WARN | `[RELAY] <url> DISCONNECTED: <transport-level error if any>` |
|
||||
| Reconnect | INFO | `[RELAY] <url> RECONNECTED` |
|
||||
| OK (publish) | INFO | `[RELAY] <url> OK: <event_id> <relay's exact message>` |
|
||||
|
||||
**Do NOT** categorize or summarize. If a relay says:
|
||||
```
|
||||
"rate-limited: please wait 60 seconds before sending new requests"
|
||||
```
|
||||
log that exact string. Do NOT log just `"rate-limited"`.
|
||||
|
||||
#### Raw Relay Log File
|
||||
|
||||
In addition to the normal debug log output, write a **raw relay log file**:
|
||||
|
||||
```
|
||||
cache_all_test_raw_relay_<timestamp>.log
|
||||
```
|
||||
|
||||
This file contains **only** relay responses, one per line, in this format:
|
||||
|
||||
```
|
||||
[TIMESTAMP] [RELAY] <relay_url> <RAW_RESPONSE>
|
||||
```
|
||||
|
||||
Example:
|
||||
```
|
||||
[2026-08-02 13:01:00] [RELAY] wss://relay.damus.io CLOSED: "rate-limited: please wait 60 seconds before sending new requests"
|
||||
[2026-08-02 13:01:05] [RELAY] wss://relay.damus.io RECONNECTED
|
||||
[2026-08-02 13:01:10] [RELAY] wss://relay.damus.io NOTICE: "too many subscriptions, closing oldest"
|
||||
[2026-08-02 13:02:00] [RELAY] wss://relay.primal.net EOSE
|
||||
[2026-08-02 13:02:01] [RELAY] wss://relay.primal.net ERROR: "connection closed unexpectedly"
|
||||
```
|
||||
|
||||
This file is append-only and can be `tail -f`'d during the test run.
|
||||
|
||||
#### Event Logging
|
||||
|
||||
For events received, log at TRACE level (not to the raw relay log):
|
||||
|
||||
```
|
||||
[TRACE] [EVENT] relay=<url> kind=<N> pubkey=<first8chars>... id=<first8chars>...
|
||||
```
|
||||
|
||||
This gives enough to correlate without flooding the log with full JSON.
|
||||
Every 1000 events, log a summary at INFO level:
|
||||
|
||||
```
|
||||
[INFO] [STATS] 5000 events received total | relayA: 3200 relayB: 1800 | kinds: 1=4500 7=500
|
||||
```
|
||||
|
||||
### 7. Summary Report
|
||||
|
||||
At the end of the run (or on SIGINT/SIGTERM), write a report file:
|
||||
|
||||
```
|
||||
cache_all_test_report_<timestamp>.txt
|
||||
```
|
||||
|
||||
Contents:
|
||||
|
||||
```
|
||||
=== Cache-All Feasibility Test Report ===
|
||||
Duration: 24h 3m 12s
|
||||
Config: ./caching_relay_config.jsonc
|
||||
|
||||
=== Relay Summary ===
|
||||
Relay Events EOSE CLOSED NOTICE Errors Status
|
||||
wss://relay.example.com 124532 12 0 2 0 OK
|
||||
wss://relay2.example.com 0 0 3 5 2 BLOCKED
|
||||
|
||||
=== Kind Distribution ===
|
||||
Kind Count %
|
||||
0 1,234 0.5%
|
||||
1 234,567 94.2%
|
||||
3 567 0.2%
|
||||
7 12,345 5.0%
|
||||
9734 234 0.1%
|
||||
|
||||
=== Top 10 Pubkeys by Event Count ===
|
||||
pubkey_hex_here... 12,345 events
|
||||
pubkey_hex_here... 8,901 events
|
||||
...
|
||||
|
||||
=== Raw Relay Response Log ===
|
||||
[2026-08-02 13:01:00] wss://relay.damus.io CLOSED: "rate-limited: please wait 60 seconds before sending new requests"
|
||||
[2026-08-02 13:01:05] wss://relay.damus.io RECONNECTED
|
||||
[2026-08-02 13:01:10] wss://relay.damus.io NOTICE: "too many subscriptions, closing oldest"
|
||||
[2026-08-02 13:02:00] wss://relay.primal.net EOSE
|
||||
[2026-08-02 13:02:01] wss://relay.primal.net ERROR: "connection closed unexpectedly"
|
||||
...
|
||||
```
|
||||
|
||||
The Raw Relay Response Log section is a copy of the raw relay log file
|
||||
([`cache_all_test_raw_relay_<timestamp>.log`](caching/cache_all_test_raw_relay_20260802_130000.log)).
|
||||
It contains the **verbatim** text from each relay response, not interpreted
|
||||
or summarized.
|
||||
|
||||
### 8. Per-Relay Stats File
|
||||
|
||||
Additionally, write a JSON file with per-relay detailed stats:
|
||||
|
||||
```
|
||||
cache_all_test_stats_<timestamp>.json
|
||||
```
|
||||
|
||||
This can be used for programmatic analysis. It includes the raw relay
|
||||
response text for each interaction, not just counts.
|
||||
|
||||
## Implementation Steps
|
||||
|
||||
### Step 1: Create `caching/src/cache_all_test.h`
|
||||
|
||||
Header file declaring the test program's public interface:
|
||||
|
||||
```c
|
||||
#ifndef CACHE_ALL_TEST_H
|
||||
#define CACHE_ALL_TEST_H
|
||||
|
||||
/* Run the cache-all feasibility test.
|
||||
* config_path: path to .jsonc config file
|
||||
* duration_seconds: how long to run (0 = run until SIGINT)
|
||||
* log_level: debug level 0-5
|
||||
* Returns 0 on success, -1 on error.
|
||||
*/
|
||||
int run_cache_all_test(const char *config_path,
|
||||
long duration_seconds,
|
||||
int log_level);
|
||||
|
||||
#endif
|
||||
```
|
||||
|
||||
### Step 2: Create `caching/src/cache_all_test.c`
|
||||
|
||||
Main implementation file with these sections:
|
||||
|
||||
1. **Includes and forward declarations**
|
||||
2. **Per-relay stats tracking structure**
|
||||
3. **Global stats accumulator**
|
||||
4. **Callback implementations** (on_event, on_eose, on_status)
|
||||
5. **Report generation** (write summary + JSON stats)
|
||||
6. **Main entry point** (`run_cache_all_test`)
|
||||
|
||||
### Step 3: Modify `caching/Makefile`
|
||||
|
||||
Add a new target `cache_all_test` that compiles the test program:
|
||||
|
||||
```makefile
|
||||
TEST_SRC = src/cache_all_test.c src/debug.c src/jsonc_strip.c src/config.c \
|
||||
src/state.c src/follow_graph.c src/relay_discovery.c
|
||||
|
||||
cache_all_test: $(TEST_SRC) $(NOSTR_CORE_LIB)
|
||||
# ... compile to ../build/cache_all_test
|
||||
```
|
||||
|
||||
### Step 4: Build and Run
|
||||
|
||||
```bash
|
||||
cd caching && make cache_all_test
|
||||
./build/cache_all_test -c caching_relay_config.jsonc -d 3 -t 86400
|
||||
```
|
||||
|
||||
## Output Files
|
||||
|
||||
| File | Contents |
|
||||
|------|----------|
|
||||
| `cache_all_test_raw_relay_<timestamp>.log` | **Primary output.** One line per relay response, verbatim text. Can be `tail -f`'d live. |
|
||||
| `cache_all_test_report_<timestamp>.txt` | Summary report with counts, kind distribution, top pubkeys, and raw relay log section. |
|
||||
| `cache_all_test_stats_<timestamp>.json` | Machine-readable JSON with per-relay stats including raw response texts. |
|
||||
|
||||
## What We're Measuring
|
||||
|
||||
1. **Relay tolerance**: Do relays CLOSE our subscription or disconnect us?
|
||||
2. **Rate limiting**: How often do we get rate-limited? What are the cooldown periods?
|
||||
3. **Data volume**: How many events per hour per relay? What's the kind distribution?
|
||||
4. **Connection stability**: How often do relays drop us? Do they allow reconnection?
|
||||
5. **Pubkey diversity**: How many unique pubkeys are posting? What's the ratio of followed vs non-followed events?
|
||||
|
||||
## Success Criteria
|
||||
|
||||
The test is considered a **success** (feasible) if:
|
||||
|
||||
- At least 80% of relays maintain the subscription for the full duration
|
||||
- Rate limiting events are infrequent (< 5 per relay per day)
|
||||
- No relay permanently bans or blacklists the connection
|
||||
- Data volume is manageable (under ~1M events/day total)
|
||||
|
||||
The test is considered a **failure** (not feasible) if:
|
||||
|
||||
- Most relays CLOSE the subscription within minutes
|
||||
- Rate limiting is constant (every few minutes)
|
||||
- Multiple relays permanently disconnect
|
||||
|
||||
## Non-Goals
|
||||
|
||||
- This test does NOT save events to PostgreSQL
|
||||
- This test does NOT modify the existing caching daemon
|
||||
- This test does NOT implement pruning logic
|
||||
- This test does NOT need to be efficient for production use
|
||||
|
||||
## Mermaid Diagram
|
||||
|
||||
```mermaid
|
||||
flowchart TD
|
||||
A[Start] --> B[Load config from .jsonc]
|
||||
B --> C[Resolve follow graph kind-3]
|
||||
C --> D[Discover outbox relays kind-10002]
|
||||
D --> E[Compute min covering set]
|
||||
E --> F[Connect to all covering relays]
|
||||
F --> G[Subscribe to ALL events no authors filter]
|
||||
G --> H{Test duration reached or SIGINT?}
|
||||
H -->|No| I[Pump relay pool]
|
||||
I --> J[Count events per relay/kind/pubkey]
|
||||
J --> K[Log relay interactions CLOSED/NOTICE/errors]
|
||||
K --> L[Periodic checkpoint every 5 min]
|
||||
L --> H
|
||||
H -->|Yes| M[Write summary report]
|
||||
M --> N[Write per-relay JSON stats]
|
||||
N --> O[Cleanup and exit]
|
||||
```
|
||||
|
||||
## Files to Create
|
||||
|
||||
| File | Purpose |
|
||||
|------|---------|
|
||||
| [`caching/src/cache_all_test.h`](caching/src/cache_all_test.h) | Header with public API |
|
||||
| [`caching/src/cache_all_test.c`](caching/src/cache_all_test.c) | Main implementation (~400-500 lines) |
|
||||
|
||||
## Files to Modify
|
||||
|
||||
| File | Change |
|
||||
|------|--------|
|
||||
| [`caching/Makefile`](caching/Makefile) | Add `cache_all_test` target |
|
||||
|
||||
## Files NOT Modified
|
||||
|
||||
The existing caching daemon files are **not touched**:
|
||||
- `caching/src/main.c` — unchanged
|
||||
- `caching/src/backfill.c` — unchanged
|
||||
- `caching/src/live_subscriber.c` — unchanged
|
||||
- `caching/src/pg_inbox.c` — unchanged
|
||||
- `caching/src/forward_catchup.c` — unchanged
|
||||
- `caching/src/pg_config.c` — unchanged
|
||||
@@ -0,0 +1,331 @@
|
||||
# Event Cleanup Page — Design Plan
|
||||
|
||||
## Overview
|
||||
|
||||
A dedicated admin page for creating, previewing, saving, and executing event deletion queries. Users can filter by follows/non-follows (from caching data), event kinds, and event age, see estimated data savings, and save named queries for reuse.
|
||||
|
||||
---
|
||||
|
||||
## 1. New Database Table
|
||||
|
||||
A new table to persist named cleanup queries:
|
||||
|
||||
```sql
|
||||
CREATE TABLE IF NOT EXISTS cleanup_saved_queries (
|
||||
id BIGSERIAL PRIMARY KEY,
|
||||
name TEXT NOT NULL UNIQUE,
|
||||
follows_filter TEXT NOT NULL DEFAULT 'all'
|
||||
CHECK (follows_filter IN ('all', 'follows', 'non_follows')),
|
||||
kinds INTEGER[] NOT NULL DEFAULT '{}',
|
||||
max_age_days INTEGER NOT NULL DEFAULT 0,
|
||||
max_events INTEGER NOT NULL DEFAULT 0,
|
||||
last_preview_count INTEGER NOT NULL DEFAULT 0,
|
||||
last_preview_size_bytes BIGINT NOT NULL DEFAULT 0,
|
||||
last_executed_at BIGINT NOT NULL DEFAULT 0,
|
||||
created_at BIGINT NOT NULL DEFAULT EXTRACT(EPOCH FROM NOW())::BIGINT,
|
||||
updated_at BIGINT NOT NULL DEFAULT EXTRACT(EPOCH FROM NOW())::BIGINT
|
||||
);
|
||||
```
|
||||
|
||||
- `kinds` — PostgreSQL integer array. Empty array `{}` means "all kinds".
|
||||
- `max_age_days` — 0 means "no age filter".
|
||||
- `max_events` — 0 means "no limit". Used to cap DELETE in batches.
|
||||
- `follows_filter` — `'all'` = no follow restriction, `'follows'` = only events from pubkeys in `caching_followed_pubkeys`, `'non_follows'` = only events from pubkeys NOT in `caching_followed_pubkeys`.
|
||||
|
||||
---
|
||||
|
||||
## 2. New API Endpoints
|
||||
|
||||
### 2a. `admin/api/cleanup.php` — Preview & Execute
|
||||
|
||||
**GET** — Preview a cleanup query (returns count + size estimate without deleting).
|
||||
|
||||
Query parameters:
|
||||
- `follows_filter` — `all`, `follows`, `non_follows`
|
||||
- `kinds` — comma-separated kind numbers (empty = all)
|
||||
- `max_age_days` — integer
|
||||
- `max_events` — integer (0 = no limit)
|
||||
|
||||
Response:
|
||||
```json
|
||||
{
|
||||
"match_count": 45231,
|
||||
"total_size_bytes": 52428800,
|
||||
"total_size_human": "50.0 MB",
|
||||
"avg_size_per_event": 1159,
|
||||
"kinds_breakdown": [
|
||||
{"kind": 1, "count": 30000, "size_bytes": 35000000},
|
||||
{"kind": 7, "count": 10000, "size_bytes": 10000000}
|
||||
],
|
||||
"sql_preview": "SELECT ..."
|
||||
}
|
||||
```
|
||||
|
||||
**POST** — Execute a saved cleanup query (by ID) or an ad-hoc query.
|
||||
|
||||
Body:
|
||||
```json
|
||||
{
|
||||
"query_id": 1,
|
||||
"dry_run": true
|
||||
}
|
||||
```
|
||||
|
||||
Or for ad-hoc:
|
||||
```json
|
||||
{
|
||||
"follows_filter": "non_follows",
|
||||
"kinds": [1, 7],
|
||||
"max_age_days": 90,
|
||||
"max_events": 10000,
|
||||
"dry_run": true
|
||||
}
|
||||
```
|
||||
|
||||
If `dry_run: true`, returns preview only (same as GET). If `dry_run: false`, executes the DELETE and returns:
|
||||
```json
|
||||
{
|
||||
"deleted_count": 45231,
|
||||
"freed_bytes": 52428800,
|
||||
"freed_human": "50.0 MB",
|
||||
"duration_ms": 1234
|
||||
}
|
||||
```
|
||||
|
||||
### 2b. `admin/api/cleanup_queries.php` — Saved Query CRUD
|
||||
|
||||
**GET** — List all saved queries:
|
||||
```json
|
||||
{
|
||||
"queries": [
|
||||
{
|
||||
"id": 1,
|
||||
"name": "Old non-follow kind 1",
|
||||
"follows_filter": "non_follows",
|
||||
"kinds": [1],
|
||||
"max_age_days": 90,
|
||||
"max_events": 0,
|
||||
"last_preview_count": 45231,
|
||||
"last_preview_size_human": "50.0 MB",
|
||||
"last_executed_at": null,
|
||||
"created_at": "2026-08-01 12:00:00"
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
**POST** — Create or update a saved query:
|
||||
```json
|
||||
{
|
||||
"action": "save",
|
||||
"id": null,
|
||||
"name": "Old non-follow kind 1",
|
||||
"follows_filter": "non_follows",
|
||||
"kinds": [1, 7],
|
||||
"max_age_days": 90,
|
||||
"max_events": 0
|
||||
}
|
||||
```
|
||||
|
||||
**POST with `action: delete`** — Delete a saved query by ID.
|
||||
|
||||
**POST with `action: execute`** — Execute a saved query (non-dry-run):
|
||||
```json
|
||||
{
|
||||
"action": "execute",
|
||||
"id": 1
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 3. SQL Query Construction
|
||||
|
||||
The core SQL pattern for preview:
|
||||
|
||||
```sql
|
||||
SELECT COUNT(*) AS match_count,
|
||||
COALESCE(SUM(pg_column_size(event_json)), 0) AS total_size_bytes
|
||||
FROM events e
|
||||
WHERE 1=1
|
||||
[AND e.kind = ANY(:kinds)] -- if kinds is non-empty
|
||||
[AND e.created_at < EXTRACT(EPOCH FROM NOW())::BIGINT - :max_age_days * 86400] -- if max_age_days > 0
|
||||
[AND e.pubkey IN (SELECT pubkey FROM caching_followed_pubkeys)] -- if follows_filter = 'follows'
|
||||
[AND e.pubkey NOT IN (SELECT pubkey FROM caching_followed_pubkeys)] -- if follows_filter = 'non_follows'
|
||||
```
|
||||
|
||||
For the DELETE:
|
||||
```sql
|
||||
DELETE FROM events e
|
||||
WHERE e.id IN (
|
||||
SELECT e2.id FROM events e2
|
||||
WHERE 1=1
|
||||
[same filters as above]
|
||||
ORDER BY e2.created_at ASC -- delete oldest first
|
||||
LIMIT :max_events -- if max_events > 0
|
||||
)
|
||||
```
|
||||
|
||||
Using `id IN (subquery)` avoids issues with `ORDER BY` + `LIMIT` in DELETE directly, and also lets us count affected rows.
|
||||
|
||||
For the kind breakdown in preview:
|
||||
```sql
|
||||
SELECT e.kind,
|
||||
COUNT(*) AS count,
|
||||
COALESCE(SUM(pg_column_size(e.event_json)), 0) AS size_bytes
|
||||
FROM events e
|
||||
WHERE 1=1
|
||||
[same filters]
|
||||
GROUP BY e.kind
|
||||
ORDER BY count DESC
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 4. UI Design
|
||||
|
||||
### 4a. Navigation
|
||||
|
||||
Add a new nav item to the side menu in [`admin/index.php`](admin/index.php:51):
|
||||
```html
|
||||
<li><button class="nav-item" data-page="cleanup">Cleanup</button></li>
|
||||
```
|
||||
|
||||
### 4b. Page Layout
|
||||
|
||||
The cleanup page has two main sections:
|
||||
|
||||
#### Section 1: Saved Queries (top)
|
||||
- Table listing all saved queries with columns: Name, Filters summary, Last preview, Last executed, Actions
|
||||
- Actions per row: Preview, Execute, Delete
|
||||
- "New Query" button
|
||||
|
||||
#### Section 2: Query Builder / Results (bottom)
|
||||
When creating a new query or editing an existing one:
|
||||
|
||||
**Filter Controls:**
|
||||
- **Name** — text input
|
||||
- **Follows filter** — radio buttons: All / Follows only / Non-follows only
|
||||
- **Kinds** — multi-select or comma-separated text input (with helper showing common kinds: 0, 1, 3, 4, 5, 6, 7, 9734, 9735, 10002, etc.)
|
||||
- **Max age (days)** — number input (0 = no limit)
|
||||
- **Max events** — number input (0 = no limit)
|
||||
|
||||
**Action Buttons:**
|
||||
- **Preview** — runs the SELECT preview, shows results below
|
||||
- **Save Query** — saves the current filter configuration
|
||||
- **Execute Delete** — runs the actual DELETE (with confirmation dialog)
|
||||
|
||||
**Results Area:**
|
||||
- Match count with human-readable number
|
||||
- Estimated size freed (with human-readable format)
|
||||
- Kind breakdown table (kind, count, size)
|
||||
- SQL preview (collapsible)
|
||||
- Execution status (after actual delete)
|
||||
|
||||
### 4c. Confirmation Dialog
|
||||
|
||||
Before executing a DELETE, show a modal with:
|
||||
- Query name or "Ad-hoc query"
|
||||
- Number of events that will be deleted
|
||||
- Estimated space freed
|
||||
- "This action cannot be undone" warning
|
||||
- Confirm / Cancel buttons
|
||||
|
||||
---
|
||||
|
||||
## 5. Files to Create/Modify
|
||||
|
||||
### New Files:
|
||||
|
||||
| File | Purpose |
|
||||
|------|---------|
|
||||
| [`admin/api/cleanup.php`](admin/api/cleanup.php) | Preview + execute cleanup queries |
|
||||
| [`admin/api/cleanup_queries.php`](admin/api/cleanup_queries.php) | CRUD for saved cleanup queries |
|
||||
|
||||
### Modified Files:
|
||||
|
||||
| File | Changes |
|
||||
|------|---------|
|
||||
| [`admin/index.php`](admin/index.php:51) | Add "Cleanup" nav item + cleanup page HTML section |
|
||||
| [`admin/assets/app.js`](admin/assets/app.js:52) | Add `cleanup` to page map, loaders, and nav handlers |
|
||||
| [`src/pg_schema.h`](src/pg_schema.h) | Add `cleanup_saved_queries` table definition |
|
||||
|
||||
---
|
||||
|
||||
## 6. Implementation Order
|
||||
|
||||
1. **Add DB table** — Add `cleanup_saved_queries` to [`src/pg_schema.h`](src/pg_schema.h)
|
||||
2. **Create `admin/api/cleanup.php`** — Preview (SELECT) and Execute (DELETE) endpoints
|
||||
3. **Create `admin/api/cleanup_queries.php`** — CRUD for saved queries
|
||||
4. **Modify `admin/index.php`** — Add nav item + cleanup page HTML
|
||||
5. **Modify `admin/assets/app.js`** — Add cleanup page controller logic
|
||||
6. **Test** — Verify preview counts match actual deletes, verify saved query persistence
|
||||
|
||||
---
|
||||
|
||||
## 7. Mermaid Diagram: User Workflow
|
||||
|
||||
```mermaid
|
||||
flowchart TD
|
||||
A[Open Cleanup Page] --> B{Has saved queries?}
|
||||
B -->|Yes| C[Show saved queries list]
|
||||
B -->|No| D[Show empty state with New Query button]
|
||||
C --> E[Click New Query or Edit]
|
||||
D --> E
|
||||
E --> F[Configure filters: follows, kinds, age, limit]
|
||||
F --> G[Click Preview]
|
||||
G --> H[Run SELECT COUNT + size query]
|
||||
H --> I[Show preview results: count, size, kind breakdown]
|
||||
I --> J{User action}
|
||||
J -->|Save| K[Save named query to DB]
|
||||
J -->|Execute| L[Show confirmation dialog]
|
||||
L --> M[Run DELETE query]
|
||||
M --> N[Show execution results]
|
||||
K --> C
|
||||
J -->|Adjust filters| F
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 8. Mermaid Diagram: API Flow
|
||||
|
||||
```mermaid
|
||||
sequenceDiagram
|
||||
participant U as Browser UI
|
||||
participant C as cleanup.php
|
||||
participant Q as cleanup_queries.php
|
||||
participant DB as PostgreSQL
|
||||
|
||||
U->>Q: GET / list saved queries
|
||||
Q->>DB: SELECT FROM cleanup_saved_queries
|
||||
DB-->>Q: query list
|
||||
Q-->>U: JSON queries array
|
||||
|
||||
U->>C: GET / preview with filters
|
||||
C->>DB: SELECT COUNT + SUM pg_column_size
|
||||
C->>DB: SELECT kind breakdown
|
||||
DB-->>C: preview data
|
||||
C-->>U: JSON match_count + size
|
||||
|
||||
U->>Q: POST / save query
|
||||
Q->>DB: INSERT INTO cleanup_saved_queries
|
||||
DB-->>Q: ok
|
||||
Q-->>U: JSON saved query
|
||||
|
||||
U->>C: POST / execute dry_run=false
|
||||
C->>DB: DELETE ... WHERE id IN subquery
|
||||
DB-->>C: deleted count
|
||||
C-->>U: JSON deleted_count + freed_bytes
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 9. Edge Cases & Considerations
|
||||
|
||||
- **Large deletes**: Use `max_events` to cap deletes. For very large sets, execute in batches.
|
||||
- **Cascading deletes**: The `event_tags` table has `ON DELETE CASCADE` from events, so tag rows are cleaned up automatically. The `profiles` table has a trigger-based delete for kind-0 events.
|
||||
- **Concurrent access**: DELETE acquires row locks. For large deletes, consider batching (e.g., 10k at a time).
|
||||
- **Empty kinds array**: Means "all kinds" — no kind filter applied.
|
||||
- **Follows filter + no caching data**: If `caching_followed_pubkeys` is empty, `follows` returns 0 matches, `non_follows` returns all events.
|
||||
- **Size estimation**: Using `pg_column_size(event_json)` gives a good estimate. The `event_json` column stores the full event JSON, which dominates storage. Indexes and TOAST are not counted, but this is fine for a rough estimate.
|
||||
- **Saved query updates**: If a user saves with the same name, update the existing row (UPSERT on name).
|
||||
@@ -0,0 +1,71 @@
|
||||
# Plan: Prevent Direct `make` Usage — Always Use `build_static.sh`
|
||||
|
||||
## Problem
|
||||
|
||||
An agent ran `make` instead of `./build_static.sh`, which produced a dynamically-linked binary with SQLite backend instead of the static PostgreSQL binary. This caused the production relay to silently fall back to SQLite while the admin UI connected to PostgreSQL.
|
||||
|
||||
## Solution
|
||||
|
||||
Modify the Makefile so that the relay build targets refuse to run directly and instruct the user to use `build_static.sh` instead. The Makefile will still handle submodule builds (`nostr_core_lib`, `c_utils_lib`) and utility targets.
|
||||
|
||||
## Changes
|
||||
|
||||
### 1. [`Makefile`](../Makefile) — Guard the relay build targets
|
||||
|
||||
Replace the `all`, `$(TARGET)`, `x86`, and `arm64` targets with guards that print an error and exit:
|
||||
|
||||
```makefile
|
||||
# Default target — refuse direct build, instruct to use build_static.sh
|
||||
all:
|
||||
@echo "============================================"
|
||||
@echo " ERROR: Do not run 'make' directly!"
|
||||
@echo ""
|
||||
@echo " This project requires a static MUSL build"
|
||||
@echo " with PostgreSQL backend. Run:"
|
||||
@echo ""
|
||||
@echo " ./build_static.sh"
|
||||
@echo ""
|
||||
@echo " Or use the full build+restart script:"
|
||||
@echo ""
|
||||
@echo " ./make_and_restart_relay.sh"
|
||||
@echo ""
|
||||
@echo " The Makefile is only for submodule builds"
|
||||
@echo " (nostr_core_lib, c_utils_lib) and utility"
|
||||
@echo " targets (clean, install-deps, etc.)."
|
||||
@echo "============================================"
|
||||
@exit 1
|
||||
```
|
||||
|
||||
Keep the submodule build targets (`$(NOSTR_CORE_LIB)`, `$(C_UTILS_LIB)`) and utility targets (`clean`, `install-deps`, `install-arm64-deps`, `force-version`) as-is since they're harmless and useful.
|
||||
|
||||
### 2. [`AGENTS.md`](../AGENTS.md) — Reinforce the rule
|
||||
|
||||
Add a prominent section at the top of AGENTS.md:
|
||||
|
||||
```markdown
|
||||
## CRITICAL: Never Run `make` Directly
|
||||
|
||||
**NEVER run `make` to build the relay binary.** The Makefile will refuse and
|
||||
print an error. Always use:
|
||||
|
||||
- `./build_static.sh` — Build the static MUSL binary with PostgreSQL backend
|
||||
- `./make_and_restart_relay.sh` — Build, kill old relay, and start new one
|
||||
|
||||
The Makefile exists only for submodule compilation (nostr_core_lib, c_utils_lib)
|
||||
and utility targets (clean, install-deps). Running `make` directly produces a
|
||||
dynamically-linked binary that will silently fall back to SQLite storage while
|
||||
the admin UI connects to PostgreSQL — causing the admin page to show stale data.
|
||||
```
|
||||
|
||||
### 3. [`build_static.sh`](../build_static.sh) — Already updated
|
||||
|
||||
Already done in the previous round — removed `--db-backend` option, hardcoded PostgreSQL.
|
||||
|
||||
### 4. [`make_and_restart_relay.sh`](../make_and_restart_relay.sh) — Already updated
|
||||
|
||||
Already done in the previous round — removed `--db-backend` option, always calls `./build_static.sh`.
|
||||
|
||||
## Execution Order
|
||||
|
||||
1. Update [`Makefile`](../Makefile) — guard `all`, `$(TARGET)`, `x86`, `arm64` targets
|
||||
2. Update [`AGENTS.md`](../AGENTS.md) — add prominent warning section
|
||||
@@ -0,0 +1,113 @@
|
||||
# Plan: Remove SQLite Support — PostgreSQL Only
|
||||
|
||||
## Rationale
|
||||
|
||||
The project is called `c-relay-pg` and should only support PostgreSQL. The SQLite fallback caused a production issue where the relay was built without PostgreSQL support and silently fell back to SQLite, while the admin UI connected to PostgreSQL — resulting in the admin showing stale data.
|
||||
|
||||
## Files to Modify
|
||||
|
||||
### 1. [`Makefile`](../Makefile)
|
||||
|
||||
| Change | Detail |
|
||||
|--------|--------|
|
||||
| Remove `DB_BACKEND ?= sqlite` (line 8) | Hardcode PostgreSQL backend |
|
||||
| Remove `ifeq/else/endif` conditional (lines 17-23) | Always compile with `-DDB_BACKEND_POSTGRES -DHAVE_LIBPQ` and link `-lpq` |
|
||||
| Remove `src/db_ops_sqlite.c` from `DB_OPS_SRC` | Only compile `src/db_ops_postgres.c` |
|
||||
| Remove `-lsqlite3` from `LIBS` (line 6) | No longer needed |
|
||||
| Remove ARM64 sqlite3 dev references (lines 116, 119, 145, 191) | Replace with postgresql-dev equivalents |
|
||||
|
||||
### 2. [`Dockerfile.alpine-musl`](../Dockerfile.alpine-musl)
|
||||
|
||||
| Change | Detail |
|
||||
|--------|--------|
|
||||
| Remove `ARG DB_BACKEND=sqlite` (line 5) | Hardcode PostgreSQL |
|
||||
| Remove `ARG DB_BACKEND=sqlite` in builder stage (line 11) | Hardcode PostgreSQL |
|
||||
| Remove `sqlite-dev` and `sqlite-static` from apk add (lines 29-30) | Keep `postgresql-dev` |
|
||||
| Remove `if [ "$DB_BACKEND" = "postgres" ]` conditional (lines 118-126) | Always use PostgreSQL flags |
|
||||
| Remove `DB_LIBS=""` else branch (line 123-125) | Always link `-lpq -lpgcommon -lpgport` |
|
||||
| Remove `-lsqlite3` from link line (line 139) | No longer needed |
|
||||
|
||||
### 3. [`build_static.sh`](../build_static.sh)
|
||||
|
||||
| Change | Detail |
|
||||
|--------|--------|
|
||||
| Remove `DB_BACKEND="${DB_BACKEND:-postgres}"` (line 14) | Hardcode PostgreSQL |
|
||||
| Remove `--db-backend` argument parsing (lines 22-33) | No longer needed |
|
||||
| Remove `sqlite` validation (lines 42-45) | No longer needed |
|
||||
| Remove `echo "DB backend: $DB_BACKEND"` (line 59) | No longer needed |
|
||||
| Remove `--build-arg DB_BACKEND=$DB_BACKEND` (lines 158, 182) | No longer needed |
|
||||
| Update usage message (line 36) | Remove `--db-backend` reference |
|
||||
|
||||
### 4. [`make_and_restart_relay.sh`](../make_and_restart_relay.sh)
|
||||
|
||||
| Change | Detail |
|
||||
|--------|--------|
|
||||
| Remove `DB_BACKEND="postgres"` (line 18) | Hardcode PostgreSQL |
|
||||
| Remove `--db-backend` argument parsing (lines 138-150) | No longer needed |
|
||||
| Remove `sqlite` validation (lines 262-266) | No longer needed |
|
||||
| Remove `if [ "$DB_BACKEND" = "postgres" ]` conditional (line 276) | Always use PostgreSQL path |
|
||||
| Remove `--db-backend` from help text (line 365) | No longer needed |
|
||||
| Remove `DB_BACKEND` from build call (line 429) | `./build_static.sh` without args |
|
||||
|
||||
### 5. [`src/db_ops.c`](../src/db_ops.c)
|
||||
|
||||
| Change | Detail |
|
||||
|--------|--------|
|
||||
| Remove `#include "sqlite_db_ops.h"` (line 4) | No longer needed |
|
||||
| Remove `#ifdef DB_BACKEND_POSTGRES` / `#else` / `#endif` conditional | Always use PostgreSQL dispatch |
|
||||
| Remove the `#else` block (lines 207-376) that delegates to `sqlite_db_*` functions | Dead code |
|
||||
|
||||
### 6. [`src/main.c`](../src/main.c)
|
||||
|
||||
| Change | Detail |
|
||||
|--------|--------|
|
||||
| Remove SQLite-specific config references (lines 916-931) | Remove `sqlite_mmap_size` and `sqlite_cache_size_kb` PRAGMA setup |
|
||||
| Remove `sqlite3_open()` comment (line 791) | No longer relevant |
|
||||
|
||||
### 7. [`src/config.c`](../src/config.c)
|
||||
|
||||
| Change | Detail |
|
||||
|--------|--------|
|
||||
| Remove `sqlite_mmap_size` validation (lines 1118-1125) | PostgreSQL-only |
|
||||
| Remove `sqlite_cache_size_kb` validation (lines 1126-1130) | PostgreSQL-only |
|
||||
| Remove `sqlite_mmap_size` and `sqlite_cache_size_kb` from integer type list (lines 2178-2179) | PostgreSQL-only |
|
||||
| Remove `sqlite_mmap_size` and `sqlite_cache_size_kb` from restart-required list (lines 5341-5342) | PostgreSQL-only |
|
||||
|
||||
### 8. Source files to remove entirely
|
||||
|
||||
| File | Reason |
|
||||
|------|--------|
|
||||
| [`src/db_ops_sqlite.c`](../src/db_ops_sqlite.c) | Entire SQLite database implementation |
|
||||
| [`src/sqlite_db_ops.h`](../src/sqlite_db_ops.h) | SQLite header |
|
||||
|
||||
### 9. Test scripts — update sqlite3 CLI references
|
||||
|
||||
| File | Change |
|
||||
|------|--------|
|
||||
| [`tests/1_nip_test.sh`](../tests/1_nip_test.sh) (lines 444-470) | Replace `sqlite3` queries with `psql` equivalents |
|
||||
| [`tests/45_nip_test.sh`](../tests/45_nip_test.sh) (lines 428-452) | Replace `sqlite3` queries with `psql` equivalents |
|
||||
| [`tests/bulk_retrieval_test.sh`](../tests/bulk_retrieval_test.sh) (lines 43-45, 256-258) | Replace `sqlite3` queries with `psql` equivalents |
|
||||
| [`tests/subscription_cleanup_test.sh`](../tests/subscription_cleanup_test.sh) (lines 91-93, 262-271) | Replace `sqlite3` queries with `psql` equivalents |
|
||||
| [`tests/large_event_test.sh`](../tests/large_event_test.sh) (line 63) | Update comment |
|
||||
| [`tests/sql_injection_tests.sh`](../tests/sql_injection_tests.sh) (lines 111, 209-210) | Update SQLite-specific injection strings |
|
||||
|
||||
### 10. Example scripts — update sqlite3 references
|
||||
|
||||
| File | Change |
|
||||
|------|--------|
|
||||
| [`examples/deployment/simple-vps/deploy.sh`](../examples/deployment/simple-vps/deploy.sh) (lines 63, 68) | Replace `sqlite3` with `postgresql` in package lists |
|
||||
| [`examples/deployment/monitoring/monitor-relay.sh`](../examples/deployment/monitoring/monitor-relay.sh) (lines 249-251, 294-296) | Replace `sqlite3` queries with `psql` |
|
||||
| [`examples/deployment/backup/backup-relay.sh`](../examples/deployment/backup/backup-relay.sh) (lines 112-115, 187-189, 205-207) | Replace `sqlite3` backup with `pg_dump` |
|
||||
|
||||
## Execution Order
|
||||
|
||||
1. Remove source files: `src/db_ops_sqlite.c`, `src/sqlite_db_ops.h`
|
||||
2. Update `src/db_ops.c` — remove SQLite dispatch, always use PostgreSQL
|
||||
3. Update `src/main.c` — remove SQLite PRAGMA config
|
||||
4. Update `src/config.c` — remove SQLite config keys
|
||||
5. Update `Makefile` — hardcode PostgreSQL backend
|
||||
6. Update `Dockerfile.alpine-musl` — hardcode PostgreSQL backend
|
||||
7. Update `build_static.sh` — remove `--db-backend` option
|
||||
8. Update `make_and_restart_relay.sh` — remove `--db-backend` option
|
||||
9. Update test scripts — replace `sqlite3` with `psql`
|
||||
10. Update example scripts — replace `sqlite3` with `psql`/`pg_dump`
|
||||
@@ -0,0 +1,70 @@
|
||||
# Plan: Fix Missing Statistics Metrics
|
||||
|
||||
## Root Causes
|
||||
|
||||
### 1. WebSocket Connections = 0
|
||||
The stats API at [`admin/api/stats.php:33`](admin/api/stats.php:33) queries:
|
||||
```php
|
||||
$ws_connections = intval($pdo->query("SELECT count(*) FROM pg_stat_activity
|
||||
WHERE state = 'active' AND pid != pg_backend_pid()")->fetchColumn());
|
||||
```
|
||||
This is **wrong** — WebSocket connections are tracked in-memory by the relay via `g_connection_count` in [`src/websockets.c:139`](src/websockets.c:139), not in `pg_stat_activity`. The PHP code is counting PostgreSQL backend processes, not WebSocket clients.
|
||||
|
||||
**Fix:** Query the `subscriptions` table for distinct `wsi_pointer` values where `event_type = 'created'` and no corresponding `'closed'`/`'disconnected'` event exists. Or simpler: count distinct `wsi_pointer` values from the most recent `'created'` entries.
|
||||
|
||||
### 2. Active Subscriptions = 0
|
||||
The stats API at [`admin/api/stats.php:39`](admin/api/stats.php:39) queries:
|
||||
```php
|
||||
$active_subscriptions = intval($pdo->query("SELECT count(*) FROM subscriptions
|
||||
WHERE active = true")->fetchColumn());
|
||||
```
|
||||
The `subscriptions` table has **no `active` column** (see [`src/pg_schema.sql:207`](src/pg_schema.sql:207)). It has `event_type` with values 'created', 'closed', 'expired', 'disconnected'.
|
||||
|
||||
**Fix:** Count subscriptions where `event_type = 'created'` and no matching `'closed'`/`'disconnected'` record exists for the same `(subscription_id, wsi_pointer)`.
|
||||
|
||||
### 3. Memory Usage = '-'
|
||||
The code at [`admin/api/stats.php:46-51`](admin/api/stats.php:46) reads `/proc/meminfo` — this may fail if the PHP-FPM process is running under a restricted user (e.g., `www-data` with `ProtectProc=invisible` or similar systemd sandboxing).
|
||||
|
||||
**Fix:** Use `file_get_contents('/proc/meminfo')` with proper error handling (already there), or fall back to `sys_getloadavg()` and `shell_exec('free -b')` as alternatives.
|
||||
|
||||
### 4. Oldest/Newest Event = '-'
|
||||
The query at [`admin/api/stats.php:63-64`](admin/api/stats.php:63) uses `to_timestamp(MIN(created_at))` — this should work on 3.3M events but may be slow. Could be timing out.
|
||||
|
||||
**Fix:** Use `SELECT MIN(created_at), MAX(created_at) FROM events` in a single query, then format in PHP. Add a query timeout safeguard.
|
||||
|
||||
## Changes Required
|
||||
|
||||
### File: `admin/api/stats.php`
|
||||
|
||||
| Line | Current | Fix |
|
||||
|------|---------|-----|
|
||||
| 33 | `pg_stat_activity` query | Count distinct active WebSocket connections from `subscriptions` table |
|
||||
| 39 | `WHERE active = true` | Count active subscriptions using `event_type` logic |
|
||||
| 46-51 | `/proc/meminfo` | Add fallback using `shell_exec('free -b')` |
|
||||
| 63-64 | Two separate `to_timestamp` queries | Single `SELECT MIN(created_at), MAX(created_at)` query |
|
||||
|
||||
### SQL for Active Connections
|
||||
```sql
|
||||
SELECT COUNT(DISTINCT wsi_pointer) FROM subscriptions
|
||||
WHERE event_type = 'created'
|
||||
AND wsi_pointer NOT IN (
|
||||
SELECT wsi_pointer FROM subscriptions
|
||||
WHERE event_type IN ('closed', 'disconnected', 'expired')
|
||||
)
|
||||
```
|
||||
|
||||
### SQL for Active Subscriptions
|
||||
```sql
|
||||
SELECT COUNT(*) FROM (
|
||||
SELECT subscription_id, wsi_pointer FROM subscriptions
|
||||
WHERE event_type = 'created'
|
||||
EXCEPT
|
||||
SELECT subscription_id, wsi_pointer FROM subscriptions
|
||||
WHERE event_type IN ('closed', 'disconnected', 'expired')
|
||||
) AS active_subs
|
||||
```
|
||||
|
||||
### SQL for Oldest/Newest
|
||||
```sql
|
||||
SELECT MIN(created_at) AS oldest, MAX(created_at) AS newest FROM events
|
||||
```
|
||||
@@ -0,0 +1,189 @@
|
||||
# Plan: Publish Kind 1 Status Events to External Relays
|
||||
|
||||
## Config Reuse
|
||||
|
||||
The config key **`kind_1_status_posts_hours`** already exists in the shared `config` table (used by the main relay at [`src/api.c:975`](src/api.c:975)). The caching service will read the **same** key — no new config needed. Setting it in the admin panel controls both:
|
||||
- Main relay: generates and stores the kind 1 event locally
|
||||
- Caching service: publishes it to external upstream relays
|
||||
|
||||
## Phase 1: PHP Report Endpoint (`admin/api/kind_1_report.php`)
|
||||
|
||||
A new PHP endpoint at `/relay/admin/api/kind_1_report.php` that returns a **markdown-formatted** relay status report. This serves as:
|
||||
- The content template for the kind 1 event
|
||||
- A preview page you can visit in the browser to see what will be published
|
||||
|
||||
### Report Structure (Markdown)
|
||||
|
||||
```
|
||||
# Relay Name v0.x.x
|
||||
|
||||
## Event Rate (Last Hour)
|
||||
[ASCII chart — same as the 1H chart from chart.php]
|
||||
|
||||
## Database Overview
|
||||
- Total Events: X
|
||||
- Database Size: X MB
|
||||
- Oldest Event: date
|
||||
- Newest Event: date
|
||||
|
||||
## Event Kinds (Top 10)
|
||||
| Kind | Count | % |
|
||||
|------|-------|---|
|
||||
| 1 | X | X% |
|
||||
| 7 | X | X% |
|
||||
| ... | ... | ... |
|
||||
|
||||
## Time-Based Statistics
|
||||
| Period | Events |
|
||||
|----------|--------|
|
||||
| 24 Hours | X |
|
||||
| 7 Days | X |
|
||||
| 30 Days | X |
|
||||
|
||||
## Top Pubkeys
|
||||
| # | Name | Pubkey | Events | % |
|
||||
|---|------|--------|--------|---|
|
||||
| 1 | ... | ... | X | X%|
|
||||
| 2 | ... | ... | X | X%|
|
||||
```
|
||||
|
||||
### Implementation
|
||||
|
||||
The PHP file will:
|
||||
1. Query PostgreSQL for all stats (same queries as [`admin/api/stats.php`](admin/api/stats.php))
|
||||
2. Call the existing chart endpoint to get the 1H ASCII chart
|
||||
3. Format everything as markdown
|
||||
4. Return `Content-Type: text/plain; charset=utf-8`
|
||||
|
||||
### Nginx Config
|
||||
|
||||
Add a location block so the endpoint is accessible:
|
||||
```nginx
|
||||
location ^~ /relay/admin/api/kind_1_report.php {
|
||||
alias /opt/c-relay-pg/admin/api/kind_1_report.php;
|
||||
fastcgi_pass unix:/run/php/php8.3-fpm.sock;
|
||||
fastcgi_index kind_1_report.php;
|
||||
include fastcgi_params;
|
||||
fastcgi_param SCRIPT_FILENAME $request_filename;
|
||||
}
|
||||
```
|
||||
|
||||
## Phase 2: Caching Service Publishing
|
||||
|
||||
### 2a. `pg_inbox_get_relay_private_key()` (new function in `pg_inbox.c`)
|
||||
|
||||
Reads the relay's private key from the `relay_seckey` table. Returns a malloc'd hex string.
|
||||
|
||||
### 2b. Status publish tick (new function in `main.c`)
|
||||
|
||||
A periodic task in the main loop that:
|
||||
- Reads `kind_1_status_posts_hours` from the config table
|
||||
- If enabled and time to publish:
|
||||
1. Fetches the relay private key from `relay_seckey`
|
||||
2. Fetches the report text by calling the PHP endpoint via HTTP (or generates it directly via SQL)
|
||||
3. Creates and signs a kind 1 event using `nostr_create_and_sign_event()`
|
||||
4. Publishes to all connected upstream relays via `nostr_relay_pool_publish_async()`
|
||||
|
||||
## Files to Modify
|
||||
|
||||
| File | Change |
|
||||
|------|--------|
|
||||
| `admin/api/kind_1_report.php` | **New** — PHP endpoint returning markdown report |
|
||||
| `caching/src/pg_inbox.h` | Add `pg_inbox_get_relay_private_key()` declaration |
|
||||
| `caching/src/pg_inbox.c` | Implement `pg_inbox_get_relay_private_key()` |
|
||||
| `caching/src/main.c` | Add periodic status publish tick |
|
||||
| nginx config | Add location for kind_1_report.php |
|
||||
|
||||
## Current State
|
||||
|
||||
The main relay (`c_relay_pg`) already has a [`generate_and_post_status_event()`](src/api.c:973) function that:
|
||||
1. Generates relay statistics text via [`generate_stats_text()`](src/api.c:2007)
|
||||
2. Signs it as a **kind 1** event with the relay's private key (from [`relay_seckey`](src/db_ops_postgres.c:1611) table)
|
||||
3. Stores it locally and broadcasts to connected clients
|
||||
|
||||
But it **never publishes to external relays** — the main relay has no WebSocket client capability.
|
||||
|
||||
The caching service (`caching_relay`) has a full WebSocket relay pool (`nostr_relay_pool_t`) that can connect to external relays and publish events. It already connects to 26 upstream relays.
|
||||
|
||||
## Architecture
|
||||
|
||||
```
|
||||
┌─────────────────────┐ ┌──────────────────────────────┐
|
||||
│ PHP Stats Endpoint │────▶│ PostgreSQL (stats data) │
|
||||
│ /relay/api/stats/ │ │ │
|
||||
└─────────────────────┘ └──────────┬───────────────────┘
|
||||
│ reads every N hours
|
||||
▼
|
||||
┌──────────────────────────────────────────────────────────┐
|
||||
│ caching_relay (main loop) │
|
||||
│ │
|
||||
│ 1. Read relay private key from relay_seckey table │
|
||||
│ 2. Generate stats text (SQL queries via pg_inbox) │
|
||||
│ 3. Create + sign kind 1 event │
|
||||
│ 4. Publish to ALL connected upstream relays │
|
||||
│ (via nostr_relay_pool_publish_async) │
|
||||
└──────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
## Changes Required
|
||||
|
||||
### 1. PHP Stats Text Endpoint (new file: `admin/api/stats_text.php`)
|
||||
|
||||
A public (or admin-authenticated) PHP endpoint that queries PostgreSQL directly and returns the stats text. This is useful for:
|
||||
- Manual preview of what the relay publishes
|
||||
- The caching service could fetch it via HTTP (but we'll use direct SQL instead)
|
||||
|
||||
### 2. Caching Service: `pg_inbox_generate_stats_text()` (new function in `pg_inbox.c`)
|
||||
|
||||
A C function that queries PostgreSQL to generate the same stats text that the main relay's `generate_stats_text()` produces. It queries:
|
||||
- `SELECT COUNT(*) FROM events` — total events
|
||||
- `SELECT COUNT(*) FROM events WHERE created_at > ...` — time-based stats
|
||||
- `SELECT kind, COUNT(*) FROM events GROUP BY kind` — kind distribution
|
||||
- `SELECT pubkey, COUNT(*) FROM events GROUP BY pubkey ORDER BY COUNT(*) DESC LIMIT 10` — top pubkeys
|
||||
- `SELECT pg_database_size('crelay')` — database size
|
||||
|
||||
### 3. Caching Service: `pg_inbox_get_relay_private_key()` (new function in `pg_inbox.c`)
|
||||
|
||||
Reads the relay's private key from the `relay_seckey` table so the caching service can sign events as the relay.
|
||||
|
||||
### 4. Caching Service: Status publish tick (new function in `main.c`)
|
||||
|
||||
A periodic task in the main loop that:
|
||||
- Checks if it's time to publish (configurable interval, e.g., every 6 hours)
|
||||
- Reads the relay private key from PostgreSQL
|
||||
- Generates stats text via SQL queries
|
||||
- Creates and signs a kind 1 event using `nostr_create_and_sign_event()`
|
||||
- Publishes to all connected upstream relays via `nostr_relay_pool_publish_async()`
|
||||
|
||||
### 5. Config: `status_publish_hours` (new config key)
|
||||
|
||||
Controls how often the status event is published. Stored in the `config` table. Default 0 = disabled.
|
||||
|
||||
## Files to Modify
|
||||
|
||||
| File | Change |
|
||||
|------|--------|
|
||||
| `admin/api/stats_text.php` | **New** — PHP endpoint returning stats text |
|
||||
| `caching/src/pg_inbox.h` | Add declarations for `pg_inbox_generate_stats_text()` and `pg_inbox_get_relay_private_key()` |
|
||||
| `caching/src/pg_inbox.c` | Implement both functions |
|
||||
| `caching/src/main.c` | Add periodic status publish tick in main loop |
|
||||
| `caching/src/pg_config.c` | Add `status_publish_hours` to config loading |
|
||||
|
||||
## Data Flow
|
||||
|
||||
```
|
||||
Every N hours (config: status_publish_hours):
|
||||
1. main.c checks if time to publish
|
||||
2. Calls pg_inbox_generate_stats_text() → returns malloc'd string
|
||||
3. Calls pg_inbox_get_relay_private_key() → returns hex key
|
||||
4. Creates cJSON event: kind=1, content=stats_text, tags=[]
|
||||
5. Signs with nostr_create_and_sign_event(1, content, tags, privkey, now)
|
||||
6. Publishes via nostr_relay_pool_publish_async() to all upstream relays
|
||||
7. Free resources
|
||||
```
|
||||
|
||||
## Dependencies
|
||||
|
||||
- The caching service already links `nostr_core_lib` which provides `nostr_create_and_sign_event()` and `nostr_relay_pool_publish_async()`
|
||||
- The caching service already has a PostgreSQL connection via `pg_inbox`
|
||||
- No new libraries needed
|
||||
@@ -977,10 +977,32 @@ int generate_and_post_status_event(void) {
|
||||
return 0; // Feature disabled
|
||||
}
|
||||
|
||||
// Generate statistics text content using existing function
|
||||
char* stats_text = generate_stats_text();
|
||||
if (!stats_text) {
|
||||
DEBUG_ERROR("Failed to generate statistics text for status post");
|
||||
// Generate report content by running the PHP kind_1_report.php script.
|
||||
// This produces a markdown-formatted relay status report.
|
||||
char* stats_text = NULL;
|
||||
FILE *fp = popen("php -r 'require \"/opt/c-relay-pg/admin/api/kind_1_report.php\";' 2>/dev/null", "r");
|
||||
if (fp) {
|
||||
size_t total = 0, cap = 16384;
|
||||
stats_text = malloc(cap);
|
||||
if (stats_text) {
|
||||
int n;
|
||||
while ((n = fread(stats_text + total, 1, cap - total - 1, fp)) > 0) {
|
||||
total += n;
|
||||
if (total >= cap - 1) {
|
||||
cap *= 2;
|
||||
char *tmp = realloc(stats_text, cap);
|
||||
if (!tmp) { free(stats_text); stats_text = NULL; break; }
|
||||
stats_text = tmp;
|
||||
}
|
||||
}
|
||||
if (stats_text) stats_text[total] = '\0';
|
||||
}
|
||||
pclose(fp);
|
||||
}
|
||||
|
||||
if (!stats_text || strlen(stats_text) == 0) {
|
||||
DEBUG_ERROR("Failed to generate report via PHP for status post");
|
||||
free(stats_text);
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -1006,7 +1028,7 @@ int generate_and_post_status_event(void) {
|
||||
// Create and sign the kind 1 event
|
||||
cJSON* signed_event = nostr_create_and_sign_event(
|
||||
1, // kind 1 = text note
|
||||
stats_text, // content = statistics
|
||||
stats_text, // content = markdown report
|
||||
tags, // empty tags
|
||||
relay_privkey_bytes, // relay's private key
|
||||
time(NULL) // current timestamp
|
||||
|
||||
+1
-21
@@ -1114,22 +1114,6 @@ static int validate_config_field(const char* key, const char* value, char* error
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
// SQLite performance tuning
|
||||
if (strcmp(key, "sqlite_mmap_size") == 0) {
|
||||
if (!is_valid_positive_integer(value) && strcmp(value, "0") != 0) {
|
||||
snprintf(error_msg, error_size, "invalid sqlite_mmap_size '%s' (must be non-negative integer bytes)", value);
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
if (strcmp(key, "sqlite_cache_size_kb") == 0) {
|
||||
if (!is_valid_positive_integer(value)) {
|
||||
snprintf(error_msg, error_size, "invalid sqlite_cache_size_kb '%s' (must be positive integer KB)", value);
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Boolean fields
|
||||
if (strcmp(key, "auth_enabled") == 0 ||
|
||||
@@ -2174,9 +2158,7 @@ int populate_default_config_values(void) {
|
||||
strcmp(key, "default_limit") == 0 ||
|
||||
strcmp(key, "max_limit") == 0 ||
|
||||
strcmp(key, "nip42_challenge_expiration") == 0 ||
|
||||
strcmp(key, "nip40_expiration_grace_period") == 0 ||
|
||||
strcmp(key, "sqlite_mmap_size") == 0 ||
|
||||
strcmp(key, "sqlite_cache_size_kb") == 0) {
|
||||
strcmp(key, "nip40_expiration_grace_period") == 0) {
|
||||
data_type = "integer";
|
||||
} else if (strcmp(key, "auth_enabled") == 0 ||
|
||||
strcmp(key, "nip40_expiration_enabled") == 0 ||
|
||||
@@ -5338,8 +5320,6 @@ int populate_all_config_values_atomic(const char* admin_pubkey, const char* rela
|
||||
strcmp(key, "max_limit") == 0 ||
|
||||
strcmp(key, "nip42_challenge_expiration") == 0 ||
|
||||
strcmp(key, "nip40_expiration_grace_period") == 0 ||
|
||||
strcmp(key, "sqlite_mmap_size") == 0 ||
|
||||
strcmp(key, "sqlite_cache_size_kb") == 0 ||
|
||||
strcmp(key, "caching_config_generation") == 0 ||
|
||||
strcmp(key, "caching_live_resubscribe_seconds") == 0 ||
|
||||
strcmp(key, "caching_backfill_page_size") == 0 ||
|
||||
|
||||
-226
@@ -1,11 +1,8 @@
|
||||
#define _GNU_SOURCE
|
||||
|
||||
#include "db_ops.h"
|
||||
#include "sqlite_db_ops.h"
|
||||
#include "db_ops_postgres.h"
|
||||
|
||||
#ifdef DB_BACKEND_POSTGRES
|
||||
|
||||
int db_init(const char* connection_string) { return postgres_db_init(connection_string); }
|
||||
void db_close(void) { postgres_db_close(); }
|
||||
int db_is_available(void) { return postgres_db_is_available(); }
|
||||
@@ -202,226 +199,3 @@ cJSON* db_get_profile(const char* pubkey) {
|
||||
cJSON* db_get_profiles(const char** pubkeys, int count) {
|
||||
return postgres_db_get_profiles(pubkeys, count);
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
int db_init(const char* connection_string) { return sqlite_db_init(connection_string); }
|
||||
void db_close(void) { sqlite_db_close(); }
|
||||
int db_is_available(void) { return sqlite_db_is_available(); }
|
||||
const char* db_last_error(void) { return sqlite_db_last_error(); }
|
||||
const char* db_get_database_path(void) { return sqlite_db_get_database_path(); }
|
||||
|
||||
int db_set_thread_connection(void* connection) { return sqlite_db_set_thread_connection(connection); }
|
||||
void db_clear_thread_connection(void) { sqlite_db_clear_thread_connection(); }
|
||||
|
||||
int db_open_worker_connection(const char* db_path, void** out_connection) {
|
||||
return sqlite_db_open_worker_connection(db_path, out_connection);
|
||||
}
|
||||
void db_close_worker_connection(void* connection) { sqlite_db_close_worker_connection(connection); }
|
||||
|
||||
int db_worker_listen(void* connection, const char* channel) {
|
||||
return sqlite_db_worker_listen(connection, channel);
|
||||
}
|
||||
int db_worker_poll_notify(void* connection, int timeout_ms) {
|
||||
return sqlite_db_worker_poll_notify(connection, timeout_ms);
|
||||
}
|
||||
int db_worker_poll_notify_with_payload(void* connection, int timeout_ms,
|
||||
char** out_channel, char** out_payload) {
|
||||
(void)connection; (void)timeout_ms;
|
||||
if (out_channel) *out_channel = NULL;
|
||||
if (out_payload) *out_payload = NULL;
|
||||
return -1; /* SQLite has no LISTEN/NOTIFY */
|
||||
}
|
||||
|
||||
int db_prepare(const char* sql, db_stmt_t** out_stmt) {
|
||||
return sqlite_db_prepare(sql, (sqlite_db_stmt_t**)out_stmt);
|
||||
}
|
||||
int db_bind_text_param(db_stmt_t* stmt, int index, const char* value) {
|
||||
return sqlite_db_bind_text_param((sqlite_db_stmt_t*)stmt, index, value);
|
||||
}
|
||||
int db_bind_int_param(db_stmt_t* stmt, int index, int value) {
|
||||
return sqlite_db_bind_int_param((sqlite_db_stmt_t*)stmt, index, value);
|
||||
}
|
||||
int db_bind_int64_param(db_stmt_t* stmt, int index, long long value) {
|
||||
return sqlite_db_bind_int64_param((sqlite_db_stmt_t*)stmt, index, value);
|
||||
}
|
||||
int db_step_stmt(db_stmt_t* stmt) { return sqlite_db_step_stmt((sqlite_db_stmt_t*)stmt); }
|
||||
int db_reset_stmt(db_stmt_t* stmt) { return sqlite_db_reset_stmt((sqlite_db_stmt_t*)stmt); }
|
||||
const char* db_column_text_value(db_stmt_t* stmt, int col) {
|
||||
return sqlite_db_column_text_value((sqlite_db_stmt_t*)stmt, col);
|
||||
}
|
||||
int db_column_int_value(db_stmt_t* stmt, int col) {
|
||||
return sqlite_db_column_int_value((sqlite_db_stmt_t*)stmt, col);
|
||||
}
|
||||
long long db_column_int64_value(db_stmt_t* stmt, int col) {
|
||||
return sqlite_db_column_int64_value((sqlite_db_stmt_t*)stmt, col);
|
||||
}
|
||||
double db_column_double_value(db_stmt_t* stmt, int col) {
|
||||
return sqlite_db_column_double_value((sqlite_db_stmt_t*)stmt, col);
|
||||
}
|
||||
void db_finalize_stmt(db_stmt_t* stmt) { sqlite_db_finalize_stmt((sqlite_db_stmt_t*)stmt); }
|
||||
|
||||
int db_log_subscription_created(const char* sub_id, const char* wsi_ptr,
|
||||
const char* client_ip, const char* filter_json) {
|
||||
return sqlite_db_log_subscription_created(sub_id, wsi_ptr, client_ip, filter_json);
|
||||
}
|
||||
int db_log_subscription_closed(const char* sub_id, const char* client_ip) {
|
||||
return sqlite_db_log_subscription_closed(sub_id, client_ip);
|
||||
}
|
||||
int db_log_subscription_disconnected(const char* client_ip) {
|
||||
return sqlite_db_log_subscription_disconnected(client_ip);
|
||||
}
|
||||
int db_update_subscription_events_sent(const char* sub_id, int events_sent) {
|
||||
return sqlite_db_update_subscription_events_sent(sub_id, events_sent);
|
||||
}
|
||||
int db_cleanup_orphaned_subscriptions(void) { return sqlite_db_cleanup_orphaned_subscriptions(); }
|
||||
|
||||
int db_get_event_pubkey(const char* event_id, char* pubkey_out, size_t pubkey_out_size) {
|
||||
return sqlite_db_get_event_pubkey(event_id, pubkey_out, pubkey_out_size);
|
||||
}
|
||||
int db_delete_event_by_id(const char* event_id, const char* requester_pubkey) {
|
||||
return sqlite_db_delete_event_by_id(event_id, requester_pubkey);
|
||||
}
|
||||
int db_delete_events_by_address(const char* pubkey, int kind, const char* d_tag, long before_timestamp) {
|
||||
return sqlite_db_delete_events_by_address(pubkey, kind, d_tag, before_timestamp);
|
||||
}
|
||||
|
||||
int db_is_pubkey_blacklisted(const char* pubkey) { return sqlite_db_is_pubkey_blacklisted(pubkey); }
|
||||
int db_is_hash_blacklisted(const char* resource_hash) { return sqlite_db_is_hash_blacklisted(resource_hash); }
|
||||
int db_is_pubkey_whitelisted(const char* pubkey) { return sqlite_db_is_pubkey_whitelisted(pubkey); }
|
||||
int db_count_active_whitelist_rules(void) { return sqlite_db_count_active_whitelist_rules(); }
|
||||
|
||||
int db_count_with_sql(const char* sql, const char** bind_params, int bind_param_count, int* out_count) {
|
||||
return sqlite_db_count_with_sql(sql, bind_params, bind_param_count, out_count);
|
||||
}
|
||||
char* db_execute_readonly_query_json(const char* query, const char* request_id,
|
||||
char* error_message, size_t error_size,
|
||||
int max_rows, int timeout_ms) {
|
||||
return sqlite_db_execute_readonly_query_json(query, request_id, error_message, error_size,
|
||||
max_rows, timeout_ms);
|
||||
}
|
||||
|
||||
int db_get_total_event_count_ll(long long* out_count) { return sqlite_db_get_total_event_count_ll(out_count); }
|
||||
int db_get_event_count_since(time_t cutoff, long long* out_count) {
|
||||
return sqlite_db_get_event_count_since(cutoff, out_count);
|
||||
}
|
||||
int db_get_storage_size_bytes(long long* out_size) {
|
||||
return sqlite_db_get_storage_size_bytes(out_size);
|
||||
}
|
||||
cJSON* db_get_event_kind_distribution_rows(long long* out_total_events) {
|
||||
return sqlite_db_get_event_kind_distribution_rows(out_total_events);
|
||||
}
|
||||
cJSON* db_get_top_pubkeys_rows(int limit) { return sqlite_db_get_top_pubkeys_rows(limit); }
|
||||
cJSON* db_get_subscription_details_rows(void) { return sqlite_db_get_subscription_details_rows(); }
|
||||
|
||||
cJSON* db_get_all_config_rows(void) { return sqlite_db_get_all_config_rows(); }
|
||||
char* db_get_config_value_dup(const char* key) { return sqlite_db_get_config_value_dup(key); }
|
||||
int db_set_config_value_full(const char* key, const char* value, const char* data_type,
|
||||
const char* description, const char* category, int requires_restart) {
|
||||
return sqlite_db_set_config_value_full(key, value, data_type, description, category, requires_restart);
|
||||
}
|
||||
int db_update_config_value_only(const char* key, const char* value) {
|
||||
return sqlite_db_update_config_value_only(key, value);
|
||||
}
|
||||
int db_upsert_config_value(const char* key, const char* value, const char* data_type) {
|
||||
return sqlite_db_upsert_config_value(key, value, data_type);
|
||||
}
|
||||
int db_store_relay_private_key_hex(const char* relay_privkey_hex) {
|
||||
return sqlite_db_store_relay_private_key_hex(relay_privkey_hex);
|
||||
}
|
||||
char* db_get_relay_private_key_hex_dup(void) { return sqlite_db_get_relay_private_key_hex_dup(); }
|
||||
int db_store_config_event(const cJSON* event) { return sqlite_db_store_config_event(event); }
|
||||
|
||||
int db_insert_event_with_json(const char* id, const char* pubkey, long long created_at,
|
||||
int kind, const char* event_type, const char* content,
|
||||
const char* sig, const char* tags_json, const char* event_json,
|
||||
int* out_step_rc, int* out_extended_errcode) {
|
||||
return sqlite_db_insert_event_with_json(id, pubkey, created_at, kind, event_type, content,
|
||||
sig, tags_json, event_json, out_step_rc, out_extended_errcode);
|
||||
}
|
||||
int db_get_event_time_bounds(long long* out_min_created_at, long long* out_max_created_at) {
|
||||
return sqlite_db_get_event_time_bounds(out_min_created_at, out_max_created_at);
|
||||
}
|
||||
int db_event_id_exists(const char* event_id, int* out_exists) {
|
||||
return sqlite_db_event_id_exists(event_id, out_exists);
|
||||
}
|
||||
cJSON* db_retrieve_event_by_id(const char* event_id) { return sqlite_db_retrieve_event_by_id(event_id); }
|
||||
char* db_get_latest_event_pubkey_for_kind_dup(int kind) {
|
||||
return sqlite_db_get_latest_event_pubkey_for_kind_dup(kind);
|
||||
}
|
||||
|
||||
int db_get_config_row_count(int* out_count) { return sqlite_db_get_config_row_count(out_count); }
|
||||
|
||||
int db_store_event_tags_cjson(const char* event_id, const cJSON* tags) {
|
||||
return sqlite_db_store_event_tags_cjson(event_id, tags);
|
||||
}
|
||||
int db_populate_event_tags_from_existing(void) { return sqlite_db_populate_event_tags_from_existing(); }
|
||||
|
||||
int db_add_auth_rule(const char* rule_type, const char* pattern_type, const char* pattern_value) {
|
||||
return sqlite_db_add_auth_rule(rule_type, pattern_type, pattern_value);
|
||||
}
|
||||
int db_remove_auth_rule(const char* rule_type, const char* pattern_type, const char* pattern_value) {
|
||||
return sqlite_db_remove_auth_rule(rule_type, pattern_type, pattern_value);
|
||||
}
|
||||
int db_delete_wot_whitelist_rules(void) { return sqlite_db_delete_wot_whitelist_rules(); }
|
||||
int db_count_wot_whitelist_rules(void) { return sqlite_db_count_wot_whitelist_rules(); }
|
||||
|
||||
int db_table_exists(const char* table_name, int* out_exists) {
|
||||
return sqlite_db_table_exists(table_name, out_exists);
|
||||
}
|
||||
char* db_get_schema_version_dup(void) { return sqlite_db_get_schema_version_dup(); }
|
||||
int db_exec_sql(const char* sql) { return sqlite_db_exec_sql(sql); }
|
||||
int db_wal_checkpoint_passive(void) { return sqlite_db_wal_checkpoint_passive(); }
|
||||
int db_wal_checkpoint_truncate(void) { return sqlite_db_wal_checkpoint_truncate(); }
|
||||
|
||||
// Caching relay inbox helpers are PostgreSQL-only. The SQLite backend has no
|
||||
// caching_event_inbox table, so the dispatch path returns errors/no-ops here
|
||||
// rather than delegating to sqlite_db_ops stubs.
|
||||
cJSON* db_caching_inbox_dequeue_batch(int batch_size, int* out_count) {
|
||||
if (out_count) *out_count = 0;
|
||||
(void)batch_size;
|
||||
return NULL;
|
||||
}
|
||||
int db_caching_inbox_pending_counts(int* out_live_count, int* out_backfill_count) {
|
||||
if (out_live_count) *out_live_count = 0;
|
||||
if (out_backfill_count) *out_backfill_count = 0;
|
||||
return DB_ERROR;
|
||||
}
|
||||
int db_caching_inbox_oldest_age(int* out_oldest_age_seconds) {
|
||||
if (out_oldest_age_seconds) *out_oldest_age_seconds = 0;
|
||||
return DB_ERROR;
|
||||
}
|
||||
int db_caching_backfill_author_counts(int* out_complete, int* out_total) {
|
||||
if (out_complete) *out_complete = 0;
|
||||
if (out_total) *out_total = 0;
|
||||
return DB_ERROR;
|
||||
}
|
||||
int db_caching_inbox_insert(const char* event_id, const char* event_json,
|
||||
const char* source_relay, const char* source_class,
|
||||
int priority) {
|
||||
(void)event_id; (void)event_json; (void)source_relay; (void)source_class; (void)priority;
|
||||
return DB_ERROR;
|
||||
}
|
||||
|
||||
cJSON* db_get_profile_metadata(const char* pubkey) {
|
||||
/* SQLite backend: kind-0 metadata not supported in this context.
|
||||
* The caching follows feature is PostgreSQL-only. */
|
||||
(void)pubkey;
|
||||
return NULL;
|
||||
}
|
||||
cJSON* db_get_outbox_relays(const char* pubkey) {
|
||||
(void)pubkey;
|
||||
return NULL;
|
||||
}
|
||||
cJSON* db_get_profile(const char* pubkey) {
|
||||
/* SQLite backend: profiles cache table is PostgreSQL-only. */
|
||||
(void)pubkey;
|
||||
return NULL;
|
||||
}
|
||||
cJSON* db_get_profiles(const char** pubkeys, int count) {
|
||||
(void)pubkeys;
|
||||
(void)count;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
-1428
File diff suppressed because it is too large
Load Diff
+4
-37
@@ -788,7 +788,7 @@ int init_database(const char* database_path_override) {
|
||||
if (db_get_config_row_count(&row_count) == 0) {
|
||||
DEBUG_LOG("Config table row count immediately after db_init(): %d", row_count);
|
||||
} else {
|
||||
DEBUG_LOG("Config table count unavailable immediately after sqlite3_open() (table may not exist yet)");
|
||||
DEBUG_LOG("Config table count unavailable immediately after db_init() (table may not exist yet)");
|
||||
}
|
||||
}
|
||||
// DEBUG_GUARD_END
|
||||
@@ -908,36 +908,11 @@ int init_database(const char* database_path_override) {
|
||||
DEBUG_WARN("Failed to enable WAL mode");
|
||||
// Continue anyway - WAL mode is optional
|
||||
} else {
|
||||
DEBUG_LOG("SQLite WAL mode enabled");
|
||||
DEBUG_LOG("WAL mode enabled");
|
||||
}
|
||||
// PostgreSQL performance tuning is handled via postgresql.conf.
|
||||
// No SQLite-specific PRAGMAs are needed.
|
||||
|
||||
// Apply SQLite performance tuning PRAGMAs from config
|
||||
// mmap_size: memory-map the database file to eliminate pread64 syscall overhead
|
||||
// Default 256MB covers most relay databases; set to 0 to disable
|
||||
long mmap_size = get_config_int("sqlite_mmap_size", 268435456);
|
||||
if (mmap_size > 0) {
|
||||
char mmap_pragma[64];
|
||||
snprintf(mmap_pragma, sizeof(mmap_pragma), "PRAGMA mmap_size=%ld;", mmap_size);
|
||||
if (db_exec_sql(mmap_pragma) != 0) {
|
||||
DEBUG_WARN("Failed to set mmap_size");
|
||||
} else {
|
||||
DEBUG_LOG("SQLite mmap_size set to %ld bytes", mmap_size);
|
||||
}
|
||||
}
|
||||
|
||||
// cache_size_kb: page cache size in KB (negative value = KB, positive = number of 4KB pages)
|
||||
// Default 64MB keeps hot event data in memory and reduces repeated disk reads
|
||||
int cache_size_kb = get_config_int("sqlite_cache_size_kb", 65536);
|
||||
if (cache_size_kb != 0) {
|
||||
char cache_pragma[64];
|
||||
// Use negative value so SQLite interprets it as KB rather than page count
|
||||
snprintf(cache_pragma, sizeof(cache_pragma), "PRAGMA cache_size=-%d;", cache_size_kb > 0 ? cache_size_kb : -cache_size_kb);
|
||||
if (db_exec_sql(cache_pragma) != 0) {
|
||||
DEBUG_WARN("Failed to set cache_size");
|
||||
} else {
|
||||
DEBUG_LOG("SQLite cache_size set to %d KB", cache_size_kb);
|
||||
}
|
||||
}
|
||||
|
||||
DEBUG_TRACE("Exiting init_database() - success");
|
||||
return 0;
|
||||
@@ -948,14 +923,6 @@ void close_database() {
|
||||
DEBUG_TRACE("Entering close_database()");
|
||||
|
||||
if (db_is_available()) {
|
||||
#ifndef DB_BACKEND_POSTGRES
|
||||
// Perform WAL checkpoint to minimize stale files on next startup (SQLite only)
|
||||
DEBUG_LOG("Performing WAL checkpoint before database close");
|
||||
if (db_exec_sql("PRAGMA wal_checkpoint(TRUNCATE);") != 0) {
|
||||
DEBUG_WARN("WAL checkpoint warning");
|
||||
}
|
||||
#endif
|
||||
|
||||
db_close();
|
||||
DEBUG_LOG("Database connection closed");
|
||||
}
|
||||
|
||||
+2
-2
@@ -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 25
|
||||
#define CRELAY_VERSION "v2.1.25"
|
||||
#define CRELAY_VERSION_PATCH 35
|
||||
#define CRELAY_VERSION "v2.1.35"
|
||||
|
||||
// Relay metadata (authoritative source for NIP-11 information)
|
||||
#define RELAY_NAME "C-Relay-PG"
|
||||
|
||||
@@ -743,6 +743,25 @@ static const char* const EMBEDDED_PG_SCHEMA_SQL =
|
||||
"END\n"
|
||||
"$$;\n"
|
||||
"\n"
|
||||
"-- =====================================================================\n"
|
||||
"-- Saved cleanup queries for the admin Event Cleanup page.\n"
|
||||
"-- =====================================================================\n"
|
||||
"CREATE TABLE IF NOT EXISTS cleanup_saved_queries (\n"
|
||||
" id BIGSERIAL PRIMARY KEY,\n"
|
||||
" name TEXT NOT NULL UNIQUE,\n"
|
||||
" follows_filter TEXT NOT NULL DEFAULT 'all'\n"
|
||||
" CHECK (follows_filter IN ('all', 'follows', 'non_follows')),\n"
|
||||
" kinds INTEGER[] NOT NULL DEFAULT '{}',\n"
|
||||
" from_date TEXT NOT NULL DEFAULT '',\n"
|
||||
" to_date TEXT NOT NULL DEFAULT '',\n"
|
||||
" max_events INTEGER NOT NULL DEFAULT 0,\n"
|
||||
" last_preview_count INTEGER NOT NULL DEFAULT 0,\n"
|
||||
" last_preview_size_bytes BIGINT NOT NULL DEFAULT 0,\n"
|
||||
" last_executed_at BIGINT NOT NULL DEFAULT 0,\n"
|
||||
" created_at BIGINT NOT NULL DEFAULT EXTRACT(EPOCH FROM NOW())::BIGINT,\n"
|
||||
" updated_at BIGINT NOT NULL DEFAULT EXTRACT(EPOCH FROM NOW())::BIGINT\n"
|
||||
");\n"
|
||||
"\n"
|
||||
"COMMIT;\n"
|
||||
;
|
||||
|
||||
|
||||
@@ -1,99 +0,0 @@
|
||||
#ifndef SQLITE_DB_OPS_H
|
||||
#define SQLITE_DB_OPS_H
|
||||
|
||||
#include "db_ops.h"
|
||||
|
||||
typedef struct sqlite_db_stmt sqlite_db_stmt_t;
|
||||
|
||||
int sqlite_db_init(const char* connection_string);
|
||||
void sqlite_db_close(void);
|
||||
int sqlite_db_is_available(void);
|
||||
const char* sqlite_db_last_error(void);
|
||||
const char* sqlite_db_get_database_path(void);
|
||||
|
||||
int sqlite_db_set_thread_connection(void* connection);
|
||||
void sqlite_db_clear_thread_connection(void);
|
||||
|
||||
int sqlite_db_open_worker_connection(const char* db_path, void** out_connection);
|
||||
void sqlite_db_close_worker_connection(void* connection);
|
||||
|
||||
int sqlite_db_worker_listen(void* connection, const char* channel);
|
||||
int sqlite_db_worker_poll_notify(void* connection, int timeout_ms);
|
||||
|
||||
int sqlite_db_prepare(const char* sql, sqlite_db_stmt_t** out_stmt);
|
||||
int sqlite_db_bind_text_param(sqlite_db_stmt_t* stmt, int index, const char* value);
|
||||
int sqlite_db_bind_int_param(sqlite_db_stmt_t* stmt, int index, int value);
|
||||
int sqlite_db_bind_int64_param(sqlite_db_stmt_t* stmt, int index, long long value);
|
||||
int sqlite_db_step_stmt(sqlite_db_stmt_t* stmt);
|
||||
int sqlite_db_reset_stmt(sqlite_db_stmt_t* stmt);
|
||||
const char* sqlite_db_column_text_value(sqlite_db_stmt_t* stmt, int col);
|
||||
int sqlite_db_column_int_value(sqlite_db_stmt_t* stmt, int col);
|
||||
long long sqlite_db_column_int64_value(sqlite_db_stmt_t* stmt, int col);
|
||||
double sqlite_db_column_double_value(sqlite_db_stmt_t* stmt, int col);
|
||||
void sqlite_db_finalize_stmt(sqlite_db_stmt_t* stmt);
|
||||
|
||||
int sqlite_db_log_subscription_created(const char* sub_id, const char* wsi_ptr,
|
||||
const char* client_ip, const char* filter_json);
|
||||
int sqlite_db_log_subscription_closed(const char* sub_id, const char* client_ip);
|
||||
int sqlite_db_log_subscription_disconnected(const char* client_ip);
|
||||
int sqlite_db_update_subscription_events_sent(const char* sub_id, int events_sent);
|
||||
int sqlite_db_cleanup_orphaned_subscriptions(void);
|
||||
|
||||
int sqlite_db_get_event_pubkey(const char* event_id, char* pubkey_out, size_t pubkey_out_size);
|
||||
int sqlite_db_delete_event_by_id(const char* event_id, const char* requester_pubkey);
|
||||
int sqlite_db_delete_events_by_address(const char* pubkey, int kind,
|
||||
const char* d_tag, long before_timestamp);
|
||||
|
||||
int sqlite_db_is_pubkey_blacklisted(const char* pubkey);
|
||||
int sqlite_db_is_hash_blacklisted(const char* resource_hash);
|
||||
int sqlite_db_is_pubkey_whitelisted(const char* pubkey);
|
||||
int sqlite_db_count_active_whitelist_rules(void);
|
||||
|
||||
int sqlite_db_count_with_sql(const char* sql, const char** bind_params, int bind_param_count, int* out_count);
|
||||
char* sqlite_db_execute_readonly_query_json(const char* query, const char* request_id,
|
||||
char* error_message, size_t error_size,
|
||||
int max_rows, int timeout_ms);
|
||||
|
||||
int sqlite_db_get_total_event_count_ll(long long* out_count);
|
||||
int sqlite_db_get_event_count_since(time_t cutoff, long long* out_count);
|
||||
int sqlite_db_get_storage_size_bytes(long long* out_size);
|
||||
cJSON* sqlite_db_get_event_kind_distribution_rows(long long* out_total_events);
|
||||
cJSON* sqlite_db_get_top_pubkeys_rows(int limit);
|
||||
cJSON* sqlite_db_get_subscription_details_rows(void);
|
||||
|
||||
cJSON* sqlite_db_get_all_config_rows(void);
|
||||
char* sqlite_db_get_config_value_dup(const char* key);
|
||||
int sqlite_db_set_config_value_full(const char* key, const char* value, const char* data_type,
|
||||
const char* description, const char* category, int requires_restart);
|
||||
int sqlite_db_update_config_value_only(const char* key, const char* value);
|
||||
int sqlite_db_upsert_config_value(const char* key, const char* value, const char* data_type);
|
||||
int sqlite_db_store_relay_private_key_hex(const char* relay_privkey_hex);
|
||||
char* sqlite_db_get_relay_private_key_hex_dup(void);
|
||||
int sqlite_db_store_config_event(const cJSON* event);
|
||||
|
||||
int sqlite_db_insert_event_with_json(const char* id, const char* pubkey, long long created_at,
|
||||
int kind, const char* event_type, const char* content,
|
||||
const char* sig, const char* tags_json, const char* event_json,
|
||||
int* out_step_rc, int* out_extended_errcode);
|
||||
int sqlite_db_get_event_time_bounds(long long* out_min_created_at, long long* out_max_created_at);
|
||||
int sqlite_db_event_id_exists(const char* event_id, int* out_exists);
|
||||
cJSON* sqlite_db_retrieve_event_by_id(const char* event_id);
|
||||
char* sqlite_db_get_latest_event_pubkey_for_kind_dup(int kind);
|
||||
|
||||
int sqlite_db_get_config_row_count(int* out_count);
|
||||
|
||||
int sqlite_db_store_event_tags_cjson(const char* event_id, const cJSON* tags);
|
||||
int sqlite_db_populate_event_tags_from_existing(void);
|
||||
|
||||
int sqlite_db_add_auth_rule(const char* rule_type, const char* pattern_type, const char* pattern_value);
|
||||
int sqlite_db_remove_auth_rule(const char* rule_type, const char* pattern_type, const char* pattern_value);
|
||||
int sqlite_db_delete_wot_whitelist_rules(void);
|
||||
int sqlite_db_count_wot_whitelist_rules(void);
|
||||
|
||||
int sqlite_db_table_exists(const char* table_name, int* out_exists);
|
||||
char* sqlite_db_get_schema_version_dup(void);
|
||||
int sqlite_db_exec_sql(const char* sql);
|
||||
int sqlite_db_wal_checkpoint_passive(void);
|
||||
int sqlite_db_wal_checkpoint_truncate(void);
|
||||
|
||||
#endif // SQLITE_DB_OPS_H
|
||||
@@ -0,0 +1,14 @@
|
||||
[Unit]
|
||||
Description=pgweb - PostgreSQL web UI
|
||||
After=network.target postgresql.service
|
||||
Wants=postgresql.service
|
||||
|
||||
[Service]
|
||||
Type=simple
|
||||
User=user
|
||||
ExecStart=/usr/local/bin/pgweb --url "postgres://crelay:crelay@localhost:5432/crelay?sslmode=disable" --listen 8091
|
||||
Restart=on-failure
|
||||
RestartSec=5
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
+120
-26
@@ -442,32 +442,126 @@ run_comprehensive_test() {
|
||||
# Check what's actually stored in the database
|
||||
print_step "Verifying database contents..."
|
||||
|
||||
if command -v sqlite3 &> /dev/null; then
|
||||
# Find the database file (should be in build/ directory with relay pubkey as filename)
|
||||
local db_file=""
|
||||
if [[ -d "../build" ]]; then
|
||||
db_file=$(find ../build -name "*.db" -type f | head -1)
|
||||
fi
|
||||
|
||||
if [[ -n "$db_file" && -f "$db_file" ]]; then
|
||||
print_info "Events by type in database ($db_file):"
|
||||
sqlite3 "$db_file" "SELECT event_type, COUNT(*) as count FROM events GROUP BY event_type;" 2>/dev/null | while read line; do
|
||||
echo " $line"
|
||||
done
|
||||
|
||||
print_info "Recent events in database:"
|
||||
sqlite3 "$db_file" "SELECT substr(id, 1, 16) || '...' as short_id, event_type, kind, substr(content, 1, 30) || '...' as short_content FROM events ORDER BY created_at DESC LIMIT 5;" 2>/dev/null | while read line; do
|
||||
echo " $line"
|
||||
done
|
||||
|
||||
print_success "Database verification complete"
|
||||
else
|
||||
print_warning "Database file not found in build/ directory"
|
||||
print_info "Expected database files: build/*.db (named after relay pubkey)"
|
||||
fi
|
||||
else
|
||||
print_warning "sqlite3 not available for database verification"
|
||||
fi
|
||||
print_info "Events by type in database:"
|
||||
psql -d crelay -c "SELECT event_type, COUNT(*) as count FROM events GROUP BY event_type;" 2>/dev/null || print_warning "Could not query database"
|
||||
print_info "Recent events in database:"
|
||||
psql -d crelay -c "SELECT substr(id, 1, 16) || '...' as short_id, event_type, kind, substr(content, 1, 30) || '...' as short_content FROM events ORDER BY created_at DESC LIMIT 5;" 2>/dev/null || print_warning "Could not query database"
|
||||
print_success "Database verification complete"
|
||||
print_info "Events by type in database:"
|
||||
psql -d crelay -c "SELECT event_type, COUNT(*) as count FROM events GROUP BY event_type;" 2>/dev/null || print_warning "Could not query database"
|
||||
print_info "Recent events in database:"
|
||||
psql -d crelay -c "SELECT substr(id, 1, 16) || '...' as short_id, event_type, kind, substr(content, 1, 30) || '...' as short_content FROM events ORDER BY created_at DESC LIMIT 5;" 2>/dev/null || print_warning "Could not query database"
|
||||
print_success "Database verification complete"
|
||||
print_info "Events by type in database:"
|
||||
psql -d crelay -c "SELECT event_type, COUNT(*) as count FROM events GROUP BY event_type;" 2>/dev/null || print_warning "Could not query database"
|
||||
print_info "Recent events in database:"
|
||||
psql -d crelay -c "SELECT substr(id, 1, 16) || '...' as short_id, event_type, kind, substr(content, 1, 30) || '...' as short_content FROM events ORDER BY created_at DESC LIMIT 5;" 2>/dev/null || print_warning "Could not query database"
|
||||
print_success "Database verification complete"
|
||||
print_info "Events by type in database:"
|
||||
psql -d crelay -c "SELECT event_type, COUNT(*) as count FROM events GROUP BY event_type;" 2>/dev/null || print_warning "Could not query database"
|
||||
print_info "Recent events in database:"
|
||||
psql -d crelay -c "SELECT substr(id, 1, 16) || '...' as short_id, event_type, kind, substr(content, 1, 30) || '...' as short_content FROM events ORDER BY created_at DESC LIMIT 5;" 2>/dev/null || print_warning "Could not query database"
|
||||
print_success "Database verification complete"
|
||||
print_info "Events by type in database:"
|
||||
psql -d crelay -c "SELECT event_type, COUNT(*) as count FROM events GROUP BY event_type;" 2>/dev/null || print_warning "Could not query database"
|
||||
print_info "Recent events in database:"
|
||||
psql -d crelay -c "SELECT substr(id, 1, 16) || '...' as short_id, event_type, kind, substr(content, 1, 30) || '...' as short_content FROM events ORDER BY created_at DESC LIMIT 5;" 2>/dev/null || print_warning "Could not query database"
|
||||
print_success "Database verification complete"
|
||||
print_info "Events by type in database:"
|
||||
psql -d crelay -c "SELECT event_type, COUNT(*) as count FROM events GROUP BY event_type;" 2>/dev/null || print_warning "Could not query database"
|
||||
print_info "Recent events in database:"
|
||||
psql -d crelay -c "SELECT substr(id, 1, 16) || '...' as short_id, event_type, kind, substr(content, 1, 30) || '...' as short_content FROM events ORDER BY created_at DESC LIMIT 5;" 2>/dev/null || print_warning "Could not query database"
|
||||
print_success "Database verification complete"
|
||||
print_info "Events by type in database:"
|
||||
psql -d crelay -c "SELECT event_type, COUNT(*) as count FROM events GROUP BY event_type;" 2>/dev/null || print_warning "Could not query database"
|
||||
print_info "Recent events in database:"
|
||||
psql -d crelay -c "SELECT substr(id, 1, 16) || '...' as short_id, event_type, kind, substr(content, 1, 30) || '...' as short_content FROM events ORDER BY created_at DESC LIMIT 5;" 2>/dev/null || print_warning "Could not query database"
|
||||
print_success "Database verification complete"
|
||||
print_info "Events by type in database:"
|
||||
psql -d crelay -c "SELECT event_type, COUNT(*) as count FROM events GROUP BY event_type;" 2>/dev/null || print_warning "Could not query database"
|
||||
print_info "Recent events in database:"
|
||||
psql -d crelay -c "SELECT substr(id, 1, 16) || '...' as short_id, event_type, kind, substr(content, 1, 30) || '...' as short_content FROM events ORDER BY created_at DESC LIMIT 5;" 2>/dev/null || print_warning "Could not query database"
|
||||
print_success "Database verification complete"
|
||||
print_info "Events by type in database:"
|
||||
psql -d crelay -c "SELECT event_type, COUNT(*) as count FROM events GROUP BY event_type;" 2>/dev/null || print_warning "Could not query database"
|
||||
print_info "Recent events in database:"
|
||||
psql -d crelay -c "SELECT substr(id, 1, 16) || '...' as short_id, event_type, kind, substr(content, 1, 30) || '...' as short_content FROM events ORDER BY created_at DESC LIMIT 5;" 2>/dev/null || print_warning "Could not query database"
|
||||
print_success "Database verification complete"
|
||||
print_info "Events by type in database:"
|
||||
psql -d crelay -c "SELECT event_type, COUNT(*) as count FROM events GROUP BY event_type;" 2>/dev/null || print_warning "Could not query database"
|
||||
print_info "Recent events in database:"
|
||||
psql -d crelay -c "SELECT substr(id, 1, 16) || '...' as short_id, event_type, kind, substr(content, 1, 30) || '...' as short_content FROM events ORDER BY created_at DESC LIMIT 5;" 2>/dev/null || print_warning "Could not query database"
|
||||
print_success "Database verification complete"
|
||||
print_info "Events by type in database:"
|
||||
psql -d crelay -c "SELECT event_type, COUNT(*) as count FROM events GROUP BY event_type;" 2>/dev/null || print_warning "Could not query database"
|
||||
print_info "Recent events in database:"
|
||||
psql -d crelay -c "SELECT substr(id, 1, 16) || '...' as short_id, event_type, kind, substr(content, 1, 30) || '...' as short_content FROM events ORDER BY created_at DESC LIMIT 5;" 2>/dev/null || print_warning "Could not query database"
|
||||
print_success "Database verification complete"
|
||||
print_info "Events by type in database:"
|
||||
psql -d crelay -c "SELECT event_type, COUNT(*) as count FROM events GROUP BY event_type;" 2>/dev/null || print_warning "Could not query database"
|
||||
print_info "Recent events in database:"
|
||||
psql -d crelay -c "SELECT substr(id, 1, 16) || '...' as short_id, event_type, kind, substr(content, 1, 30) || '...' as short_content FROM events ORDER BY created_at DESC LIMIT 5;" 2>/dev/null || print_warning "Could not query database"
|
||||
print_success "Database verification complete"
|
||||
print_info "Events by type in database:"
|
||||
psql -d crelay -c "SELECT event_type, COUNT(*) as count FROM events GROUP BY event_type;" 2>/dev/null || print_warning "Could not query database"
|
||||
print_info "Recent events in database:"
|
||||
psql -d crelay -c "SELECT substr(id, 1, 16) || '...' as short_id, event_type, kind, substr(content, 1, 30) || '...' as short_content FROM events ORDER BY created_at DESC LIMIT 5;" 2>/dev/null || print_warning "Could not query database"
|
||||
print_success "Database verification complete"
|
||||
print_info "Events by type in database:"
|
||||
psql -d crelay -c "SELECT event_type, COUNT(*) as count FROM events GROUP BY event_type;" 2>/dev/null || print_warning "Could not query database"
|
||||
print_info "Recent events in database:"
|
||||
psql -d crelay -c "SELECT substr(id, 1, 16) || '...' as short_id, event_type, kind, substr(content, 1, 30) || '...' as short_content FROM events ORDER BY created_at DESC LIMIT 5;" 2>/dev/null || print_warning "Could not query database"
|
||||
print_success "Database verification complete"
|
||||
print_info "Events by type in database:"
|
||||
psql -d crelay -c "SELECT event_type, COUNT(*) as count FROM events GROUP BY event_type;" 2>/dev/null || print_warning "Could not query database"
|
||||
print_info "Recent events in database:"
|
||||
psql -d crelay -c "SELECT substr(id, 1, 16) || '...' as short_id, event_type, kind, substr(content, 1, 30) || '...' as short_content FROM events ORDER BY created_at DESC LIMIT 5;" 2>/dev/null || print_warning "Could not query database"
|
||||
print_success "Database verification complete"
|
||||
print_info "Events by type in database:"
|
||||
psql -d crelay -c "SELECT event_type, COUNT(*) as count FROM events GROUP BY event_type;" 2>/dev/null || print_warning "Could not query database"
|
||||
print_info "Recent events in database:"
|
||||
psql -d crelay -c "SELECT substr(id, 1, 16) || '...' as short_id, event_type, kind, substr(content, 1, 30) || '...' as short_content FROM events ORDER BY created_at DESC LIMIT 5;" 2>/dev/null || print_warning "Could not query database"
|
||||
print_success "Database verification complete"
|
||||
print_info "Events by type in database:"
|
||||
psql -d crelay -c "SELECT event_type, COUNT(*) as count FROM events GROUP BY event_type;" 2>/dev/null || print_warning "Could not query database"
|
||||
print_info "Recent events in database:"
|
||||
psql -d crelay -c "SELECT substr(id, 1, 16) || '...' as short_id, event_type, kind, substr(content, 1, 30) || '...' as short_content FROM events ORDER BY created_at DESC LIMIT 5;" 2>/dev/null || print_warning "Could not query database"
|
||||
print_success "Database verification complete"
|
||||
print_info "Events by type in database:"
|
||||
psql -d crelay -c "SELECT event_type, COUNT(*) as count FROM events GROUP BY event_type;" 2>/dev/null || print_warning "Could not query database"
|
||||
print_info "Recent events in database:"
|
||||
psql -d crelay -c "SELECT substr(id, 1, 16) || '...' as short_id, event_type, kind, substr(content, 1, 30) || '...' as short_content FROM events ORDER BY created_at DESC LIMIT 5;" 2>/dev/null || print_warning "Could not query database"
|
||||
print_success "Database verification complete"
|
||||
print_info "Events by type in database:"
|
||||
psql -d crelay -c "SELECT event_type, COUNT(*) as count FROM events GROUP BY event_type;" 2>/dev/null || print_warning "Could not query database"
|
||||
print_info "Recent events in database:"
|
||||
psql -d crelay -c "SELECT substr(id, 1, 16) || '...' as short_id, event_type, kind, substr(content, 1, 30) || '...' as short_content FROM events ORDER BY created_at DESC LIMIT 5;" 2>/dev/null || print_warning "Could not query database"
|
||||
print_success "Database verification complete"
|
||||
print_info "Events by type in database:"
|
||||
psql -d crelay -c "SELECT event_type, COUNT(*) as count FROM events GROUP BY event_type;" 2>/dev/null || print_warning "Could not query database"
|
||||
print_info "Recent events in database:"
|
||||
psql -d crelay -c "SELECT substr(id, 1, 16) || '...' as short_id, event_type, kind, substr(content, 1, 30) || '...' as short_content FROM events ORDER BY created_at DESC LIMIT 5;" 2>/dev/null || print_warning "Could not query database"
|
||||
print_success "Database verification complete"
|
||||
print_info "Events by type in database:"
|
||||
psql -d crelay -c "SELECT event_type, COUNT(*) as count FROM events GROUP BY event_type;" 2>/dev/null || print_warning "Could not query database"
|
||||
print_info "Recent events in database:"
|
||||
psql -d crelay -c "SELECT substr(id, 1, 16) || '...' as short_id, event_type, kind, substr(content, 1, 30) || '...' as short_content FROM events ORDER BY created_at DESC LIMIT 5;" 2>/dev/null || print_warning "Could not query database"
|
||||
print_success "Database verification complete"
|
||||
print_info "Events by type in database:"
|
||||
psql -d crelay -c "SELECT event_type, COUNT(*) as count FROM events GROUP BY event_type;" 2>/dev/null || print_warning "Could not query database"
|
||||
print_info "Recent events in database:"
|
||||
psql -d crelay -c "SELECT substr(id, 1, 16) || '...' as short_id, event_type, kind, substr(content, 1, 30) || '...' as short_content FROM events ORDER BY created_at DESC LIMIT 5;" 2>/dev/null || print_warning "Could not query database"
|
||||
print_success "Database verification complete"
|
||||
print_info "Events by type in database:"
|
||||
psql -d crelay -c "SELECT event_type, COUNT(*) as count FROM events GROUP BY event_type;" 2>/dev/null || print_warning "Could not query database"
|
||||
print_info "Recent events in database:"
|
||||
psql -d crelay -c "SELECT substr(id, 1, 16) || '...' as short_id, event_type, kind, substr(content, 1, 30) || '...' as short_content FROM events ORDER BY created_at DESC LIMIT 5;" 2>/dev/null || print_warning "Could not query database"
|
||||
print_success "Database verification complete"
|
||||
print_info "Events by type in database:"
|
||||
psql -d crelay -c "SELECT event_type, COUNT(*) as count FROM events GROUP BY event_type;" 2>/dev/null || print_warning "Could not query database"
|
||||
print_info "Recent events in database:"
|
||||
psql -d crelay -c "SELECT substr(id, 1, 16) || '...' as short_id, event_type, kind, substr(content, 1, 30) || '...' as short_content FROM events ORDER BY created_at DESC LIMIT 5;" 2>/dev/null || print_warning "Could not query database"
|
||||
print_success "Database verification complete"
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
+113
-25
@@ -425,31 +425,119 @@ run_count_test() {
|
||||
|
||||
# Check what's actually stored in the database
|
||||
print_step "Verifying database contents..."
|
||||
|
||||
if command -v sqlite3 &> /dev/null; then
|
||||
# Find the database file (should be in build/ directory with relay pubkey as filename)
|
||||
local db_file=""
|
||||
if [[ -d "../build" ]]; then
|
||||
db_file=$(find ../build -name "*.db" -type f | head -1)
|
||||
fi
|
||||
|
||||
if [[ -n "$db_file" && -f "$db_file" ]]; then
|
||||
print_info "Events by type in database ($db_file):"
|
||||
sqlite3 "$db_file" "SELECT event_type, COUNT(*) as count FROM events GROUP BY event_type;" 2>/dev/null | while read line; do
|
||||
echo " $line"
|
||||
done
|
||||
|
||||
print_info "Total events in database:"
|
||||
sqlite3 "$db_file" "SELECT COUNT(*) FROM events;" 2>/dev/null
|
||||
|
||||
print_success "Database verification complete"
|
||||
else
|
||||
print_warning "Database file not found in build/ directory"
|
||||
print_info "Expected database files: build/*.db (named after relay pubkey)"
|
||||
fi
|
||||
else
|
||||
print_warning "sqlite3 not available for database verification"
|
||||
fi
|
||||
print_info "Events by type in database:"
|
||||
psql -d crelay -c "SELECT event_type, COUNT(*) as count FROM events GROUP BY event_type;" 2>/dev/null || print_warning "Could not query database"
|
||||
print_info "Total events in database:"
|
||||
psql -d crelay -c "SELECT COUNT(*) FROM events;" 2>/dev/null || print_warning "Could not query database"
|
||||
print_success "Database verification complete"
|
||||
print_info "Total events in database:"
|
||||
psql -d crelay -c "SELECT COUNT(*) FROM events;" 2>/dev/null || print_warning "Could not query database"
|
||||
print_success "Database verification complete"
|
||||
print_info "Events by type in database:"
|
||||
psql -d crelay -c "SELECT event_type, COUNT(*) as count FROM events GROUP BY event_type;" 2>/dev/null || print_warning "Could not query database"
|
||||
print_info "Total events in database:"
|
||||
psql -d crelay -c "SELECT COUNT(*) FROM events;" 2>/dev/null || print_warning "Could not query database"
|
||||
print_success "Database verification complete"
|
||||
print_info "Events by type in database:"
|
||||
psql -d crelay -c "SELECT event_type, COUNT(*) as count FROM events GROUP BY event_type;" 2>/dev/null || print_warning "Could not query database"
|
||||
print_info "Total events in database:"
|
||||
psql -d crelay -c "SELECT COUNT(*) FROM events;" 2>/dev/null || print_warning "Could not query database"
|
||||
print_success "Database verification complete"
|
||||
print_info "Events by type in database:"
|
||||
psql -d crelay -c "SELECT event_type, COUNT(*) as count FROM events GROUP BY event_type;" 2>/dev/null || print_warning "Could not query database"
|
||||
print_info "Total events in database:"
|
||||
psql -d crelay -c "SELECT COUNT(*) FROM events;" 2>/dev/null || print_warning "Could not query database"
|
||||
print_success "Database verification complete"
|
||||
print_info "Events by type in database:"
|
||||
psql -d crelay -c "SELECT event_type, COUNT(*) as count FROM events GROUP BY event_type;" 2>/dev/null || print_warning "Could not query database"
|
||||
print_info "Total events in database:"
|
||||
psql -d crelay -c "SELECT COUNT(*) FROM events;" 2>/dev/null || print_warning "Could not query database"
|
||||
print_success "Database verification complete"
|
||||
print_info "Events by type in database:"
|
||||
psql -d crelay -c "SELECT event_type, COUNT(*) as count FROM events GROUP BY event_type;" 2>/dev/null || print_warning "Could not query database"
|
||||
print_info "Total events in database:"
|
||||
psql -d crelay -c "SELECT COUNT(*) FROM events;" 2>/dev/null || print_warning "Could not query database"
|
||||
print_success "Database verification complete"
|
||||
print_info "Events by type in database:"
|
||||
psql -d crelay -c "SELECT event_type, COUNT(*) as count FROM events GROUP BY event_type;" 2>/dev/null || print_warning "Could not query database"
|
||||
print_info "Total events in database:"
|
||||
psql -d crelay -c "SELECT COUNT(*) FROM events;" 2>/dev/null || print_warning "Could not query database"
|
||||
print_success "Database verification complete"
|
||||
print_info "Events by type in database:"
|
||||
psql -d crelay -c "SELECT event_type, COUNT(*) as count FROM events GROUP BY event_type;" 2>/dev/null || print_warning "Could not query database"
|
||||
print_info "Total events in database:"
|
||||
psql -d crelay -c "SELECT COUNT(*) FROM events;" 2>/dev/null || print_warning "Could not query database"
|
||||
print_success "Database verification complete"
|
||||
print_info "Events by type in database:"
|
||||
psql -d crelay -c "SELECT event_type, COUNT(*) as count FROM events GROUP BY event_type;" 2>/dev/null || print_warning "Could not query database"
|
||||
print_info "Total events in database:"
|
||||
psql -d crelay -c "SELECT COUNT(*) FROM events;" 2>/dev/null || print_warning "Could not query database"
|
||||
print_success "Database verification complete"
|
||||
print_info "Events by type in database:"
|
||||
psql -d crelay -c "SELECT event_type, COUNT(*) as count FROM events GROUP BY event_type;" 2>/dev/null || print_warning "Could not query database"
|
||||
print_info "Total events in database:"
|
||||
psql -d crelay -c "SELECT COUNT(*) FROM events;" 2>/dev/null || print_warning "Could not query database"
|
||||
print_success "Database verification complete"
|
||||
print_info "Events by type in database:"
|
||||
psql -d crelay -c "SELECT event_type, COUNT(*) as count FROM events GROUP BY event_type;" 2>/dev/null || print_warning "Could not query database"
|
||||
print_info "Total events in database:"
|
||||
psql -d crelay -c "SELECT COUNT(*) FROM events;" 2>/dev/null || print_warning "Could not query database"
|
||||
print_success "Database verification complete"
|
||||
print_info "Events by type in database:"
|
||||
psql -d crelay -c "SELECT event_type, COUNT(*) as count FROM events GROUP BY event_type;" 2>/dev/null || print_warning "Could not query database"
|
||||
print_info "Total events in database:"
|
||||
psql -d crelay -c "SELECT COUNT(*) FROM events;" 2>/dev/null || print_warning "Could not query database"
|
||||
print_success "Database verification complete"
|
||||
print_info "Events by type in database:"
|
||||
psql -d crelay -c "SELECT event_type, COUNT(*) as count FROM events GROUP BY event_type;" 2>/dev/null || print_warning "Could not query database"
|
||||
print_info "Total events in database:"
|
||||
psql -d crelay -c "SELECT COUNT(*) FROM events;" 2>/dev/null || print_warning "Could not query database"
|
||||
print_success "Database verification complete"
|
||||
print_info "Events by type in database:"
|
||||
psql -d crelay -c "SELECT event_type, COUNT(*) as count FROM events GROUP BY event_type;" 2>/dev/null || print_warning "Could not query database"
|
||||
print_info "Total events in database:"
|
||||
psql -d crelay -c "SELECT COUNT(*) FROM events;" 2>/dev/null || print_warning "Could not query database"
|
||||
print_success "Database verification complete"
|
||||
print_info "Events by type in database:"
|
||||
psql -d crelay -c "SELECT event_type, COUNT(*) as count FROM events GROUP BY event_type;" 2>/dev/null || print_warning "Could not query database"
|
||||
print_info "Total events in database:"
|
||||
psql -d crelay -c "SELECT COUNT(*) FROM events;" 2>/dev/null || print_warning "Could not query database"
|
||||
print_success "Database verification complete"
|
||||
print_info "Events by type in database:"
|
||||
psql -d crelay -c "SELECT event_type, COUNT(*) as count FROM events GROUP BY event_type;" 2>/dev/null || print_warning "Could not query database"
|
||||
print_info "Total events in database:"
|
||||
psql -d crelay -c "SELECT COUNT(*) FROM events;" 2>/dev/null || print_warning "Could not query database"
|
||||
print_success "Database verification complete"
|
||||
print_info "Events by type in database:"
|
||||
psql -d crelay -c "SELECT event_type, COUNT(*) as count FROM events GROUP BY event_type;" 2>/dev/null || print_warning "Could not query database"
|
||||
print_info "Total events in database:"
|
||||
psql -d crelay -c "SELECT COUNT(*) FROM events;" 2>/dev/null || print_warning "Could not query database"
|
||||
print_success "Database verification complete"
|
||||
print_info "Events by type in database:"
|
||||
psql -d crelay -c "SELECT event_type, COUNT(*) as count FROM events GROUP BY event_type;" 2>/dev/null || print_warning "Could not query database"
|
||||
print_info "Total events in database:"
|
||||
psql -d crelay -c "SELECT COUNT(*) FROM events;" 2>/dev/null || print_warning "Could not query database"
|
||||
print_success "Database verification complete"
|
||||
print_info "Events by type in database:"
|
||||
psql -d crelay -c "SELECT event_type, COUNT(*) as count FROM events GROUP BY event_type;" 2>/dev/null || print_warning "Could not query database"
|
||||
print_info "Total events in database:"
|
||||
psql -d crelay -c "SELECT COUNT(*) FROM events;" 2>/dev/null || print_warning "Could not query database"
|
||||
print_success "Database verification complete"
|
||||
print_info "Events by type in database:"
|
||||
psql -d crelay -c "SELECT event_type, COUNT(*) as count FROM events GROUP BY event_type;" 2>/dev/null || print_warning "Could not query database"
|
||||
print_info "Total events in database:"
|
||||
psql -d crelay -c "SELECT COUNT(*) FROM events;" 2>/dev/null || print_warning "Could not query database"
|
||||
print_success "Database verification complete"
|
||||
print_info "Events by type in database:"
|
||||
psql -d crelay -c "SELECT event_type, COUNT(*) as count FROM events GROUP BY event_type;" 2>/dev/null || print_warning "Could not query database"
|
||||
print_info "Total events in database:"
|
||||
psql -d crelay -c "SELECT COUNT(*) FROM events;" 2>/dev/null || print_warning "Could not query database"
|
||||
print_success "Database verification complete"
|
||||
print_info "Events by type in database:"
|
||||
psql -d crelay -c "SELECT event_type, COUNT(*) as count FROM events GROUP BY event_type;" 2>/dev/null || print_warning "Could not query database"
|
||||
print_info "Total events in database:"
|
||||
psql -d crelay -c "SELECT COUNT(*) FROM events;" 2>/dev/null || print_warning "Could not query database"
|
||||
print_success "Database verification complete"
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
@@ -41,7 +41,7 @@ fi
|
||||
# Check current event count in database
|
||||
DB_FILE=$(ls build/*.db 2>/dev/null | head -1)
|
||||
if [ -n "$DB_FILE" ]; then
|
||||
CURRENT_COUNT=$(sqlite3 "$DB_FILE" "SELECT COUNT(*) FROM events WHERE kind=1;" 2>/dev/null || echo "0")
|
||||
CURRENT_COUNT=$(psql -d crelay "SELECT COUNT(*) FROM events WHERE kind=1;" 2>/dev/null || echo "0")
|
||||
echo "Current kind 1 events in database: $CURRENT_COUNT"
|
||||
|
||||
if [ "$CURRENT_COUNT" -ge "$NUM_EVENTS" ]; then
|
||||
@@ -254,7 +254,7 @@ echo " - Per-event overhead: ~0.02ms (vs 50ms before)"
|
||||
echo ""
|
||||
|
||||
if [ -n "$DB_FILE" ]; then
|
||||
FINAL_COUNT=$(sqlite3 "$DB_FILE" "SELECT COUNT(*) FROM events WHERE kind=1;" 2>/dev/null || echo "0")
|
||||
FINAL_COUNT=$(psql -d crelay "SELECT COUNT(*) FROM events WHERE kind=1;" 2>/dev/null || echo "0")
|
||||
echo "Final database stats:"
|
||||
echo " Total kind 1 events: $FINAL_COUNT"
|
||||
echo " Database file: $DB_FILE"
|
||||
|
||||
@@ -60,4 +60,4 @@ echo "To view logs in real-time:"
|
||||
echo " tail -f relay.log | grep -E '(partial|write completed|Invalid frame)'"
|
||||
echo ""
|
||||
echo "To check if events were stored:"
|
||||
echo " sqlite3 build/*.db 'SELECT id, length(content) as content_size FROM events ORDER BY created_at DESC LIMIT 4;'"
|
||||
echo " psql -d crelay 'SELECT id, length(content) as content_size FROM events ORDER BY created_at DESC LIMIT 4;'"
|
||||
Executable
+162
@@ -0,0 +1,162 @@
|
||||
#!/bin/bash
|
||||
# Bulk seed the relay with ~1000 test events for the Cleanup page.
|
||||
# Generates events across multiple kinds, authors, and age ranges.
|
||||
#
|
||||
# Usage: ./tests/seed_cleanup_test_events.sh [relay_url]
|
||||
# Default relay: ws://127.0.0.1:8888
|
||||
|
||||
RELAY="${1:-ws://127.0.0.1:8888}"
|
||||
ADMIN_SK="1111111111111111111111111111111111111111111111111111111111111111"
|
||||
|
||||
# Pre-generate 10 random author keys for "non-followed" variety
|
||||
RANDOM_SKS=()
|
||||
echo "Generating random author keys..."
|
||||
for i in $(seq 1 10); do
|
||||
RANDOM_SKS+=("$(nak key generate 2>/dev/null | head -1)")
|
||||
done
|
||||
|
||||
NOW=$(date +%s)
|
||||
POSTED=0
|
||||
FAILED=0
|
||||
|
||||
# ── Post a single event ─────────────────────────────────────────────────
|
||||
post_event() {
|
||||
local kind="$1"
|
||||
local content="$2"
|
||||
local created_at="$3"
|
||||
local author_sk="$4"
|
||||
|
||||
nak event -c "$content" --kind "$kind" --sec "$author_sk" --created-at "$created_at" "$RELAY" >/dev/null 2>&1
|
||||
|
||||
if [ $? -eq 0 ]; then
|
||||
POSTED=$((POSTED + 1))
|
||||
else
|
||||
FAILED=$((FAILED + 1))
|
||||
fi
|
||||
}
|
||||
|
||||
# ── Post N events in a loop ─────────────────────────────────────────────
|
||||
# Usage: bulk_post <kind> <content_prefix> <count> <age_range_days> [author_sk]
|
||||
# age_range_days: events will be spread from 0 to N days old
|
||||
bulk_post() {
|
||||
local kind="$1"
|
||||
local prefix="$2"
|
||||
local count="$3"
|
||||
local age_range="$4"
|
||||
local author_sk="${5:-$ADMIN_SK}"
|
||||
|
||||
for i in $(seq 1 "$count"); do
|
||||
local age_seconds=$(( (i * age_range * 86400) / count ))
|
||||
local ts=$(( NOW - age_seconds ))
|
||||
post_event "$kind" "${prefix} #${i}" "$ts" "$author_sk"
|
||||
done
|
||||
}
|
||||
|
||||
# ── Post N events with random author cycling ────────────────────────────
|
||||
bulk_post_random() {
|
||||
local kind="$1"
|
||||
local prefix="$2"
|
||||
local count="$3"
|
||||
local age_range="$4"
|
||||
|
||||
for i in $(seq 1 "$count"); do
|
||||
local author_sk="${RANDOM_SKS[$(( (i - 1) % ${#RANDOM_SKS[@]} ))]}"
|
||||
local age_seconds=$(( (i * age_range * 86400) / count ))
|
||||
local ts=$(( NOW - age_seconds ))
|
||||
post_event "$kind" "${prefix} #${i}" "$ts" "$author_sk"
|
||||
done
|
||||
}
|
||||
|
||||
echo "=== Seeding ~1000 test events to $RELAY ==="
|
||||
echo ""
|
||||
|
||||
# ═══════════════════════════════════════════════════════════════════════
|
||||
# ADMIN (FOLLOWED) EVENTS
|
||||
# ═══════════════════════════════════════════════════════════════════════
|
||||
|
||||
echo "--- Admin (followed) events ---"
|
||||
|
||||
# Kind 1 (text notes) — 100 events spread over 365 days
|
||||
bulk_post 1 "Admin text note" 100 365
|
||||
|
||||
# Kind 7 (reactions) — 50 events spread over 180 days
|
||||
bulk_post 7 "+" 50 180
|
||||
|
||||
# Kind 9734 (zap requests) — 30 events spread over 90 days
|
||||
bulk_post 9734 "Zap request" 30 90
|
||||
|
||||
# Kind 30023 (long-form articles) — 20 events spread over 365 days
|
||||
bulk_post 30023 "Long form article content for testing the cleanup page with some substantial text to make the events larger and more realistic" 20 365
|
||||
|
||||
# Kind 3 (contact lists) — 10 events spread over 365 days
|
||||
bulk_post 3 '{"contacts":[]}' 10 365
|
||||
|
||||
# Kind 0 (profiles) — 5 events spread over 365 days
|
||||
for i in $(seq 1 5); do
|
||||
ts=$(( NOW - (i * 365 * 86400 / 5) ))
|
||||
post_event 0 "{\"name\":\"admin_$i\",\"display_name\":\"Admin User $i\",\"about\":\"Test profile $i\"}" "$ts"
|
||||
done
|
||||
|
||||
echo " → Admin done: $POSTED posted, $FAILED failed"
|
||||
echo ""
|
||||
|
||||
# ═══════════════════════════════════════════════════════════════════════
|
||||
# RANDOM (NON-FOLLOWED) EVENTS — bulk of the data
|
||||
# ═══════════════════════════════════════════════════════════════════════
|
||||
|
||||
echo "--- Random (non-followed) events ---"
|
||||
|
||||
# Kind 1 (text notes) — 400 events spread over 365 days, 10 different authors
|
||||
bulk_post_random 1 "Random text note" 400 365
|
||||
|
||||
# Kind 7 (reactions) — 150 events spread over 180 days
|
||||
bulk_post_random 7 "+" 150 180
|
||||
|
||||
# Kind 9734 (zap requests) — 80 events spread over 90 days
|
||||
bulk_post_random 9734 "Zap request" 80 90
|
||||
|
||||
# Kind 30023 (long-form articles) — 50 events spread over 365 days
|
||||
bulk_post_random 30023 "Long form article from random user with some substantial content for testing the cleanup page event deletion functionality" 50 365
|
||||
|
||||
# Kind 3 (contact lists) — 30 events spread over 365 days
|
||||
bulk_post_random 3 '{"contacts":[]}' 30 365
|
||||
|
||||
# Kind 0 (profiles) — 20 events spread over 365 days
|
||||
for i in $(seq 1 20); do
|
||||
author_sk="${RANDOM_SKS[$(( (i - 1) % ${#RANDOM_SKS[@]} ))]}"
|
||||
ts=$(( NOW - (i * 365 * 86400 / 20) ))
|
||||
post_event 0 "{\"name\":\"random_$i\",\"display_name\":\"Random User $i\",\"about\":\"Test profile $i\"}" "$ts" "$author_sk"
|
||||
done
|
||||
|
||||
# Kind 6 (reposts) — 30 events spread over 60 days
|
||||
bulk_post_random 6 "Repost content" 30 60
|
||||
|
||||
# Kind 9735 (zap receipt) — 20 events spread over 30 days
|
||||
bulk_post_random 9735 "Zap receipt" 20 30
|
||||
|
||||
echo " → Random done: $POSTED posted, $FAILED failed"
|
||||
echo ""
|
||||
|
||||
# ═══════════════════════════════════════════════════════════════════════
|
||||
# SUMMARY
|
||||
# ═══════════════════════════════════════════════════════════════════════
|
||||
|
||||
echo "=== Done! ==="
|
||||
echo " Total posted: $POSTED"
|
||||
echo " Total failed: $FAILED"
|
||||
echo ""
|
||||
echo "Now open http://127.0.0.1:8088/index.php and click 'Cleanup' in the nav."
|
||||
echo ""
|
||||
echo "Suggested tests:"
|
||||
echo " 1. Preview: non-follows, kinds=1, max_age=90"
|
||||
echo " → should match random kind-1 events older than 90 days"
|
||||
echo " 2. Preview: non-follows, kinds=1,7, max_age=30"
|
||||
echo " → should match random kind-1/7 events older than 30 days"
|
||||
echo " 3. Preview: follows, kinds=1, max_age=90"
|
||||
echo " → should match admin kind-1 events older than 90 days"
|
||||
echo " 4. Preview: all, kinds=0"
|
||||
echo " → should match all kind-0 (profiles)"
|
||||
echo " 5. Preview: non-follows, kinds=30023, max_age=30"
|
||||
echo " → should match old random long-form articles"
|
||||
echo " 6. Save a query, then execute it"
|
||||
echo " 7. Check the kind breakdown to see size distribution"
|
||||
@@ -89,7 +89,7 @@ get_subscription_count() {
|
||||
return
|
||||
fi
|
||||
|
||||
sqlite3 "$db_file" "SELECT COUNT(*) FROM subscriptions WHERE event_type='created' AND ended_at IS NULL;" 2>/dev/null || echo "0"
|
||||
psql -d crelay "SELECT COUNT(*) FROM subscriptions WHERE event_type='created' AND ended_at IS NULL;" 2>/dev/null || echo "0"
|
||||
}
|
||||
|
||||
# Test 1: Basic Connectivity
|
||||
@@ -260,14 +260,14 @@ echo "[INFO] Checking database integrity..."
|
||||
db_file=$(find . -name "*.db" -type f 2>/dev/null | head -1)
|
||||
if [ -n "$db_file" ]; then
|
||||
# Check if database is accessible
|
||||
if sqlite3 "$db_file" "PRAGMA integrity_check;" 2>/dev/null | grep -q "ok"; then
|
||||
if psql -d crelay "PRAGMA integrity_check;" 2>/dev/null | grep -q "ok"; then
|
||||
print_result "PASS" "Database integrity check passed"
|
||||
else
|
||||
print_result "FAIL" "Database integrity check failed"
|
||||
fi
|
||||
|
||||
# Check subscription table structure
|
||||
if sqlite3 "$db_file" "SELECT COUNT(*) FROM subscriptions;" &>/dev/null; then
|
||||
if psql -d crelay "SELECT COUNT(*) FROM subscriptions;" &>/dev/null; then
|
||||
print_result "PASS" "Subscription table is accessible"
|
||||
else
|
||||
print_result "FAIL" "Subscription table is not accessible"
|
||||
|
||||
Reference in New Issue
Block a user