From 167954b4ba90b779fb115f648eb26b35b286787f Mon Sep 17 00:00:00 2001 From: Anthony Ettinger Date: Mon, 26 Oct 2026 14:50:13 +0000 Subject: [PATCH] dev2 edge: per-site retry holds requests across an app restart; on for group.call A site with "retry" gets its own reverse_proxy with lb_try_duration, so Caddy keeps dialing the app while a deploy restarts it instead of answering 502. group.call needs it: Telnyx webhooks drive live calls. Co-Authored-By: Claude Opus 5.5 --- dev2/dev2-edge | 7 ++++++- dev2/edge/edge.json | 4 ++-- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/dev2/dev2-edge b/dev2/dev2-edge index 15f71ed..12cd4be 100755 --- a/dev2/dev2-edge +++ b/dev2/dev2-edge @@ -156,7 +156,12 @@ def caddy_site(site, s): lines.append("\tencode gzip") if site.get("access_log"): lines += ["\tlog {", f"\t\toutput file /var/log/caddy/{site['hosts'][0]}.access.log", "\t}"] - if "proxy" in site: + if "proxy" in site and site.get("retry"): + # While the app restarts (a deploy), hold the request and keep dialing instead of + # answering 502: webhooks that drive live calls (Telnyx) must not fail mid-call. + lines += [f"\treverse_proxy 127.0.0.1:{int(site['proxy'])} {{", "\t\theader_up X-Real-IP {remote_host}", + "\t\tstream_close_delay 1h", f"\t\tlb_try_duration {site['retry']}", "\t\tlb_try_interval 250ms", "\t}"] + elif "proxy" in site: lines.append(f"\timport edge_proxy {int(site['proxy'])}") elif "root" in site: lines += [f"\troot * {site['root']}", "\tfile_server"] diff --git a/dev2/edge/edge.json b/dev2/edge/edge.json index 25c00d9..465d888 100644 --- a/dev2/edge/edge.json +++ b/dev2/edge/edge.json @@ -18,8 +18,8 @@ { "hosts": ["pit.world"], "proxy": 8787, "max_body": "1MiB" }, { "hosts": ["www.pit.world"], "redirect": "https://pit.world{uri}" }, { "hosts": ["ad.network.pit.world"], "proxy": 8800, "max_body": "1MiB", "gzip": true }, - { "hosts": ["group.call.pit.world"], "proxy": 8810, "max_body": "1MiB", - "//": "group.call (moshcoder/group.call): no gzip, so the room page's server-sent events are not held back" }, + { "hosts": ["group.call.pit.world"], "proxy": 8810, "max_body": "1MiB", "retry": "20s", + "//": "group.call (moshcoder/group.call): no gzip, so the room page's server-sent events are not held back; retry holds Telnyx webhooks across a deploy instead of 502" }, { "hosts": ["*.*.pit.world", "*.*.*.pit.world"], "proxy": 8787, "max_body": "30MiB", "gzip": true, "//": "pit-proxy: every .pit.world (+ bbs./social.) relayed by the pit.world app; one Let's Encrypt certificate per name from pit-proxy-cert" }, { "hosts": ["built.indie"], "proxy": 8798, "max_body": "1MiB", "moshpit": true },