title: Is this redis lua script that deals with key expire race conditions a pure function?
body: <p>I've been playing around with redis to keep track of the ratelimit of an external api in a distributed system. I've decided to create a key for each route where a limit is present. The value of the key is how many request I can still make until the limit resets. And the reset is made by setting the TTL of the key to when the limit will reset.</p>
  
  <p>For that I wrote the following lua script:</p>
  
  <pre><code>if redis.call("EXISTS", KEYS[1]) == 1 then
      local remaining = redis.call("DECR", KEYS[1])
      if remaining &lt; 0 then
          local pttl = redis.call("PTTL", KEYS[1])
          if pttl &gt; 0 then
              --[[
              -- We would exceed the limit if we were to do a call now, so let's send back that a limit exists (1)
              -- Also let's send back how much we would have exceeded the ratelimit if we were to ignore it (ramaning)
              -- and how long we need to wait in ms untill we can try again (pttl)
                ]]
              return {1, remaining, pttl}
          elseif pttl == -1 then
              -- The key expired the instant after we checked that it existed, so delete it and say there is no ratelimit
              redis.call("DEL", KEYS[1])
              return {0}
          elseif pttl == -2 then
              -- The key expired the instant after we decreased it by one. So let's just send back that there is no limit
             return  {0}
          end
      else
          -- Great we have a ratelimit, but we did not exceed it yet.
          return {1, remaining}
      end
  else
     return {0}
  end
  </code></pre>
  
  <p><a href="https://www.bennadel.com/blog/2785-volatile-keys-can-expire-mid-multi-transaction-in-redis-jedis.htm" rel="nofollow noreferrer">Since a watched key can expire in the middle of a multi transaction without aborting it</a>. I assume the same is the case for lua scripts. Therefore I put in the cases for when the ttl is -1 or -2.</p>
  
  <p>After I wrote that script I looked a bit more in depth at the eval command page and found out that a lua script has to be a <a href="https://redis.io/commands/eval#scripts-as-pure-functions" rel="nofollow noreferrer">pure function</a>.</p>
  
  <p>In there it says</p>
  
  <blockquote>
    <p>The script must always evaluates the same Redis write commands with
    the same arguments given the same input data set. Operations performed
    by the script cannot depend on any hidden (non-explicit) information
    or state that may change as script execution proceeds or between
    different executions of the script, nor can it depend on any external
    input from I/O devices.</p>
  </blockquote>
  
  <p>With this description I'm not sure if my function is a pure function or not.</p>