Skip to content

Firehose phase 2: follows hose (kind 3) + relay-URL harvesting#10

Merged
melvincarvalho merged 1 commit into
gh-pagesfrom
issue-9-follows-hose
Jun 17, 2026
Merged

Firehose phase 2: follows hose (kind 3) + relay-URL harvesting#10
melvincarvalho merged 1 commit into
gh-pagesfrom
issue-9-follows-hose

Conversation

@melvincarvalho

Copy link
Copy Markdown
Contributor

Closes #9. Phase 2 of the firehose rework (after #7) — adds the follows hose and retires the legacy raw-upsert path for kind 3.

What

  • src/hoses/event.js — extract the shared structural + schnorr-signature check (eventId, verifySignature) every hose uses; the profiles hose now delegates to it (DRY, −18 lines there).
  • src/hoses/follows.js (kind 3):
    • Verifies the signature (kind-3 content is optional / free-form, so — unlike profiles — it is not required to be JSON).
    • Derives the social-graph shape { pubkey, follows:[hex…], created_at, count } from p tags (64-hex, lowercased, deduped). This is the shape followerCount (in-degree) and enrichCounts need.
    • Latest-wins upsert — the legacy followshose blindly replaceOne'd, so an out-of-order older contact list could clobber a newer one.
    • Owns its indexes: pubkey, follows (reverse lookup), created_at.
    • Relay-URL harvesting: parses the legacy relay map in kind-3 content, canonicalizes (trailing slash on origins; ws/wss only), and $setOnInserts into the relays directory — discovery only, never overwrites health metrics, best-effort (never fails ingest).
  • src/indexer.js: register the follows hose; LEGACY_KINDS drops to [10002]. The HOSES switch removes kind 3 from the legacy set automatically, so HOSES=profiles,follows is now meaningful.

Why it's also a fix

The phase-1 legacy fallback wrote raw kind-3 events for kind 3, which have no top-level follows array — so follower counts didn't accrue for them. Routing kind 3 through the derived-shape hose fixes in-degree.

Verification

  • npm test34/34 (new follows-hose tests: verify, wrong kind, tampered, malformed; parseFollows dedupe/hex; canonicalizeRelayUrl; relayUrlsFrom; plan tests updated for hose-owned kind 3).
  • Integration smoke vs Mongo: derived doc stored (no raw fields), latest-wins keeps the newest list, stale rejected, a new relay URL harvested as {relay} only, and a pre-existing relay's online/uptime left untouched by the harvest.

Out of scope

Relay-lists hose (kind 10002) — phase 3 · relay-health prober — phase 4 · deploy/retire legacy server hoses — phase 5.

- src/hoses/event.js: extract the shared structural + schnorr-signature
  check (eventId, verifySignature); profiles hose refactored to use it.
- src/hoses/follows.js (kind 3): verify signature, derive the social-graph
  shape { pubkey, follows:[hex…], created_at, count } from p tags (64-hex,
  lowercased, deduped), latest-wins upsert (the legacy followshose blindly
  replaced — an out-of-order older list could clobber a newer one). Owns
  its indexes (pubkey, follows, created_at). Harvests relay URLs from the
  legacy relay map in kind-3 content into the relays directory via
  $setOnInsert (discovery only — never overwrites health metrics;
  best-effort, never fails ingest).
- src/indexer.js: register the follows hose; LEGACY_KINDS drops to [10002].
  The switch removes kind 3 from the legacy set automatically.
- tests: new follows-hose tests (verify/parse/harvest/canonicalize);
  plan tests updated for the now-hose-owned kind 3.

Fixes in-degree for kind-3 events the legacy raw-upsert path wrote without
a top-level follows array. npm test 34/34.

Closes #9
@melvincarvalho
melvincarvalho merged commit dc3bc86 into gh-pages Jun 17, 2026
@melvincarvalho
melvincarvalho deleted the issue-9-follows-hose branch June 17, 2026 08:56
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Firehose phase 2: follows hose (kind 3) + relay-URL harvesting

1 participant