Skip to content

Commit 5ef19b3

Browse files
Aditya-eddyclaude
andauthored
feat(async-config-poll): add BLOCK_BOOT_ON_WATCH to block boot on the config watch (#148)
Env-gated (replay-only) mode: init() does a synchronous GET /v1/buckets/app-config?watch=true and blocks boot until it returns, the shape a synchronously-blocking config client hits. Lets the keploy async-config-poll e2e reproduce the boot deadlock — the old anchor-hold async engine parks the poll (app never ready) while the value-epoch engine serves the startup epoch immediately (app boots). When unset (default / record path, and the periodic + httppoll scenarios) the watch keeps running on the background daemon, unchanged. Pairs with keploy/keploy#4379. Signed-off-by: Aditya Sharma <aditya282003@gmail.com> Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
1 parent 4b3b4fc commit 5ef19b3

1 file changed

Lines changed: 18 additions & 2 deletions

File tree

async-config-poll/src/main/java/com/example/asyncconfig/config/ConfigWatchService.java

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -58,8 +58,24 @@ public void init() {
5858
log.info("ConfigWatchService initialized; featuresEnabled={} appConfigVersion={}",
5959
featuresEnabled, appConfigVersion);
6060

61-
// (2) Background watch long-poll.
62-
startWatchPoller();
61+
// (2) Config watch. BLOCK_BOOT_ON_WATCH (replay-only) makes boot BLOCK
62+
// synchronously on a watch=true long-poll — the Flipkart shape. With the
63+
// old anchor-hold async engine this poll is parked at replay (its
64+
// delivery anchored past the reachable window), so the app never becomes
65+
// ready = boot deadlock; the value-epoch engine serves the startup epoch
66+
// immediately so boot proceeds. When unset (the record path), the watch
67+
// runs on a background daemon and does not block boot.
68+
if ("true".equalsIgnoreCase(System.getenv("BLOCK_BOOT_ON_WATCH"))) {
69+
String url = baseUrl + "/v1/buckets/app-config?watch=true&version=" + appConfigVersion;
70+
log.info("BLOCK_BOOT_ON_WATCH: blocking boot on synchronous config watch {}", url);
71+
@SuppressWarnings("unchecked")
72+
Map<String, Object> resp = rt.getForObject(url, Map.class);
73+
log.info("BLOCK_BOOT_ON_WATCH: synchronous config watch returned (version now {}); boot continues",
74+
intFrom(resp, "version", appConfigVersion));
75+
} else {
76+
// Background watch long-poll (record path).
77+
startWatchPoller();
78+
}
6379
}
6480

6581
private void startWatchPoller() {

0 commit comments

Comments
 (0)