This book covers the use of Redis, an in-memory database/data structure server.

open all | close all

6.3.3 Refreshing semaphores

As the API for the marketplace was being completed, it was decided that there should
be a method for users to stream all item listings as they happen, along with a stream
for all purchases that actually occur. The semaphore method that we created only supports
a timeout of 10 seconds, primarily to deal with timeouts and possible bugs on
our side of things. But users of the streaming portion of the API will want to keep connected
for much longer than 10 seconds, so we need a method for refreshing the
semaphore so that it doesn’t time out.

Because we already separated the timeout ZSET from the owner ZSET, we can actually
refresh timeouts quickly by updating our time in the timeout ZSET, shown in the
following listing.

Listing 6.16The refresh_fair_semaphore() function
def refresh_fair_semaphore(conn, semname, identifier):
   if conn.zadd(semname, identifier, time.time()):

Update our semaphore.

      release_fair_semaphore(conn, semname, identifier)
      return False

We lost our semaphore; report back.

   return True

We still have our semaphore.

As long as we haven’t already timed out, we’ll be able to refresh the semaphore. If we
were timed out in the past, we’ll go ahead and let the semaphore be lost and report to
the caller that it was lost. When using a semaphore that may be refreshed, we need to
be careful to refresh often enough to not lose the semaphore.

Now that we have the ability to acquire, release, and refresh a fair semaphore, it’s
time to deal with our final race condition.