Class: Liszt::RedisList

Inherits:
Object
  • Object
show all
Defined in:
lib/liszt/redis_list.rb

Instance Method Summary collapse

Constructor Details

#initialize(key) ⇒ RedisList

Returns a new instance of RedisList.

Parameters:

  • key (String)

    The Redis key associated with this list.



4
5
6
# File 'lib/liszt/redis_list.rb', line 4

def initialize(key)
  @key = key
end

Instance Method Details

#allArray<Fixnum> Also known as: to_a

Return an Array of all the ids in the list.

Returns:

  • (Array<Fixnum>)


109
110
111
# File 'lib/liszt/redis_list.rb', line 109

def all
  redis.lrange(@key, 0, -2).map(&:to_i)
end

#clearObject

Clear all items from the list.



94
95
96
97
# File 'lib/liszt/redis_list.rb', line 94

def clear
  redis.del(@key)
  redis.rpush(@key, '*')
end

#clear_and_populate!(ids) ⇒ Array<Fixnum>

Remove existing list items and repopulate the list with the given ids (in the given order).

Parameters:

  • ids (Array<Fixnum>)

Returns:

  • (Array<Fixnum>)


17
18
19
20
21
22
23
24
# File 'lib/liszt/redis_list.rb', line 17

def clear_and_populate!(ids)
  redis.multi do
    clear
    # reverse and unshift to avoid touching the marker
    ids.reverse.each { |id| unshift!(id) }
  end
  ids
end

#get(index) ⇒ Object (private)

Return the item at the given index in the list.

Parameters:

  • index (Fixnum)


175
176
177
# File 'lib/liszt/redis_list.rb', line 175

def get(index)
  redis.lindex(@key, index).to_i
end

#get_lock(timeout = lock_expiration_time) ⇒ Object (private)



197
198
199
200
201
202
203
204
# File 'lib/liszt/redis_list.rb', line 197

def get_lock(timeout=lock_expiration_time)
  if redis.setnx(lock_key, true)
    redis.expire(lock_key, timeout)
    true
  else
    false
  end
end

#include?(id) ⇒ Boolean

Does the list currently include this id?

Parameters:

  • id (Fixnum)

Returns:

  • (Boolean)


35
36
37
# File 'lib/liszt/redis_list.rb', line 35

def include?(id)
  all.include?(id)
end

#index(id) ⇒ Fixnum

Return the index of the given id in the list.

Parameters:

  • id (Fixnum)

Returns:

  • (Fixnum)


42
43
44
# File 'lib/liszt/redis_list.rb', line 42

def index(id)
  all.index(id)
end

#initialized?Boolean

Has the list been initialized?

Returns:

  • (Boolean)


28
29
30
# File 'lib/liszt/redis_list.rb', line 28

def initialized?
  redis.exists(@key)
end

#lengthFixnum?

Return the number of ids in the list, or nil if it's uninitialized.

Returns:

  • (Fixnum)
  • (nil)


102
103
104
105
# File 'lib/liszt/redis_list.rb', line 102

def length
  len = redis.llen(@key)
  (len > 0) ? (len - 1) : nil
end

#lock_expiration_timeObject (private)



214
215
216
# File 'lib/liszt/redis_list.rb', line 214

def lock_expiration_time
  5 # seconds
end

#lock_keyObject (private)



210
211
212
# File 'lib/liszt/redis_list.rb', line 210

def lock_key
  "#{@key}:lock"
end

#move_down(id) ⇒ Object

Swap the position of the given id with the one below it. If it's at the bottom of the list or not present in the list, do nothing.

Parameters:

  • id (Fixnum)


135
136
137
138
139
140
141
142
143
144
145
146
147
148
# File 'lib/liszt/redis_list.rb', line 135

def move_down(id)
  with_lock do
    position = index(id)
    if position.nil? or position == (length - 1)
      nil
    else
      next_id = get(position + 1)
      redis.multi do
        set(position + 1, id)
        set(position, next_id)
      end
    end
  end
