Skip to content

fix(relay): make Telegram broker pairing and reconnects resilient#59

Merged
zikolach merged 4 commits into
mainfrom
fix/resilient-telegram-pairing
May 16, 2026
Merged

fix(relay): make Telegram broker pairing and reconnects resilient#59
zikolach merged 4 commits into
mainfrom
fix/resilient-telegram-pairing

Conversation

@zikolach
Copy link
Copy Markdown
Owner

Summary

  • Keep Telegram pairing links retryable when the Pi client/socket is temporarily unavailable instead of consuming the pending pairing too early.
  • Hydrate broker-registered routes from persisted Telegram bindings so commands like /progress quiet keep working after broker/client reconnects.
  • Add broker socket reconnect/resync behavior for registered routes after broker restart or socket recreation.
  • Clear stale local status warnings after successful lifecycle/binding-authority recovery so the relay status line does not remain noisy.

Validation

  • npm run typecheck
  • npm test -- tests/broker-namespace.test.ts tests/broker-process.test.ts tests/relay/telegram-route-binding.test.ts tests/integration.test.ts
  • npx vitest run --testTimeout=15000

Live verification

  • Reproduced pairing/command inconsistency after broker restart.
  • Verified fresh Telegram pairing succeeds after broker restart.
  • Observed follow-up prompt/image prompt routing through the paired Telegram chat.

Copilot AI review requested due to automatic review settings May 16, 2026 09:26
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR improves the resilience of the Telegram relay broker/client interaction by making pairing links retryable during transient Pi connectivity issues, rehydrating route bindings from persisted state after reconnects, and adding broker socket reconnect + route resync behavior so Telegram commands keep routing correctly across broker restarts.

Changes:

  • Prevents consuming Telegram pending pairings until after successful local approval and client availability checks, allowing users to retry valid links.
  • Hydrates broker-registered routes with persisted Telegram binding metadata when the client route registration is stale/missing binding details.
  • Adds broker socket reconnect/backoff and route resync logic, plus clears stale local status warnings after recovery.

Reviewed changes

Copilot reviewed 11 out of 11 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
tests/relay/telegram-route-binding.test.ts Adds unit coverage for persisted Telegram binding hydration behavior.
tests/broker-process.test.ts Adds regression test ensuring broker hydrates stale route registrations from persisted bindings.
tests/broker-namespace.test.ts Adds reconnect/resync test coverage for broker socket recreation scenarios.
extensions/relay/runtime/extension-runtime.ts Adds clearLocalStatus wiring and clears lifecycle warnings after successful recovery.
extensions/relay/core/types.ts Extends SessionRouteActions with optional clearLocalStatus.
extensions/relay/broker/tunnel-runtime.ts Implements reconnect scheduling/backoff and resyncs registered routes after reconnect.
extensions/relay/broker/telegram-route-binding.ts Introduces helper to hydrate routes with persisted Telegram binding metadata.
extensions/relay/broker/process.js Makes Telegram pairing retryable and hydrates incoming route registrations with persisted bindings.
extensions/relay/adapters/telegram/runtime.ts Clears binding-authority local status when state is healthy again.
extensions/relay/adapters/slack/runtime.ts Clears binding-authority local status when delivery is authorized again.
extensions/relay/adapters/discord/runtime.ts Clears binding-authority local status when delivery is authorized again.

Comment thread extensions/relay/broker/telegram-route-binding.ts Outdated
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 11 out of 11 changed files in this pull request and generated no new comments.

Comments suppressed due to low confidence (2)

extensions/relay/adapters/slack/runtime.ts:182

  • relay-binding-authority local status is only cleared when an active binding is returned. If the previous call set a state-unavailable warning, then later outcomes like revoked/moved/missing will leave that stale warning visible even though the state is now readable. Consider clearing relay-binding-authority for any outcome where outcome.kind !== "state-unavailable" (e.g., before the revoked/moved/... cleanup or as a final else branch).
    if (authorityOutcomeAllowsDelivery(outcome) && "status" in outcome.binding) {
      route.actions.clearLocalStatus?.("relay-binding-authority");
      return outcome.binding;
    }
    if (outcome.kind === "state-unavailable") route.actions.setLocalStatus?.("relay-binding-authority", bindingAuthorityDiagnostic(outcome) ?? "Relay state is unavailable; protected messenger delivery was suppressed.");
    if (outcome.kind === "revoked" || outcome.kind === "moved" || outcome.kind === "state-unavailable") {
      this.ownedBindingSessionKeys.delete(route.sessionKey);
      this.recentBindingBySessionKey.delete(route.sessionKey);
    }
    return undefined;

extensions/relay/adapters/discord/runtime.ts:144

  • relay-binding-authority local status is cleared only when an active binding is returned. If a prior call set the state-unavailable warning, subsequent non-state-unavailable outcomes (e.g. revoked, moved, missing) will keep the stale warning even though the state has recovered. Consider clearing relay-binding-authority whenever outcome.kind !== "state-unavailable" (before returning/cleanup).
    if (authorityOutcomeAllowsDelivery(outcome) && "status" in outcome.binding) {
      route.actions.clearLocalStatus?.("relay-binding-authority");
      return outcome.binding;
    }
    if (outcome.kind === "state-unavailable") route.actions.setLocalStatus?.("relay-binding-authority", bindingAuthorityDiagnostic(outcome) ?? "Relay state is unavailable; protected messenger delivery was suppressed.");
    if (outcome.kind === "revoked" || outcome.kind === "moved" || outcome.kind === "state-unavailable") this.recentBindingBySessionKey.delete(route.sessionKey);
    return undefined;
  }

@zikolach zikolach merged commit 96b2fe7 into main May 16, 2026
6 checks passed
@zikolach zikolach deleted the fix/resilient-telegram-pairing branch May 16, 2026 10:15
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.

2 participants