Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 26 additions & 4 deletions plugins/platforms/photon/sidecar/index.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -343,6 +343,31 @@ async function normalizeEvent(space, message) {
}
}

function inboundStreamErrorMessage(e) {
const msg = e && e.message ? e.message : String(e);
let out = "photon-sidecar: inbound stream errored — restarting: " + msg;

// The Spectrum SDK surfaces Photon cloud CatchUpEvents failures as an
// iMessage internal error. Local Hermes allowlists cannot cause or fix this:
// inbound messages stop before they reach the gateway. Add an explicit hint
// so operators know to retry/restart or escalate to Photon support instead
// of chasing PHOTON_ALLOWED_USERS / pairing configuration.
const details = String(e?.cause?.details || e?.details || "");
const path = String(e?.cause?.path || e?.path || "");
const code = String(e?.code || "");
if (
path.includes("EventService/CatchUpEvents") ||
details.includes("Unknown server error occurred") ||
(code === "internalError" && msg.includes("Unknown server error"))
) {
out +=
" | Photon Spectrum CatchUpEvents returned an internal server error; " +
"this is upstream of Hermes, so inbound iMessages may not be delivered " +
"until Photon recovers or the stream is re-established.";
Comment on lines +363 to +366
}
return out;
}

// spectrum-ts handles in-session gRPC reconnects internally, but if the async
// iterator itself throws or ends, this consumer would stop forever. Wrap it in
// a re-subscribe loop with capped exponential backoff + jitter so inbound
Expand All @@ -365,10 +390,7 @@ async function normalizeEvent(space, message) {
}
console.error("photon-sidecar: inbound stream ended — re-subscribing");
} catch (e) {
console.error(
"photon-sidecar: inbound stream errored — restarting: " +
(e && e.message ? e.message : String(e))
);
console.error(inboundStreamErrorMessage(e));
}
await new Promise((r) =>
setTimeout(r, backoff + Math.random() * backoff * 0.2)
Expand Down
9 changes: 9 additions & 0 deletions tests/plugins/platforms/photon/test_spectrum_patch.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,15 @@ def test_sidecar_applies_spectrum_patch_before_importing_sdk() -> None:
assert index.index("patchSpectrumTs();") < index.index('await import("spectrum-ts")')


def test_sidecar_labels_catchup_internal_errors_as_upstream_photon() -> None:
"""Photon cloud stream failures should not look like local auth problems."""
index = Path("plugins/platforms/photon/sidecar/index.mjs").read_text(encoding="utf-8")
assert "function inboundStreamErrorMessage" in index
assert "EventService/CatchUpEvents" in index
assert "this is upstream of Hermes" in index
assert "PHOTON_ALLOWED_USERS" in index
Comment on lines +23 to +26


def test_spectrum_patch_preserves_text_when_single_attachment(tmp_path: Path) -> None:
"""The sidecar dependency patch must turn text+one attachment into group content."""
dist = tmp_path / "node_modules" / "spectrum-ts" / "dist"
Expand Down