Skip to content

Complete Reddit bridge - #3

Open
Fizzadar wants to merge 9 commits into
mainfrom
feature/complete-reddit-bridge
Open

Fizzadar wants to merge 9 commits into
mainfrom
feature/complete-reddit-bridge

Conversation

@Fizzadar

@Fizzadar Fizzadar commented Oct 8, 2026

Copy link
Copy Markdown
Contributor

No description provided.

@Fizzadar

Fizzadar commented Oct 9, 2026

Copy link
Copy Markdown
Contributor Author

@indent review please

@indent

indent Bot commented Oct 9, 2026 •

Copy link
Copy Markdown

Issues

All clear! No issues remaining. 🎉

10 issues already resolved
  • With bridge.split_portals false, shared group portals with nil saved State (created by main, via CreateGroup, or before the first ChatResync) make savedRoomPortal error before sync state is merged. Sync then retries forever, and after the upgrade's full resync the whole account stops bridging. (fixed by commit 5846ee3)
    Found by Indent Review Agent
  • handleSync aborts the whole batch on any per-room or per-event error and runSync retries it forever, so one deterministic failure (unsupported redaction target, unknown chat type, non-t2_ user, permanent reaction image 404) leaves the login in TRANSIENT_DISCONNECT and stops all bridging. (fixed by commit 429c6fb)
    Found by Indent Review Agent
  • In FetchMessages, one event that fails conversion (unsupported msgtype, edit, media download failure, reaction image failure) returns an error for the whole page, so catch-up and backward backfill never make progress past it. (fixed by commit 429c6fb)
    Found by Indent Review Agent
  • Sync now advances the cursor even on transient failures (network, 5xx, 429, DB errors in room-state resolution or GetEvent), so those messages, redactions and unhides are lost permanently. Previously they were retried. (fixed by commit 04a7cd2)
    Found by Indent Review Agent
  • Backfill stores an error placeholder under the real message ID for transient media failures (download timeout, 5xx, 429, upload failure), so the image is permanently replaced and never retried. (fixed by commit 04a7cd2)
    Found by Indent Review Agent
  • Non-split deployments: DMs that main saved as shared (receiver-less) portals fail the ownership check on every sync and now silently stop bridging. (fixed by commit 91979f5)
    Found by Indent Review Agent
  • Every room with an unknown chat type triggers an unfiltered full account sync on each poll until its portal state is saved, which can cause load and rate limiting. (fixed by commit 91979f5)
    Found by Indent Review Agent
  • Only 404/410 are classified as permanent. Other permanent 4xx responses (403 on GetEvent or media, redirect rejections, upload rejections) are retried forever, so one such event stalls sync for the whole account and fails every backfill retry. (fixed by commit 91979f5)
    Found by Indent Review Agent
  • Every 403 is classified as permanent, but Reddit's edge returns temporary 403 blocks. During a block, redactions are dropped, reaction images fall back to text, and backfilled media or reactions are skipped or replaced, all permanently. (fixed by commit 144118b)
    Found by Indent Review Agent
  • Failures not classified as permanent retry the whole sync batch with no attempt or time limit, and the held cursor stops every chat on the account. There is no point at which the offending event is skipped. (fixed by commit 144118b)
    Found by Indent Review Agent

CI Checks

All CI checks passed on da909c6.

Review agents

Select any unchecked box below to run or rerun that agent.

Passed (1)
  • Indent Review Agent · The edge-403 nit is fixed; one residual nit: unclassified permanent failures retry with no limit.
Full results

