redisjson-py
redisjson-py copied to clipboard
Client.jsonget not finding key from rootpath
I'm entirely certain this may be a usage issue, but reaching out here as I'm not sure where else to look.
Problem
I have a class Jobs
which inherits the rejson module classes Client
and Path
. Methods in the Jobs
class are called by routes in a flask API.
My /run
route calls the make_job
function, which in turn generates a unique id for that job, and inserts a JSON body into redis. I am using the redis-json docker image from dockerhub.
My /status
route calls the get_job
function, and is supposed to return a JSON object from redis.
The problem I'm having is, I can insert JSON objects without issue, but jsonget
can't seem to find the key I inserted previously.
All keys are inserted at the root path.
Workflow
Insert Key via /run
route:
{
"JobID": "5de40954-bf5f-499e-8d6e-f283d4d326c8",
}
Verify via redis-cli:
127.0.0.1:6379> KEYS 5de40954-bf5f-499e-8d6e-f283d4d326c8
1) "5de40954-bf5f-499e-8d6e-f283d4d326c8"
127.0.0.1:6379>
127.0.0.1:6379> json.get 5de40954-bf5f-499e-8d6e-f283d4d326c8
"{\"gitOrg\":\"test-org\",\"gitRepo\":\"test-repo\",\"job\":{\"inventory\":\"site.ini\",\"playbook\":\"deploy.yml\",\"vars\":\"env=testenv cleanup_keys=true\"}}"
Run /status
route that calls get_job()
, which gets a key using jsonget
;
None
127.0.0.1 - - [12/Jul/2019 16:24:02] "GET /status/5de40954-bf5f-499e-8d6e-f283d4d326c8 HTTP/1.1" 404 -
where None
is the output of print(job)
Code:
from rejson import Client, Path
class Jobs(Client, Path):
Client(host='localhost', port=6379, decode_responses=True)
def make_job_id(self):
return uuid.uuid4()
def make_job(self, data):
jobId = str(self.make_job_id())
self.jsonset(jobId, Path.rootPath(), data)
return jobId
def get_job(self, jobId):
job = self.jsonget(jobId)
if job:
print(job)
return job
else:
return False
Expected results
jsonget
returns and decodes the JSON object stored under the keyname set when inserted.
I'm not sure if this is a pathing issue. I've looked at the source, and I see that jsonget
defaults to the root path.
Before using rejson-py, I was using just the raw redis client and encoding/decoding json as needed, but I had issues where the first key I inserted into redis would be rendered null
, so I switched to rejson-py.
Idk if I'm being incredibly stupid here or what..
This might be a clue, I just don't know how to interpret it.
I modified the get_job
function to run a raw redis command.
def get_job(self, jobId):
reply = self.execute_command('JSON.GET', jobId)
print(reply)
return reply
When called, throws the error:
return self.response_callbacks[command_name](response, **options)
File "/usr/local/Cellar/python/3.7.3/Frameworks/Python.framework/Versions/3.7/lib/python3.7/json/decoder.py", line 337, in decode
obj, end = self.raw_decode(s, idx=_w(s, 0).end())
TypeError: cannot use a string pattern on a bytes-like object
Hello! Your code seems to be good, but the None answer from the client, and the error thrown with your second test confirm that there are no JSON data under that key.
Have you tried the same way as you did with the redis-cli, but with Python ? With the key hard-written in the code ? I'd say that the jobId
parameter in the get_job
method maybe isn't what you think it is ? It is the only answer I can think of at the moment.
This seems to be a decoding problem of the data stored as bytes()
in Redis.
Replacing the default JSONDecoder
with the following did the trick for me:
from rejson import Client, Path
from json import JSONDecoder
class RedisJsonDecoder(JSONDecoder):
def decode(self, s, *args, **kwargs):
if isinstance(s, bytes):
s = s.decode('UTF-8')
return super(RedisJsonDecoder, self).decode(s, *args, **kwargs)
r = Client(decoder=RedisJsonDecoder())
# ...
HTH!