Skip to content

Instantly share code, notes, and snippets.

@wxmn
Created March 31, 2011 13:23
Show Gist options
  • Select an option

  • Save wxmn/896321 to your computer and use it in GitHub Desktop.

Select an option

Save wxmn/896321 to your computer and use it in GitHub Desktop.

Revisions

  1. wxmn revised this gist Apr 1, 2011. 1 changed file with 4 additions and 0 deletions.
    4 changes: 4 additions & 0 deletions status.rb
    Original file line number Diff line number Diff line change
    @@ -8,6 +8,8 @@ def feed(obj=true, count=FEED_COUNT)
    results=$redis.zrevrange key(:feed), 0, count
    if obj && results.size > 0
    results.collect {|r| Status.decode(r)}
    else
    results
    end
    end

    @@ -16,6 +18,8 @@ def ofeed(max, obj=true, id=self.id_s, limit=FEED_COUNT, scores=false)
    results=$redis.zrevrangebyscore(key(:feed), "(#{max}", "-inf", :limit => [0, limit], :with_scores => scores)
    if obj && results.size > 0
    results.collect {|r| Status.decode(r)}
    else
    results
    end
    end

  2. wxmn revised this gist Mar 31, 2011. 2 changed files with 13 additions and 0 deletions.
    2 changes: 2 additions & 0 deletions base.rb → redis_helper.rb
    Original file line number Diff line number Diff line change
    @@ -1,3 +1,4 @@
    module RedisHelper
    # decode Redis value back to Ruby object
    def self.decode(json)
    self.new(ActiveSupport::JSON.decode(json)["#{self.name.downcase}"])
    @@ -25,3 +26,4 @@ def ukey(str, uid=self.user_id) #for keys needing user_id
    def id_s
    id.to_s
    end
    end
    11 changes: 11 additions & 0 deletions status.rb
    Original file line number Diff line number Diff line change
    @@ -1,3 +1,5 @@
    class User

    FEED_COUNT=30

    # get latest feed using reverse range lookup of sorted set
    @@ -17,6 +19,11 @@ def ofeed(max, obj=true, id=self.id_s, limit=FEED_COUNT, scores=false)
    end
    end

    end


    class Status

    # push status to a specific feed
    def push(id, location="feed")
    $redis.zadd key(location, id), timestamp, encoded
    @@ -29,6 +36,10 @@ def push_to_followers
    end
    end

    end

    # also in user.rb:

    # since most sorted set commands are a variation on O(log(N))
    # where N is the size of the set, in makes sense to trim the
    # feed when it gets beyond a certain length
  3. wxmn created this gist Mar 31, 2011.
    27 changes: 27 additions & 0 deletions base.rb
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,27 @@
    # decode Redis value back to Ruby object
    def self.decode(json)
    self.new(ActiveSupport::JSON.decode(json)["#{self.name.downcase}"])
    end

    # encode Ruby object for Redis
    def encoded
    self.updated_at = nil
    self.to_json
    end

    # helpers to generate Redis keys
    def timestamp
    "#{self.created_at.to_i}"
    end

    def key(str, uid=self.id)
    "#{str}:#{uid}"
    end

    def ukey(str, uid=self.user_id) #for keys needing user_id
    "#{str}:#{uid}"
    end

    def id_s
    id.to_s
    end
    50 changes: 50 additions & 0 deletions status.rb
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,50 @@
    FEED_COUNT=30

    # get latest feed using reverse range lookup of sorted set
    # then decode raw JSON back into Ruby objects
    def feed(obj=true, count=FEED_COUNT)
    results=$redis.zrevrange key(:feed), 0, count
    if obj && results.size > 0
    results.collect {|r| Status.decode(r)}
    end
    end

    # get older statuses by using reverse range by score lookup
    def ofeed(max, obj=true, id=self.id_s, limit=FEED_COUNT, scores=false)
    results=$redis.zrevrangebyscore(key(:feed), "(#{max}", "-inf", :limit => [0, limit], :with_scores => scores)
    if obj && results.size > 0
    results.collect {|r| Status.decode(r)}
    end
    end

    # push status to a specific feed
    def push(id, location="feed")
    $redis.zadd key(location, id), timestamp, encoded
    end

    # push to followers (assumes an array of follower ids)
    def push_to_followers
    @follower_ids.each do |follower_id|
    push(follower_id)
    end
    end

    # since most sorted set commands are a variation on O(log(N))
    # where N is the size of the set, in makes sense to trim the
    # feed when it gets beyond a certain length

    FEED_LENGTH=240

    # there may be a more efficient way to do this
    # but I check the length of the set
    # then I get the score of the last value I want to keep
    # then remove all keys with a lower score
    def trim_feed(id=self.id_s, location="feed", indx=FEED_LENGTH)
    k = key(:feed)
    if ($redis.zcard k) >= indx
    n = indx - 1
    if (r = $redis.zrevrange k, n, n, :with_scores => true)
    $redis.zremrangebyscore k, "-inf", "(#{r.last}"
    end
    end
    end