Indent Review Agent

  • Summary: The edge-403 nit is fixed; one residual nit: unclassified permanent failures retry with no limit.
  • Last ran on commit: da909c65
  • Latest result
    {
      "summary": "The edge-403 nit is fixed; one residual nit: unclassified permanent failures retry with no limit.",
      "findings": [
        {
          "fix": "Track consecutive failures of the same sync batch (same `since` cursor). After N attempts, or a time budget, switch that pass into skip mode: log and skip each room or event that still fails, instead of retrying the whole batch. That keeps edge blocks retryable for a while without letting one deterministic failure hold the account forever.",
          "line": 89,
          "path": "pkg/connector/chatsync.go",
          "issue": "The author's claim checks out against the code.\n- `isPermanentHTTPError` returns true for 404/410 always.\n- For any other 4xx it returns true only when `httpErr.RespError != nil`. In mautrix v0.30, `ParseErrorResponse` sets `RespError` to nil when the body has no `errcode` (client.go:766-775), so HTML or empty edge blocks retry.\n- 401/`M_UNKNOWN_TOKEN`/`M_MISSING_TOKEN` (via `isUnauthorized`), 408 and 429 are excluded. `M_LIMIT_EXCEEDED` normally arrives as 429.\n- Reaction images become unbridgeable only on 404/410 (`isGoneStatus`, emoji.go:75).\n- The redirect rejection is a plain error again, so it retries.\n\nThe remaining risk is that every failure the classifier doesn't recognise as permanent retries the whole sync batch with no upper limit. Because the cursor is held, one such failure stops every chat on the account until it clears. Examples:\n- An off-host or long redirect from i.redd.it for a catalogued reaction.\n- A permanent 4xx without a JSON errcode from the media CDN or i.redd.it.\n- A deterministic Beeper `Bot.UploadMedia` rejection of a reaction image.\nThere is no attempt count or time budget after which the offending event is skipped. This is unlikely with today's static reaction assets, so I'm reporting it as a nit.",
          "title": "Failures the classifier doesn't recognise as permanent still retry with no limit and hold the cursor",
          "severity": "nit"
        }
      ]
    }

@indent

indent Bot commented Oct 9, 2026

Copy link
Copy Markdown

Review started on 18c7892. Findings will show up in the banner comment.

Comment thread pkg/connector/roomstate.go Outdated
Comment thread pkg/connector/chatsync.go Outdated
Comment thread pkg/connector/backfill.go
Comment thread pkg/connector/chatsync.go
Comment thread pkg/connector/backfill.go
Comment thread pkg/connector/roomstate.go
Comment thread pkg/connector/roomstate.go Outdated
Comment thread pkg/connector/unbridgeable.go
Comment thread pkg/connector/unbridgeable.go Outdated
Comment thread pkg/connector/chatsync.go
Remove the embedded browser and drive password, verification, and OTP through bridgev2 login steps. Preserve structured login errors without exposing response bodies, and update the bridge dependencies.
Include pending-room previews and unfiltered reactions in sync, use the retained-media download endpoint, and paginate thread children by native sequence. Expose reaction relations and the native reaction catalog for the connector.
Project native state into stable DM and group portal identities, recover missing snapshots once per sync pass, and preserve pending and hidden message requests. Retain the sync cursor on retryable failures, skip only unbridgeable data, and refresh sessions without changing accounts.
Translate reply and thread targets through bridge mappings and use stable transaction IDs for sends and echoes. Transfer supported images and thumbnails with size, MIME, and encryption checks, and advertise the observed text and attachment capabilities.
Import the Reddit reaction palette, persist provider reaction IDs, and validate native deletion proofs before emitting removals. Retry transient media and edge failures while falling back for permanently unavailable reaction images.
Follow provider cursors through short and state-only pages, seek exact bridge anchors, and return historical reactions without mutating local mappings. Preserve deleted content as tombstones and use placeholders for unbridgeable messages while retrying transient failures.
Translate receipt targets without widening private or thread-specific receipts. Track native typing snapshots to emit stopped indicators and bound stale typing notifications.
Use signed direct-media identities with authenticated downloads and verified reupload for encrypted attachments. Allow native group invites, removals, and departures while enforcing portal ownership and DM restrictions.
Keep local state and development artifacts out of the image, and generate configuration as the same configured user that runs the bridge. Document persistent state, configuration, login, media, and the native client API.
@Fizzadar
Fizzadar force-pushed the feature/complete-reddit-bridge branch from 144118b to da909c6 Compare October 9, 2026 20:48
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

1 participant