Skip to content

Commit

Permalink
gat implementation
Browse files Browse the repository at this point in the history
  • Loading branch information
svanellewee committed Nov 8, 2018
1 parent bad4122 commit 019196e
Show file tree
Hide file tree
Showing 2 changed files with 80 additions and 0 deletions.
69 changes: 69 additions & 0 deletions memcache.py
Original file line number Diff line number Diff line change
Expand Up @@ -1113,6 +1113,61 @@ def _unsafe_get():
server.mark_dead(msg)
return None

def _gat(self, cmd, key, time, noreply=False):
key = self._encode_key(key)
if self.do_check_key:
self.check_key(key)
server, key = self._get_server(key)
if not server:
return None

def _unsafe_gat():
self._statlog(cmd)
try:
_time = str(time)
_time = _time.encode('utf-8')
cmd_bytes = cmd.encode('utf-8') if six.PY3 else cmd
fullcmd = b''.join((cmd_bytes, b' ', _time, b' ', key))
server.send_cmd(fullcmd)
rkey = flags = rlen = cas_id = None

if cmd == 'gats':
rkey, flags, rlen, cas_id, = self._expect_cas_value(
server, raise_exception=True
)
if rkey and self.cache_cas:
self.cas_ids[rkey] = cas_id
else:
rkey, flags, rlen, = self._expectvalue(
server, raise_exception=True
)

if not rkey:
return None
try:
value = self._recv_value(server, flags, rlen)
finally:
server.expect(b"END", raise_exception=True)
except (_Error, socket.error) as msg:
if isinstance(msg, tuple):
msg = msg[1]
server.mark_dead(msg)
return None

return value

try:
return _unsafe_gat()
except _ConnectionDeadError:
# retry once
try:
if server.connect():
return _unsafe_gat()
return None
except (_ConnectionDeadError, socket.error) as msg:
server.mark_dead(msg)
return None

def get(self, key):
'''Retrieves a key from the memcache.
Expand All @@ -1127,6 +1182,20 @@ def gets(self, key):
'''
return self._get('gets', key)

def gat(self, key, time=1):
'''Retrieves and touches a key from the memcache.
@return: The value or None.
'''
return self._gat('gat', key, time=time)

def gats(self, key, time=1):
'''Retrieves and touches a key from the memcache. Used in conjunction with 'cas'.
@return: The value or None.
'''
return self._gat('gats', key, time=time)

def get_multi(self, keys, key_prefix=''):
'''Retrieves multiple keys from the memcache doing just one query.
Expand Down
11 changes: 11 additions & 0 deletions tests/test_memcache.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,17 @@ def test_setget(self):
self.check_setget("an_integer", 42)
self.check_setget("an_integer_2", 42, noreply=True)

def check_setgat(self, key, val, noreply=False):
self.mc.set(key, val, noreply=noreply)
newval = self.mc.gat(key, 2)
self.assertEqual(newval, val)

def test_setgat(self):
self.check_setgat("a_string", "some random string")
self.check_setgat("a_string_2", "some random string", noreply=True)
self.check_setgat("an_integer", 42)
self.check_setgat("an_integer_2", 42, noreply=True)

def test_delete(self):
self.check_setget("long", int(1 << 30))
result = self.mc.delete("long")
Expand Down

0 comments on commit 019196e

Please sign in to comment.