Skip to content

Commit

Permalink
Update stream ID regex to support '(' (#209)
Browse files Browse the repository at this point in the history
* Fix hmset exception and xadd spec errors

* Update ID regex

* Implement exclusive xrange
  • Loading branch information
jmthomas committed May 1, 2021
1 parent 04ab75d commit c129012
Show file tree
Hide file tree
Showing 3 changed files with 30 additions and 9 deletions.
12 changes: 9 additions & 3 deletions lib/mock_redis/stream.rb
Expand Up @@ -49,9 +49,15 @@ def range(start, finish, reversed, *opts_in)
opts = options opts_in, ['count']
start_id = MockRedis::Stream::Id.new(start)
finish_id = MockRedis::Stream::Id.new(finish, sequence: Float::INFINITY)
items = members
.select { |m| (start_id <= m[0]) && (finish_id >= m[0]) }
.map { |m| [m[0].to_s, m[1]] }
if start_id.exclusive
items = members
.select { |m| (start_id < m[0]) && (finish_id >= m[0]) }
.map { |m| [m[0].to_s, m[1]] }
else
items = members
.select { |m| (start_id <= m[0]) && (finish_id >= m[0]) }
.map { |m| [m[0].to_s, m[1]] }
end
items.reverse! if reversed
return items.first(opts['count'].to_i) if opts.key?('count')
items
Expand Down
11 changes: 8 additions & 3 deletions lib/mock_redis/stream/id.rb
Expand Up @@ -3,9 +3,10 @@ class Stream
class Id
include Comparable

attr_accessor :timestamp, :sequence
attr_accessor :timestamp, :sequence, :exclusive

def initialize(id, min: nil, sequence: 0)
@exclusive = false
case id
when '*'
@timestamp = (Time.now.to_f * 1000).to_i
Expand All @@ -20,8 +21,12 @@ def initialize(id, min: nil, sequence: 0)
@timestamp = @sequence = Float::INFINITY
else
if id.is_a? String
(_, @timestamp, @sequence) = id.match(/^(\d+)-?(\d+)?$/)
.to_a
# See https://redis.io/topics/streams-intro
# Ids are a unix timestamp in milliseconds followed by an
# optional dash sequence number, e.g. -0. They can also optionally
# be prefixed with '(' to change the XRANGE to exclusive.
(_, @timestamp, @sequence) = id.match(/^\(?(\d+)-?(\d+)?$/).to_a
@exclusive = true if id[0] == '('
if @timestamp.nil?
raise Redis::CommandError,
'ERR Invalid stream ID specified as stream command argument'
Expand Down
16 changes: 13 additions & 3 deletions spec/commands/xrange_spec.rb
Expand Up @@ -79,13 +79,23 @@
)
end

it 'returns entries with both a lower and an upper limit' do
expect(@redises.xrange(@key, '1234567891239-0', '1234567891285-0')).to eq(
it 'returns entries with both a lower and an upper limit inclusive' do
expect(@redises.xrange(@key, '1234567891245-0', '1234567891278-0')).to eq(
[
['1234567891245-0', { 'key2' => 'value2' }],
['1234567891245-1', { 'key3' => 'value3' }],
['1234567891278-0', { 'key4' => 'value4' }]
]
)
end

it 'returns entries with both a lower and an upper limit exclusive' do
expect(@redises.xrange(@key, '(1234567891245-0', '1234567891285-1')).to eq(
[
# We no longer get '1234567891245-0'
['1234567891245-1', { 'key3' => 'value3' }],
['1234567891278-0', { 'key4' => 'value4' }],
['1234567891278-1', { 'key5' => 'value5' }]
['1234567891278-1', { 'key5' => 'value5' }] # Note sequence -1
]
)
end
Expand Down

0 comments on commit c129012

Please sign in to comment.