agoragames / leaderboard

Leaderboards backed by Redis in Ruby
https://rubygems.org/gems/leaderboard
MIT License
478 stars 65 forks source link

Member data type error #39

Closed jgadbois closed 11 years ago

jgadbois commented 11 years ago

Using leaderboard 2.2.1.

This is the same issue that I opened the other day. I recently upgraded to redis-rb version 3 and upgraded leaderboard. On my development and staging servers I am fine. On production I get a lot of errors. The error seems to be related to calling:

leader = leaderboard.member_at(1, :with_member_data=>true)

When I attempt to access my member data (leader[:member_data]["workout_exercise"]) I get the following error:

TypeError: can't convert String into Integer

Any idea what could be going on?

jeffarena commented 11 years ago

The return value from leader[:member_data] is likely an Array, which you're attempting to access as if it's a Hash.

jgadbois commented 11 years ago

I'm putting in a hash though and it's a hash on development and production. Does 2.2.1 handle adding member data differently from older versions?

jgadbois commented 11 years ago

Here's how records get put in my leaderboard

        Records::LeaderboardFactory.create(base(exercise_id)).rank_member(user.id, record, { workout_exercise: workout_exercise.id, workout: workout_exercise.workout_id, exercise: exercise_id, nickname: user.nickname, slug: user.cached_slug, workout_date: workout_exercise.workout.workout_date.to_i })

I actually have thousands of leaderboards and I'm using a Factory class that I wrote to instantiate/fetch the leaderboard, but you can see the rank_member call is putting in a hash.

jgadbois commented 11 years ago

Also - when I rollback my code, I can still access the leaderboard member data fine with the older gem version (which means it is getting stored correctly as a hash even with the newer versions)

jgadbois commented 11 years ago

Ok - here's more info: Member data is indeed being converted to an array instead of staying in a hash:

["workout_exercise", "109135", "workout", "14375", "exercise", "14301", "nickname", "user1", "slug", "user1", "workout_date", "1369180800"]

irb(main):004:0> REDIS
=> #<Redis client v3.0.4 for redis://184.73.236.163:11184/0>
irb(main):005:0> Leaderboard::VERSION
=> "2.2.1"
jgadbois commented 11 years ago

According to the Redis docs hgetall returns an array not a hash, which means member_data is an array since it just calls hgetall. However, before updating, member_data has been a hash, not an array. Any idea if it's a change in leaderboard or a change in REDIS or a change in both?

czarneckid commented 11 years ago

The difference between leaderboard 2.x and 3.x is that in 2.x, optional member data is stored as a hash in Redis per-member, where in 3.x, optional member data is stored as a string as part of a hash in Redis for all members. More details in the original proposal, https://github.com/agoragames/leaderboard/pull/26.

jgadbois commented 11 years ago

I totally forgot about that :) For now I was able to get it working using leaderboard 2.x with redis-rb 3 by just manually converting member data from an array back to a hash like my code expected. I'll think about a migration path so I can use the latest version of leaderboard. Sorry for all the back and forth, totally forgot about that.

czarneckid commented 11 years ago

No problem.