-
Notifications
You must be signed in to change notification settings - Fork 5
/
set_command.rb
106 lines (90 loc) · 2.55 KB
/
set_command.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
module BYORedis
class SetCommand < BaseCommand
CommandOption = Struct.new(:kind)
CommandOptionWithValue = Struct.new(:kind, :validator)
OPTIONS = Dict.new
OPTIONS.set(
'ex',
CommandOptionWithValue.new(
'expire',
->(value) { Utils.validate_integer(value) * 1000 },
)
)
OPTIONS.set(
'px',
CommandOptionWithValue.new(
'expire',
->(value) { Utils.validate_integer(value) },
)
)
OPTIONS.set(
'xx', CommandOption.new('presence')
)
OPTIONS.set(
'nx', CommandOption.new('presence')
)
OPTIONS.set(
'keepttl', CommandOption.new('expire')
)
def initialize(db, args)
@db = db
@args = args
@options = Dict.new
end
def call
key, value = @args.shift(2)
if key.nil? || value.nil?
return RESPError.new("ERR wrong number of arguments for 'SET' command")
end
parse_options
if @options['presence'] == 'nx' && [email protected]_store[key].nil?
NullBulkStringInstance
elsif @options['presence'] == 'xx' && @db.data_store[key].nil?
NullBulkStringInstance
else
@db.data_store[key] = value
expire_option = @options['expire']
# The implied third branch is if expire_option == 'KEEPTTL', in which case we don't have
# to do anything
if expire_option.is_a? Integer
@db.expires[key] = (Time.now.to_f * 1000).to_i + expire_option
elsif expire_option.nil?
@db.expires.delete(key)
end
OKSimpleStringInstance
end
end
def self.describe
Describe.new('set', -3, [ 'write', 'denyoom' ], 1, 1, 1, [ '@write', '@string', '@slow' ])
end
private
def parse_options
while @args.any?
option = @args.shift
option_detail = OPTIONS[option.downcase]
if option_detail
option_values = parse_option_arguments(option, option_detail)
existing_option = @options[option_detail.kind]
if existing_option
raise RESPSyntaxError
else
@options[option_detail.kind] = option_values
end
else
raise RESPSyntaxError
end
end
end
def parse_option_arguments(option, option_detail)
case option_detail
when CommandOptionWithValue
option_value = @args.shift
option_detail.validator.call(option_value)
when CommandOption
option.downcase
else
raise "Unknown command option type: #{ option_detail }"
end
end
end
end