@@ -323,9 +323,28 @@ type PropagationConfig struct {
323323 RegisterReplayOnStart * bool `mapstructure:"register_replay_on_start"`
324324 // RegisterReplayLookbackHours bounds how far back IterateStatusesSince
325325 // scans when replaying. Older txs are very likely terminal already
326- // (MINED/IMMUTABLE) and skipping them avoids walking months of history
327- // on every boot. Defaults to 168 (7 days).
326+ // (MINED/IMMUTABLE), and a non-terminal tx older than this window has
327+ // almost certainly stalled — re-registering it on every boot won't
328+ // unstick it. Defaults to 24 (one day), tightened from the original
329+ // 7 days after issue #145.
328330 RegisterReplayLookbackHours int `mapstructure:"register_replay_lookback_hours"`
331+ // MerkleReplaySkipRecentMinutes lets the startup replay skip txs whose
332+ // MerkleRegisteredAt is within this window. /watch is INSERT ... ON
333+ // CONFLICT DO NOTHING on the merkle-service side and does not refresh
334+ // expires_at, so re-registering a tx merkle-service already knows about
335+ // is wasted work. Default 30 (matches merkle-service postMineTTLSec).
336+ // Set to 0 to disable the skip and re-register every non-terminal tx —
337+ // useful for forcing a full re-sync after a known merkle-service wipe.
338+ // Issue #145.
339+ MerkleReplaySkipRecentMinutes int `mapstructure:"merkle_replay_skip_recent_minutes"`
340+ // MerkleReplayRPS caps the average requests-per-second the startup
341+ // replay issues against merkle-service. Implemented as an inter-batch
342+ // sleep proportional to batch size, so the actual rate hovers around
343+ // the configured RPS rather than burst-then-stall. 0 disables
344+ // throttling. Default 50 — a 24h replay over a 1.85M-row store would
345+ // otherwise pin merkle-service at its postgres write ceiling for hours.
346+ // Issue #145.
347+ MerkleReplayRPS int `mapstructure:"merkle_replay_rps"`
329348 // MaxPending caps the in-memory pending-batch slice the propagation
330349 // consumer accumulates between flushes. Once full, new messages are
331350 // returned as errors from handleMessage so the Kafka consumer's
@@ -665,7 +684,9 @@ func setDefaults() {
665684 // drops its registration state and arcade silently stops receiving
666685 // callbacks for everything in-flight.
667686 viper .SetDefault ("propagation.register_replay_on_start" , true )
668- viper .SetDefault ("propagation.register_replay_lookback_hours" , 168 )
687+ viper .SetDefault ("propagation.register_replay_lookback_hours" , 24 )
688+ viper .SetDefault ("propagation.merkle_replay_skip_recent_minutes" , 30 )
689+ viper .SetDefault ("propagation.merkle_replay_rps" , 50 )
669690
670691 viper .SetDefault ("network" , NetworkMainnet )
671692
0 commit comments