py-sherlock / sherlock

Easy distributed locks for Python with a choice of backends.
MIT License
374 stars 35 forks source link

redis.exceptions.DataError: Invalid input of type: 'UUID' #32

Closed Nuqlear closed 5 years ago

Nuqlear commented 5 years ago

environment:

traceback:

Traceback (most recent call last):
  File "/usr/local/lib/python3.6/site-packages/celery/app/trace.py", line 375, in trace_task
    R = retval = fun(*args, **kwargs)
  File "/usr/local/lib/python3.6/site-packages/celery/app/trace.py", line 632, in __protected_call__
    return self.run(*args, **kwargs)
  File "/search/src/search_service/tasks/common.py", line 29, in queue
    with RedisLock("(queue/wipe)lock", client=self.app.redis_client):
  File "/usr/local/lib/python3.6/site-packages/sherlock/lock.py", line 199, in __enter__
    self.acquire()
  File "/usr/local/lib/python3.6/site-packages/sherlock/lock.py", line 171, in acquire
    if self._acquire() is not True:
  File "/usr/local/lib/python3.6/site-packages/sherlock/lock.py", line 429, in _acquire
    expire]) != 1:
  File "/usr/local/lib/python3.6/site-packages/redis/client.py", line 3498, in __call__
    return client.evalsha(self.sha, len(keys), *args)
  File "/usr/local/lib/python3.6/site-packages/redis/client.py", line 2704, in evalsha
    return self.execute_command('EVALSHA', sha, numkeys, *keys_and_args)
  File "/usr/local/lib/python3.6/site-packages/redis/client.py", line 754, in execute_command
    connection.send_command(*args)
  File "/usr/local/lib/python3.6/site-packages/redis/connection.py", line 619, in send_command
    self.send_packed_command(self.pack_command(*args))
  File "/usr/local/lib/python3.6/site-packages/redis/connection.py", line 659, in pack_command
    for arg in imap(self.encoder.encode, args):
  File "/usr/local/lib/python3.6/site-packages/redis/connection.py", line 124, in encode
    "byte, string or number first." % typename)
redis.exceptions.DataError: Invalid input of type: 'UUID'. Convert to a byte, string or number first.

It seems that sherlock has tests for Python 3 and they are passing... Why I am getting the exception then?

vaidik commented 5 years ago

Apologies for not being able to respond to this earlier. I have fixed the issue. And will make a release soon.

ghost commented 5 years ago

This seems to still be an issue, even on 0.3.2

shaleh commented 5 years ago

Confirmed. I am also seeing this with Sherlock 0.3.2 and Python 3.6.

File "/usr/local/lib/python3.6/site-packages/sherlock/lock.py", line 171, in acquire
    if self._acquire() is not True:
  File "/usr/local/lib/python3.6/site-packages/sherlock/lock.py", line 429, in _acquire
    expire]) != 1:
  File "/usr/local/lib/python3.6/site-packages/redis/client.py", line 3575, in __call__
    return client.evalsha(self.sha, len(keys), *args)
  File "/usr/local/lib/python3.6/site-packages/redis/client.py", line 2761, in evalsha
    return self.execute_command('EVALSHA', sha, numkeys, *keys_and_args)
  File "/usr/local/lib/python3.6/site-packages/redis/client.py", line 774, in execute_command
    connection.send_command(*args)
  File "/usr/local/lib/python3.6/site-packages/redis/connection.py", line 620, in send_command
    self.send_packed_command(self.pack_command(*args))
  File "/usr/local/lib/python3.6/site-packages/redis/connection.py", line 663, in pack_command
    for arg in imap(self.encoder.encode, args):
  File "/usr/local/lib/python3.6/site-packages/redis/connection.py", line 125, in encode
    "byte, string or number first." % typename)
redis.exceptions.DataError: Invalid input of type: 'UUID'. Convert to a byte, string or number first.

Which it turns out does not match what is checked into master. @vaidik you appear to have created a tgz with older code.

$ diff --exclude .git --exclude .gitignore --exclude .travis.yml --exclude Docker* --exclude Makefile --exclude PKG-INFO --exclude docker-compose.dev.yml --exclude sherlock.egg-info --exclude '*.rst' --exclude conf.py --exclude tests -pruNb ~/tmp/sherlock-0.3.2/ sherlock/

diff --exclude .git --exclude .gitignore --exclude .travis.yml --exclude 'Docker*' --exclude Makefile --exclude PKG-INFO --exclude docker-compose.dev.yml --exclude sherlock.egg-info --exclude '*.rst' --exclude conf.py --exclude tests -pruNb /Users/seanperry/tmp/sherlock-0.3.2/setup.cfg sherlock/setup.cfg
--- /Users/seanperry/tmp/sherlock-0.3.2/setup.cfg   2019-05-11 04:26:46.000000000 -0700
+++ sherlock/setup.cfg  1969-12-31 16:00:00.000000000 -0800
@@ -1,4 +0,0 @@
-[egg_info]
-tag_build = 
-tag_date = 0
-
diff --exclude .git --exclude .gitignore --exclude .travis.yml --exclude 'Docker*' --exclude Makefile --exclude PKG-INFO --exclude docker-compose.dev.yml --exclude sherlock.egg-info --exclude '*.rst' --exclude conf.py --exclude tests -pruNb /Users/seanperry/tmp/sherlock-0.3.2/sherlock/lock.py sherlock/sherlock/lock.py
--- /Users/seanperry/tmp/sherlock-0.3.2/sherlock/lock.py    2019-05-11 04:03:35.000000000 -0700
+++ sherlock/sherlock/lock.py   2019-06-04 17:28:34.000000000 -0700
@@ -57,7 +57,7 @@ class BaseLock(object):
     ...
     ...     def _acquire(self):
     ...         if self.client.get(self.lock_name) is not None:
-    ...             owner = uuid.uuid4() # or anythin you want
+    ...             owner = str(uuid.uuid4()) # or anythin you want
     ...             self.client.set(self.lock_name, owner)
     ...             self._owner = owner
     ...             if self.expire is not None:
@@ -419,7 +419,7 @@ class RedisLock(BaseLock):
         return key

     def _acquire(self):
-        owner = uuid.uuid4()
+        owner = str(uuid.uuid4())
         if self.expire is None:
             expire = -1
         else:
@@ -524,7 +524,7 @@ class EtcdLock(BaseLock):
             return '/%s' % self.lock_name

     def _acquire(self):
-        owner = uuid.uuid4()
+        owner = str(uuid.uuid4())

         _args = [self._key_name, owner]
         if self.expire is not None:
@@ -641,7 +641,7 @@ class MCLock(BaseLock):
         return key

     def _acquire(self):
-        owner = uuid.uuid4()
+        owner = str(uuid.uuid4())

         _args = [self._key_name, str(owner)]
         if self.expire is not None:

A common pattern in other repos is to use git tagging to mark releases. This way it is easy for people to examine a specific version of a fix or to look at what changed between versions. git diff 0.3.0..0.3.2 for example.

When preparing a release you can then do:

$ cd tmp
$ git clone --branch v0.3.2 --depth 1 $GITHUB_REPO_URL sherlock-0.3.2
$ # whatever it takes to prepare repo for release.....
$ tar czvf sherlock-0.3.2.tar.gz sherlock-0.3.2