Can @Memoized prevent duplicate writes when a Groovy retry re-invokes a side-effecting method?
0 reputation · 07 Dec 2021, 16:13 UTC
0 reputation · 07 Dec 2021, 16:13 UTC
Groovy (assuming the 4.x line) has no standard retry primitive with idempotency guarantees, so retry logic around a failing write is usually hand-rolled as a closure inside a try/catch loop. Because a closure re-executes its captured side effects on each invocation, every retry attempt repeats the write unless the block is made idempotent by hand.
@Memoized (groovy.transform.Memoized) is the documented AST transformation that caches a method's return value after its first call. The transformation is documented for pure methods, which leaves the retry case unresolved: it is unclear whether the annotation can double as a deduplication guard for a method that writes, or what happens when the first invocation throws before returning a value. Closure delegate and resolve strategy, along with @CompileStatic, can also change which captured state is re-evaluated per attempt, so behavior may need checking against the specific Groovy version and compilation mode in use.
Can @Memoized be relied on to stop a side-effecting method from running twice when a retry invokes it again? Does a first invocation that throws an exception get cached, or does the method re-execute on the next call? And where the annotation cannot help, how should a manual retry loop be structured so the write occurs exactly once while the retryable check can repeat?
35275 reputation · 07 Dec 2021, 20:55 UTC
No – @Memoized cannot be relied on to guarantee that a side‑effecting method runs only once when a hand‑rolled retry loop re‑invokes it. It will prevent duplicate execution only when the first invocation completes normally and the method is called with exactly the same arguments on every retry attempt. If the first call throws an exception, or if any argument changes between attempts, the method will be re‑executed on each retry.
@Memoized transformation@CompileStatic or the chosen compile mode.When a retry loop surrounds a @Memoized method:
@Memoized method that increments a static counter and returns a value.The only missing detail that changes the recommendation is whether your retry logic passes **exactly the same arguments** on each attempt. If any argument (such as a retry counter, timestamp, or mutable payload) varies, @Memoized will not deduplicate the write, and you must add an explicit idempotency guard (e.g., a flag, a database check, or a deduplication token).
Use comments to ask for clarification. Post a solution as an answer.
No question comments on this page.