Skip to content
GitHubRSS

Package Structure

BigBrotr is organized into five packages, each with a single clear responsibility. This page details the contents and purpose of every package.

Pure domain foundations. Frozen dataclasses representing Nostr concepts with invariants enforced at construction.

ModuleContents
relay.pyRelay — URL validation (RFC 3986), network detection (clearnet/tor/i2p/loki/local), local IP rejection
event.pyEvent — Nostr event with signature, EventRelay — junction model
metadata.pyMetadata — content-addressed with SHA-256 hash, MetadataType enum (7 types), RelayMetadata — junction model
constants.pyNetworkType, ServiceName (StrEnum), EventKind (IntEnum), EVENT_KIND_MAX
service_state.pyServiceState — service checkpoint data, ServiceStateType (StrEnum), ServiceStateDbParams (NamedTuple)

Key patterns:

  • All models use @dataclass(frozen=True, slots=True) for immutability and memory efficiency.
  • All models cache to_db_params() in __post_init__ via a _db_params field (using object.__setattr__ frozen workaround).
  • from_db_params() classmethod reconstructs objects from database tuples with full re-validation.
  • stdlib logging only — no bigbrotr imports.

Infrastructure and lifecycle. Manages the connection pool, database operations, service lifecycle, logging, and metrics.

ModuleContents
pool.pyPool — asyncpg connection pool with retry/backoff and health-checked acquisition. PoolConfig Pydantic model.
brotr.pyBrotr — database facade. _call_procedure() for stored functions, generic query methods: fetch(), fetchrow(), fetchval(), execute(), transaction(). BrotrConfig with BatchConfig and TimeoutsConfig.
base_service.pyBaseService[ConfigT] — abstract base class. run() cycle, run_forever() loop, graceful shutdown. from_yaml()/from_dict() factory methods.
logger.pyLogger — structured key=value logging with JSON output mode. format_kv_pairs() utility.
metrics.pyPrometheus /metrics endpoint. Four metric types: SERVICE_INFO, SERVICE_GAUGE, SERVICE_COUNTER, CYCLE_DURATION_SECONDS.
yaml.pyYAML configuration file loading with environment variable interpolation.

Key patterns:

  • Brotr._pool is private. Services use Brotr methods, never the pool directly.
  • BaseService is generic over ConfigT (a Pydantic BaseModel), enabling type-safe configuration.
  • Pool implements async with context management for automatic cleanup.

Protocol-aware I/O. Each NIP implementation is a “sensor” that produces typed Metadata objects. The package contains shared base classes and two sub-packages.

ModuleContents
base.pyShared base classes for NIP implementations
event_builders.pyNostr event construction for publishing monitoring data
parsing.pyDeclarative field parsing utilities
nip11/Sub-package: nip11.py (main class), data.py (data models), logs.py (result logging), info.py (field extraction)
nip66/Sub-package: nip66.py (main class), data.py, logs.py, plus one module per test: rtt.py, ssl.py, dns.py, geo.py, net.py, http.py

NIP-66 health tests:

TestMetadataTypeMeasures
RTTNIP66_RTTWebSocket round-trip time in milliseconds
SSLNIP66_SSLCertificate validity, expiration, issuer
DNSNIP66_DNSResolution time, IP addresses, DNSSEC
GeoNIP66_GEOCountry, city, ASN, coordinates via GeoIP
NetNIP66_NETAS number, ISP name, network prefix
HTTPNIP66_HTTPHTTP status, headers, redirect chain

NIP-11 produces MetadataType.NIP11_INFO.

Key patterns:

  • Fetch methods never raise exceptions. Always check logs.success on the result.
  • Depends on utils (for transport) and models (for data types). Does not depend on core.

Network and crypto primitives. Stateless helper functions with no business logic.

ModuleContents
protocol.pycreate_client(), connect_relay(), broadcast_events(), is_nostr_relay() — WebSocket client creation and relay connectivity testing.
transport.pyDEFAULT_TIMEOUT, InsecureWebSocketTransport — HTTP/WebSocket transport with SSL fallback and timeout configuration.
http.pyBounded JSON reading and file downloads with size limits.
dns.pyDNS resolution utilities for relay URL validation.
keys.pyload_keys_from_env(), KeysConfig Pydantic model — Nostr key management for event signing and publishing.
parsing.pyModel parsing utilities for data extraction.

Key patterns:

  • All functions are stateless. No class instances, no side effects beyond I/O.
  • SOCKS5 proxy support for Tor/I2P/Lokinet relays.
  • Depends only on models.

Business logic. Six independent services, each inheriting BaseService[ConfigT] and implementing async def run().

ServiceModePurpose
seederOne-shotLoad relay URLs from seed files and known relay lists
finderContinuousDiscover relay URLs from NIP-65 events and public APIs
validatorContinuousTest WebSocket connectivity, promote candidates to relay table
monitorContinuousNIP-11 + NIP-66 health checks, publish kind 10166/30166 events
refresherScheduledOrchestrate materialized view refresh cycles
synchronizerContinuousCursor-based event collection from validated relays

Shared infrastructure in services/common/:

ModuleContents
configs.pyPer-network Pydantic models: ClearnetConfig, TorConfig, I2pConfig, LokiConfig with timeouts, proxy URLs, concurrency limits
queries.py15 domain-specific SQL query functions. Centralized to avoid scattering inline SQL.
mixins.pyChunkProgress (cycle tracking), NetworkSemaphoresMixin (per-network concurrency), GeoReaders (GeoIP database lifecycle)