end

#move_to_bottom(id) ⇒ Object

Move the given id to the bottom of the list.

Parameters:

  • id (Fixnum)


161
162
163
164
165
166
# File 'lib/liszt/redis_list.rb', line 161

def move_to_bottom(id)
  redis.multi do
    remove(id)
    push!(id)
  end
end

#move_to_top(id) ⇒ Object

Move the given id to the top of the list.

Parameters:

  • id (Fixnum)


152
153
154
155
156
157
# File 'lib/liszt/redis_list.rb', line 152

def move_to_top(id)
  redis.multi do
    remove(id)
    unshift!(id)
  end
end

#move_up(id) ⇒ Object

Swap the position of the given id with the one above it. If it's at the top of the list or not present in the list, do nothing.

Parameters:

  • id (Fixnum)


117
118
119
120
121
122
123
124
125
126
127
128
129
130
# File 'lib/liszt/redis_list.rb', line 117

def move_up(id)
  with_lock do
    position = index(id)
    if position.nil? or position == 0
      nil
    else
      prev_id = get(position - 1)
      redis.multi do
        set(position - 1, id)
        set(position, prev_id)
      end
    end
  end
end

#push(id) ⇒ Boolean Also known as: <<

Push the given id onto the bottom of the list, if not already present.

Parameters:

  • id (Fixnum)

Returns:

  • (Boolean)

    false if the item was already in the list, true otherwise.



69
70
71
72
73
74
75
76
# File 'lib/liszt/redis_list.rb', line 69

def push(id)
  if include?(id)
    false
  else
    push!(id)
    true
  end
end

#push!(id) ⇒ Object

Push the given id onto the bottom of the list.

Parameters:

  • id (Fixnum)


81
82
83
84
85
# File 'lib/liszt/redis_list.rb', line 81

def push!(id)
  redis.rpop(@key)
  redis.rpush(@key, id)
  redis.rpush(@key, '*')
end

#redisObject (private)



169
170
171
# File 'lib/liszt/redis_list.rb', line 169

def redis
  ::Liszt.redis
end

#release_lockObject (private)



206
207
208
# File 'lib/liszt/redis_list.rb', line 206

def release_lock
  redis.del(lock_key)
end

#remove(id) ⇒ Object

Remove the given id from the list.

Parameters:

  • id (Fixnum)


89
90
91
# File 'lib/liszt/redis_list.rb', line 89

def remove(id)
  redis.lrem(@key, 1, id)
end

#set(index, value) ⇒ Object (private)



179
180
181
# File 'lib/liszt/redis_list.rb', line 179

def set(index, value)
  redis.lset(@key, index, value)
end

#uninitializeObject

Completely delete the list from Redis, leaving no marker.



9
10
11
# File 'lib/liszt/redis_list.rb', line 9

def uninitialize
  redis.del(@key)
end

#unshift(id) ⇒ Boolean

Push the given id onto the top of the list, if not already present.

Parameters:

  • id (Fixnum)

Returns:

  • (Boolean)

    false if the item was already in the list, true otherwise.



50
51
52
53
54
55
56
57
# File 'lib/liszt/redis_list.rb', line 50

def unshift(id)
  if include?(id)
    false
  else
    unshift!(id)
    true
  end
end

#unshift!(id) ⇒ Object

Push the given id onto the top of the list.

Parameters:

  • id (Fixnum)


61
62
63
# File 'lib/liszt/redis_list.rb', line 61

def unshift!(id)
  redis.lpush(@key, id)
end

#with_lockObject (private)

Obtain an exclusive lock on the list, execute the given block, and then release the lock. If the lock is currently taken by someone else, we just block until it becomes available.



186
187
188
189
190
191
192
193
194
195
# File 'lib/liszt/redis_list.rb', line 186

def with_lock
  start_time = Time.now
  until get_lock
    sleep 0.2
    raise "Timed out!" if (Time.now - start_time) > 10
  end
  yield
ensure
  release_lock
end