stefanwille / crystal-redis

Full featured Redis client for Crystal
MIT License
380 stars 61 forks source link

Is there a way to get the equivalent of `OBJECT IDLETIME <key>` with crystal-redis? #42

Closed weirdbricks closed 7 years ago

weirdbricks commented 7 years ago

Hello,

Thank you for your excellent work in this.

I was looking for a way to get the age of an object in seconds and it looks like you can do that by using OBJECT IDLETIME <key> - for example, with the redis-cli I can do:

redis-cli 
127.0.0.1:6379> object idletime kerberos
(integer) 42

Is there a way to get the same result with crystal-redis?

Thanks!

weirdbricks commented 7 years ago

Sorry, forgot to attach the relevant Redis command page where this is referenced:

https://redis.io/commands/object

maiha commented 7 years ago

Hi @weirdbricks ! Unfortunetely, it seems object command has not been implemented yet.

But, all crystal commands is internally represented as Array(String). So you can manually call it by Redis#command(ary : Array(String)) method like this!

idle = redis.command(["object", "idletime", "kerberos"]).as(Int64)
weirdbricks commented 7 years ago

Hi @maiha, Thank you very much for your prompt response.

I gave it a try but I got a strange error:

Redis: #<Redis:0x13d3d80>
Keyname: kerberos
Older than: 120
OK - Found the key "kerberos"
RedisError: ERR Protocol error: expected '$', got ':' (Redis::Error)
0x4602d7: *CallStack::unwind:Array(Pointer(Void)) at ??
0x4ae58f: receive at /root/redis-check/lib/redis/src/redis/connection.cr 79:7
0x4b7aa3: command at /root/redis-check/lib/redis/src/redis/strategy/single_statement.cr 12:5
0x4adf87: command at /root/redis-check/lib/redis/src/redis.cr 219:5
0x45e368: check_if_a_key_exists at /root/redis-check/src/redis-check.cr 80:16
0x44d41b: __crystal_main at /root/redis-check/src/redis-check.cr 94:2
0x45cd79: main at /opt/crystal/src/main.cr 12:15
0x7fb2e8366b35: __libc_start_main at ??
0x44c7ba: ??? at ??
0x0: ??? at ??

Here's my function with some additional debugging information:

def check_if_a_key_exists(redis,keyname,older_than)
        puts "Redis: #{redis.inspect}"
        puts "Keyname: #{keyname.inspect}"
        puts "Older than: #{older_than.inspect}"
        result=redis.exists(keyname)
        if result == 1
                puts "OK - Found the key \"#{keyname}\""
                age_of_key = redis.command([keyname, older_than, keyname]).as(Int64)
                puts age_of_key
        else
                puts "CRITICAL - I could not find the key \"#{keyname}\""
                exit 2
        end
end

Do you see anything wrong with my code? In case it matters my version of Redis is: 3.2.5

Many thanks!

maiha commented 7 years ago
                age_of_key = redis.command([keyname, older_than, keyname]).as(Int64)

I think this should be:

                age_of_key = redis.command(["object", "idletime", keyname]).as(Int64?)

otherwise, it means as same as:

redis-cli> kerberos 120 kerberos

FYI: object idletime returns nil if the key doesn't exist, so I found we should use as(Int64?).

stefanwille commented 7 years ago

Hello @weirdbricks,

I overlooked the OBJECT command. But I can add it during the next days.

The error you get with maiha's workaround is a type error that was reported by Redis. I am not sure what it is. I guess I will find out when I build the object command(s).

weirdbricks commented 7 years ago

@maiha many many thanks! It worked great!

@stefanwille thank you sir and no rush at all - the workaround suggested by @maiha did the trick!

Feel free to close or do whatever you think is necessary with this issue :)

stefanwille commented 7 years ago

@weirdbricks done: https://github.com/stefanwille/crystal-redis/releases/tag/v1.9.0

weirdbricks commented 7 years ago

@stefanwille thank you!!