It ins't the typical use case for WATCH-EXEC, but consider this scenario:

WATCH key
MULTI
INCR key
... time passes and key expires logically
... but not deleted yet (other clients and active expire don't hit it)
EXEC

EXEC successfully runs, the queued INCR deletes the key and creates a new one, that's non-volatile.

we could in theory actively check the expiration time of all watched keys before executing EXEC, if any are logically expired, delete them and fail the EXEC, if not proceed with EXEC, and also freeze time during EXEC so that the logical time of EXEC will not change for all commands it executes.

issue raised by @tzongw in #7920

Comment From: oranagra

@redis/core-team please share your thoughts.

Comment From: madolson

I agree, I think this is a problem. My thought is that the example you gave should give the same result for the following three placements of the key being expired:

WATCH key
GET KEY
1) ... key is logically expired
MULTI
2) ... key is logically expired
INCR key
3) ... key is logically expired
EXEC

Which as you mentioned it does not. I think the specific constraint is that a client can not lazy expire a key that it has watched, during a subsequent multi-exec. An alternative to what you proposed is: if we are going to lazy-expire a key, first check if this client has watched keys, if it does, check to see if they key we're going to expire is in that list of keys, if it is, ignore it for now.

Comment From: zuiderkwast

Expiration should be treated as if the key was touched. The EXEC should fail. Thus I agree with @madolson.

Comment From: soloestoy

Agree we should fix it, and we already have the fixed_time_expire, the logical time of exec is already frozen see #6537

Seems the reset is about logical expired during WATCH and EXEC, here is a way to solve this problem I think:

  1. call lookupKeyRead in WATCH command to delete expired keys, in case watch logical expired keys.
  2. check if the watched keys are logical expired before EXEC command, if it is, just abort this transaction.

Comment From: oranagra

@madolson i don't understand your proposal, please elaborate.

note, that in my proposal above, i accidentally said "all volatile keys" meant "all watched keys" (fixed and elaborated a bit).

Comment From: zuiderkwast

I think it's a bug. Logically, the commands between MULTI and EXEC are queued and not executed until EXEC so if a key expires before EXEC, the transaction should fail.

I'm not sure about how to solve it, but I think it should be solved and backported to 6.0 and 6.2, not wait until 7.0.

It's not that serious if we can assume that MULTI...EXEC is usually a pipeline.

Comment From: enjoy-binbin

i thinks the rest was fixed in #10256 (#10256 is a revamp of #9234), so we can finally close this issue