soveran / ohm

Object-Hash Mapping for Redis

Home Page:http://ohm.keyvalue.org

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Getting last id

carina-akaia opened this issue · comments

Is there a method for last id getting?
Something like User.last_id, more low-cost (and low-level) than current User.all.ids[-1]

commented

The last ID is stored as a separate Redis key at <ModelName>:id.

You could get the last ID with a Redis GET:

Ohm.redis.call("GET", "User:id")

Thanks for answer, it helps in my case. It seems like undocumented feature.
I think it might be nice if that functional be realized as OHM model method instead of redis call.

Can you add feature request label?

@katecanaveral I just added the label. Not sure if I prefer Model.id or Model.last_id. Or maybe we just need to document how to get that value from Redis. What was your use case? You can leave your comments here, I guess the next version can include an improvement on this area.

My case is using last user id for next id prediction, i use it in next username.

last_id = Ohm.redis.call('GET', 'User:id').to_i
    User.create(
        name: "user_#{last_id + 1}",
        ...
    )

User.all.ids[-1].to_i is bit laggy, sometimes i was getting username 'user_30',
although last user id was >40 0_o

About method Model.last_id (i guess .id is implicit name), it's very usable and graceful alias for Ohm.redis.call('GET', 'User:id').to_i

commented

@katecanaveral regardless of the last id feature, I'd want to comment on a possible source of bugs with your approach.

If timed just right, you might get an incorrect name attribute in your users, since another user might be created between you calling GET User:id and creating the new user, which is a difficult bug to reproduce that is sure to cause you some pain if/when it happens.

But also: it doesn't seem like you need to store the name in an Ohm attribute for that model since the information you want is composed of the model id and a static string, a method like the one below might be enough:

class User < Ohm::Model
  def name
    "user_#{ id }"
  end
end

Maybe there are extra considerations that make you actually need a name Ohm attribute, but I'd still suggest an alternative implementation (like setting the name after the model is created, either synchronously or with a background job) to avoid a possible id/name mismatch bug, happy to help if you need any guidance.