Docs improvements

This commit is contained in:
Jack Kingsman
2026-04-17 10:24:45 -07:00
parent 39f5bb2b51
commit ad0e398704
3 changed files with 12 additions and 6 deletions

View File

@@ -179,7 +179,9 @@ Outgoing DMs send once immediately, then may retry up to 2 more times in the bac
ACKs are not a contact-route source. They drive message delivery state and may appear in analytics/detail surfaces, but they do not update `direct_path*` or otherwise influence route selection for future sends.
**Channel messages**: Flood messages echo back through repeaters. Repeats are identified by the database UNIQUE constraint on `(type, conversation_key, text, sender_timestamp)` — when an INSERT hits a duplicate, `_handle_duplicate_message()` in `packet_processor.py` adds the new path and, for outgoing messages only, increments the ack count. Incoming repeats add path data but do not change the ack count. There is no timestamp-windowed matching; deduplication is exact-match only.
**Channel messages**: Flood messages echo back through repeaters. Repeats are identified by the database UNIQUE constraint `idx_messages_dedup_null_safe` on `(type, conversation_key, text, COALESCE(sender_timestamp, 0))` where `type = 'CHAN'` — when an INSERT hits a duplicate, `_handle_duplicate_message()` in `packet_processor.py` adds the new path and, for outgoing messages only, increments the ack count. Incoming repeats add path data but do not change the ack count. There is no timestamp-windowed matching; deduplication is exact-match only.
**Incoming direct messages**: A separate unique index `idx_messages_incoming_priv_dedup` on `(type, conversation_key, text, COALESCE(sender_timestamp, 0), COALESCE(sender_key, ''))` where `type = 'PRIV' AND outgoing = 0` deduplicates incoming DMs. The additional `sender_key` term (added in migration 056) distinguishes room-server posts from different senders that arrive in the same second with identical text.
This message-layer echo/path handling is independent of raw-packet storage deduplication.

View File

@@ -140,8 +140,8 @@ app/
### Echo/repeat dedup
- Channel message uniqueness: `(type, conversation_key, text, sender_timestamp)`.
- Incoming PRIV message uniqueness: `(type, conversation_key, text, COALESCE(sender_timestamp, 0), COALESCE(sender_key, ''))``sender_key` was added in migration 056 to distinguish room-server posts from different senders in the same second.
- Channel message uniqueness (`idx_messages_dedup_null_safe`): `(type, conversation_key, text, COALESCE(sender_timestamp, 0))` where `type = 'CHAN'`.
- Incoming PRIV message uniqueness (`idx_messages_incoming_priv_dedup`): `(type, conversation_key, text, COALESCE(sender_timestamp, 0), COALESCE(sender_key, ''))` where `type = 'PRIV' AND outgoing = 0``sender_key` was added in migration 056 to distinguish room-server posts from different senders in the same second.
- Duplicate insert is treated as an echo/repeat: the new path (if any) is appended, and the ACK count is incremented only for outgoing channel messages. Incoming direct messages with the same dedup identity also collapse onto one stored row, with later observations merging path data instead of creating a second DM.
### Raw packet dedup policy

View File

@@ -237,9 +237,13 @@ async def on_new_contact(event: "Event") -> None:
logger.debug("New contact: %s", public_key[:12])
contact_upsert = ContactUpsert.from_radio_dict(public_key.lower(), payload, on_radio=False)
# Intentionally do not set last_seen here: NEW_CONTACT fires from the
# radio's stored contact DB, not an RF observation. last_seen means
# "last time we heard this pubkey on RF".
# Intentionally do not set first_seen or last_seen here: NEW_CONTACT
# fires from the radio's stored contact DB, not an RF observation.
# Both first_seen and last_seen are RF-only timestamps — they track
# the first and most recent time we actually heard this pubkey over
# the air (adverts, messages, path updates). Contacts synced from the
# radio's internal DB without any RF activity stay NULL until a real
# RF observation fills them in.
await ContactRepository.upsert(contact_upsert)
promoted_keys = await promote_prefix_contacts_for_contact(
public_key=public_key,