Skip to content

Commit fbf3a55

Browse files
fix(restheart-mongo): noise Etag/Location + disable ACL cache for time-freeze compat
After fixing the Authorization-header-prefix bug in flow.sh (parent commit), 214 admin-auth calls that previously 401'd now actually mutate state and reach RESTHeart's normal write/read path. That exposed two new categories of record/replay divergence the all-401 recording had hidden: 1) Etag header: RESTHeart auto-stamps a hash on every doc / collection response. body._etag is already in globalNoise, but the same hash also appears as a response header (Etag) — needs to be noised separately. Without it, ~85 of 306 tests fail on header.Etag diff. 2) Location header: POST /_sessions returns Location: /_sessions/<uuid> where the UUID is server-generated. 2 tests fail without noising. Both added to keploy.yml.template's globalNoise.global.header. Separate fix on the compose side: disable mongoAclAuthorizer's cache (`/mongoAclAuthorizer/cache-enabled->false` via RHO). Default is cache-enabled with TTL=5_000ms, backed by Caffeine. Caffeine's internal ticker uses System.nanoTime, which keploy's --freezeTime LD_PRELOAD shim intercepts — so at replay the wall-clock-bound TTL never expires. flow.sh's `sleep 6` between `POST /acl` and the writer-permission test works at record (clock advances, cache reloads the new rule) but is ineffective at replay (cache stuck on whatever it loaded first). Result: writer gets 403 at replay despite recorded 200. Disabling the cache makes ACL rules read-through from mongo on every request — small perf cost in the test environment but eliminates the time-freeze × cache-TTL interaction. Local cell record-pr-replay-pr verified 306/306 PASSED with both fixes in place. Test count went 296 → 306 (10 additional tests captured because admin operations now mutate state and unlock paths that previously 404'd).
1 parent 05d83a7 commit fbf3a55

2 files changed

Lines changed: 25 additions & 1 deletion

File tree

restheart-mongo/docker-compose.yml

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ services:
2727
# --freezeTime keeps `exp` valid. Pinning the secret keeps
2828
# the bearer signature verifiable across record→replay
2929
# container restarts (deterministic key, deterministic JWT).
30-
RHO: '/mclient/connection-string->"mongodb://${RESTHEART_MONGO_IP:-172.36.0.10}:27017";/http-listener/host->"0.0.0.0";/core/log-level->"INFO";/jwtConfigProvider/key->"keploy-fixed-jwt-secret-for-deterministic-recordings"'
30+
RHO: '/mclient/connection-string->"mongodb://${RESTHEART_MONGO_IP:-172.36.0.10}:27017";/http-listener/host->"0.0.0.0";/core/log-level->"INFO";/jwtConfigProvider/key->"keploy-fixed-jwt-secret-for-deterministic-recordings";/mongoAclAuthorizer/cache-enabled->false'
3131
# Bound RESTHeart's JVM heap. RESTHeart 9.x's default uses
3232
# `MaxRAMPercentage=25` of cgroup memory, which on a typical
3333
# Woodpecker runner cgroup (~8GB) lands ~2GB heap. With three
@@ -44,6 +44,21 @@ services:
4444
# 512m is comfortable for the record/replay workload (peak
4545
# observed at ~280MB in single-cell local runs).
4646
JAVA_TOOL_OPTIONS: "-Xms128m -Xmx512m"
47+
# Note on /mongoAclAuthorizer/cache-enabled->false in RHO:
48+
# RESTHeart's mongoAclAuthorizer caches ACL rules with a 5s
49+
# TTL backed by Caffeine, which uses System.nanoTime() to
50+
# measure expiry. When the lane runs `keploy test --freezeTime`,
51+
# the LD_PRELOADed clock-shim intercepts clock_gettime/
52+
# gettimeofday — and Caffeine's nanoTime ticker is also
53+
# frozen — so the cache TTL never expires. flow.sh's `sleep 6`
54+
# between an `acl` rule POST and the writer-permission test
55+
# works at record time (the wall clock advances and the cache
56+
# reloads), but at replay the cache stays loaded with whatever
57+
# state it had at the first request and never picks up the
58+
# newly-POSTed rule. Result: writer gets 403 at replay
59+
# despite recorded 200. Disabling the cache makes ACL rules
60+
# read-through from mongo on every request — small perf cost,
61+
# but eliminates the time-freeze x cache-ttl interaction.
4762
depends_on:
4863
mongo:
4964
condition: service_healthy

restheart-mongo/keploy.yml.template

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,15 @@ test:
4444
Date: []
4545
Content-Length: []
4646
Auth-Token: []
47+
# Etag is server-stamped per write/read on every doc and
48+
# collection in RESTHeart. The body field _etag is already
49+
# noised (below), but RESTHeart also exposes the same hash
50+
# in the response header `Etag`, which differs per run.
51+
Etag: []
52+
# POST /_sessions returns a `Location: /_sessions/<uuid>`
53+
# header where the UUID is server-generated per session.
54+
# Each replay gets a fresh UUID; ignore the header to match.
55+
Location: []
4756
body:
4857
_etag: []
4958
_oid: []

0 commit comments

Comments
 (0)