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>)


113
114
115
# File 'lib/liszt/redis_list.rb', line 113

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

#clearObject

Clear all items from the list.



96
97
98
99
100
101
# File 'lib/liszt/redis_list.rb', line 96

def clear
  redis.multi do
    redis.del(@key)
    redis.rpush(@key, '*')
  end
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)


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

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

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



201
202
203
204
205
206
207
208
# File 'lib/liszt/redis_list.rb', line 201

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)


106
107
108
109
# File 'lib/liszt/redis_list.rb', line 106

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

#lock_expiration_timeObject (private)



218
219
220
# File 'lib/liszt/redis_list.rb', line 218

def lock_expiration_time
  5 # seconds
end

#lock_keyObject (private)



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

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)


139
140
141
142
143
144
145
146
147
148
149
150
151
152
# File 'lib/liszt/redis_list.rb', line 139

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)


165
166
167
168
169
170
# File 'lib/liszt/redis_list.rb', line 165

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)


156
157
158
159
160
161
# File 'lib/liszt/redis_list.rb', line 156

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)


121
122
123
124
125
126
127
128
129
130
131
132
133
134
# File 'lib/liszt/redis_list.rb', line 121

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
86
87
# File 'lib/liszt/redis_list.rb', line 81

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

#redisObject (private)



173
174
175
# File 'lib/liszt/redis_list.rb', line 173

def redis
  ::Liszt.redis
end

#release_lockObject (private)



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

def release_lock
  redis.del(lock_key)
end

#remove(id) ⇒ Object

Remove the given id from the list.

Parameters:

  • id (Fixnum)


91
92
93
# File 'lib/liszt/redis_list.rb', line 91

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

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



183
184
185
# File 'lib/liszt/redis_list.rb', line 183

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.



190
191
192
193
194
195
196
197
198
199
# File 'lib/liszt/redis_list.rb', line 190

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