Skip to content

Fix asynchronous Retry via Relay fallback - #149

Merged
torlando-tech merged 25 commits into
mainfrom
fix/ios-issue-146-propagation-fallback
Aug 6, 2026
Merged

Fix asynchronous Retry via Relay fallback#149
torlando-tech merged 25 commits into
mainfrom
fix/ios-issue-146-propagation-fallback

Conversation

@torlando-tech

Copy link
Copy Markdown
Owner

Summary

  • pass the Retry via Relay policy into the shipping embedded-Python send path when an opportunistic message is queued
  • handle later asynchronous opportunistic failure in the backend by repacking and requeuing the same LXMessage once as propagated, preserving its canonical hash and structured payload
  • distinguish propagation-node acceptance (sent) from recipient delivery (delivered), persist the propagated method, and emit terminal failure when propagation is unavailable or fails
  • carry effective transport independently from lifecycle state, including a direct delivered callback with no observed intermediate sent, and keep an already-open detail page synchronized

Fixes #146.

Verification

  • regression-first focused suite before production changes: 8 tests executed, 7 failed for the missing asynchronous fallback/seam behavior, 1 passed
  • propagation-representation regression before its fix: 8 tests executed, 1 failed because propagation_packed remained absent, 7 passed
  • shipping LXMF 0.9.9 lock regression before its fix: 9 tests executed, 1 failed because the failure callback synchronously waited on the router's non-reentrant outbound lock, 8 passed
  • runtime-replacement regression before its fix: 10 tests executed, 1 failed because the fallback worker enqueued on a superseded router, 9 passed
  • delivered-method regression before its fix: 11 tests executed, 1 failed because the event lacked effective transport metadata, 10 passed
  • presentation-edge regressions before their fixes: 12 tests executed, 2 failed for no-node method preservation and notification/open-sheet seams, 10 passed
  • lifecycle-arbitration regressions before their fixes: 14 tests executed, 3 failed because sent suppressed recipient proof, deferred fallback ignored authoritative delivery, and canonical detail aliasing was absent
  • linearization regressions before their fixes: 17 tests executed, 4 failed for concurrent lifecycle event ordering, mutation during fallback preparation, atomic final enqueue admission, and missing Swift monotonic/alias defenses
  • recipient-authority regressions before their fixes: 18 tests executed, 2 failed because failed suppressed later recipient proof and buffered proofs lost effective transport metadata
  • pre-alias regressions before their fixes: the public send path emitted an unpersisted propagated delivery proof before returning the canonical hash, then forced a concurrent refresh before alias registration; production now buffers the proof and removes it only after a repository update confirms a matching row changed
  • focused suite at final head: 18 passed; repeated 100/100 runs without failure
  • complete static suite at final head: 243 passed, 1 skipped, 254 subtests passed
  • pinned LXMF 0.9.9 copy/repack probe: shallow copy passed; the primary stayed opportunistic; hash, payload, fields, and propagated bytes were preserved
  • Mac native XCTest compile/run: 19 passed at the initial Swift implementation head; the exact-head native integration test is present, but a later build-for-testing exhausted task-volume storage before reaching Swift test compilation
  • exact-head d1a30ad7 app source compiled with zero compiler errors; the low-space outer-signing failure was completed with the generated entitlements, then exact bridge equality, strict signature verification, installation, launch, and process readback passed
  • CI now explicitly executes Tests.static.test_async_propagation_fallback; exact-head native integration test execution remains pending hosted CI because local task-volume storage prevented the device test bundle from reaching test compilation
  • final app bundle at each installed candidate contained an exact byte-for-byte copy of that candidate's embedded Python bridge
  • sanitized live phone diagnosis of the prior candidate observed 0 sent and 2 delivered events, reproducing the missing-method path without exposing message content or identities

Remaining manual check

  • interactive offline-recipient smoke test on the installed iPhone build should be completed before merge to confirm the configured propagation node accepts the retry in the real network environment

Risk and rollback

The change is limited to the shipping Python LXMF send path and its Swift policy/event-persistence seam. The retry is one-shot, hash-guarded, and fails closed when no propagation node is configured, repacking fails, the hash changes, enqueue fails, or the propagated attempt later fails. Rollback is to revert this PR.

@greptile-apps

greptile-apps Bot commented Aug 5, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

The PR adds one-shot asynchronous propagation fallback for opportunistic sends while preserving the canonical message identity and delivery metadata.

  • Threads the retry-via-relay policy through the shipping Swift-to-Python send path.
  • Requeues asynchronous failures through propagation and distinguishes relay acceptance from recipient delivery.
  • Adds monotonic delivery persistence, effective-transport tracking, alias reconciliation, and open-detail synchronization.
  • Adds focused Python and Swift regressions and includes the new static suite in CI.

Confidence Score: 5/5

The PR appears safe to merge based on the eligible follow-up review scope.

No blocking failure remains in the available follow-up review record.

Important Files Changed

Filename Overview
app/rns_bridge.py Implements one-shot asynchronous propagation fallback with callback arbitration, canonical-hash validation, runtime replacement checks, and explicit lifecycle events.
Sources/ColumbaApp/Services/MessageRepository.swift Persists delivery state and effective method atomically while preventing stale events from downgrading recipient delivery.
Sources/ColumbaApp/ViewModels/MessagingViewModel.swift Passes the fallback policy into sends and reconciles early delivery proofs, optimistic aliases, transport metadata, and open message details.
Sources/PythonBridge/PythonBridge.swift Extends Swift/Python marshalling for fallback policy and effective transport metadata.
Sources/RNSBackendPy/PythonRNSBackend.swift Maps the typed fallback policy and delivery method across the shipping Python backend seam.
Sources/RNSAPI/Protocols/RnsLxmf.swift Adds the optional backend-owned asynchronous fallback operation while preserving compatibility for implementations using the original send requirement.
Sources/ColumbaApp/Services/AppServices.swift Explicitly maps sent, delivered, and failed lifecycle events and persists their effective transport.
Tests/static/test_async_propagation_fallback.py Exercises fallback repacking, callback ordering, lock behavior, runtime replacement, lifecycle arbitration, transport metadata, and Swift seam contracts.

Sequence Diagram

sequenceDiagram
    participant UI as MessagingViewModel
    participant Backend as PythonRNSBackend
    participant Bridge as PythonBridge
    participant LXMF as rns_bridge.py / LXMRouter
    participant Repo as MessageRepository

    UI->>Backend: send opportunistic + propagated fallback policy
    Backend->>Bridge: sendOpportunistic(...)
    Bridge->>LXMF: send_opportunistic(...)
    LXMF-->>UI: queued(canonical hash)
    alt Opportunistic attempt fails asynchronously
        LXMF->>LXMF: repack same LXMessage for propagation
        LXMF->>LXMF: enqueue propagated attempt
        LXMF-->>Repo: sent(method: propagated)
        LXMF-->>Repo: delivered or failed
    else Recipient proof arrives first
        LXMF-->>Repo: delivered(method: effective transport)
        LXMF->>LXMF: cancel deferred fallback
    end
    Repo-->>UI: persist monotonic state and refresh alias/detail
Loading

Reviews (2): Last reviewed commit: "test: fix native delivery proof compilat..." | Re-trigger Greptile

@torlando-tech
torlando-tech merged commit d271778 into main Aug 6, 2026
4 checks passed
@torlando-tech
torlando-tech deleted the fix/ios-issue-146-propagation-fallback branch August 6, 2026 01:23
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.

propagation node fallback

1 participant