Class: GitHub::KV
- Inherits:
-
Object
- Object
- GitHub::KV
- Defined in:
- lib/github/kv.rb
Defined Under Namespace
Classes: MissingConnectionError
Constant Summary collapse
- MAX_KEY_LENGTH =
255
- MAX_VALUE_LENGTH =
65535
- KeyLengthError =
Class.new(StandardError)
- ValueLengthError =
Class.new(StandardError)
Class.new(StandardError)
Instance Method Summary collapse
- #connection ⇒ Object
-
#del(key) ⇒ Object
- del
-
String -> nil.
-
#exists(key) ⇒ Object
- exists
-
String -> Result<Boolean>.
-
#get(key) ⇒ Object
- get
-
String -> Result<String | nil>.
-
#initialize(encapsulated_errors = [SystemCallError], &conn_block) ⇒ KV
constructor
A new instance of KV.
-
#mdel(keys) ⇒ Object
- mdel
-
String -> nil.
-
#mexists(keys) ⇒ Object
- mexists
- String
-
-> Result<>.
-
#mget(keys) ⇒ Object
- mget
- String
-
-> Result<[String | nil]>.
-
#mset(kvs, expires: nil) ⇒ Object
- mset
-
{ String => String }, expires: Time? -> nil.
-
#set(key, value, expires: nil) ⇒ Object
- set
-
String, String, expires: Time? -> nil.
-
#setnx(key, value, expires: nil) ⇒ Object
- setnx
-
String, String, expires: Time? -> Boolean.
Constructor Details
#initialize(encapsulated_errors = [SystemCallError], &conn_block) ⇒ KV
Returns a new instance of KV.
54 55 56 57 |
# File 'lib/github/kv.rb', line 54 def initialize(encapsulated_errors = [SystemCallError], &conn_block) @encapsulated_errors = encapsulated_errors @conn_block = conn_block end |
Instance Method Details
#connection ⇒ Object
59 60 61 |
# File 'lib/github/kv.rb', line 59 def connection @conn_block.try(:call) || (raise MissingConnectionError, "KV must be initialized with a block that returns a connection") end |
#del(key) ⇒ Object
- del
-
String -> nil
Deletes the specified key. Returns nil. Raises on error.
Example:
kv.del("foo")
# => nil
246 247 248 249 250 |
# File 'lib/github/kv.rb', line 246 def del(key) validate_key(key) mdel([key]) end |
#exists(key) ⇒ Object
- exists
-
String -> Result<Boolean>
Checks for existence of the specified key.
Example:
kv.exists("foo")
# => #<Result value: true>
kv.exists("octocat")
# => #<Result value: false>
168 169 170 171 172 |
# File 'lib/github/kv.rb', line 168 def exists(key) validate_key(key) mexists([key]).map { |values| values[0] } end |
#get(key) ⇒ Object
- get
-
String -> Result<String | nil>
Gets the value of the specified key.
Example:
kv.get("foo")
# => #<Result value: "bar">
kv.get("octocat")
# => #<Result value: nil>
75 76 77 78 79 |
# File 'lib/github/kv.rb', line 75 def get(key) validate_key(key) mget([key]).map { |values| values[0] } end |
#mdel(keys) ⇒ Object
- mdel
-
String -> nil
Deletes the specified keys. Returns nil. Raises on error.
Example:
kv.mdel(["foo", "octocat"])
# => nil
261 262 263 264 265 266 267 268 269 270 271 |
# File 'lib/github/kv.rb', line 261 def mdel(keys) validate_key_array(keys) encapsulate_error do GitHub::SQL.run(<<-SQL, :keys => keys, :connection => connection) DELETE FROM key_values WHERE `key` IN :keys SQL end nil end |
#mexists(keys) ⇒ Object
- mexists
- String
-
-> Result<>
Checks for existence of all specified keys. Booleans will be returned in the same order as keys are specified.
Example:
kv.mexists(["foo", "octocat"])
# => #<Result value: [true, false]>
184 185 186 187 188 189 190 191 192 193 194 |
# File 'lib/github/kv.rb', line 184 def mexists(keys) validate_key_array(keys) Result.new { existing_keys = GitHub::SQL.values(<<-SQL, :keys => keys, :connection => connection).to_set SELECT `key` FROM key_values WHERE `key` IN :keys AND (`expires_at` IS NULL OR `expires_at` > NOW()) SQL keys.map { |key| existing_keys.include?(key) } } end |
#mget(keys) ⇒ Object
- mget
- String
-
-> Result<[String | nil]>
Gets the values of all specified keys. Values will be returned in the same order as keys are specified. nil will be returned in place of a String for keys which do not exist.
Example:
kv.mget(["foo", "octocat"])
# => #<Result value: ["bar", nil]
92 93 94 95 96 97 98 99 100 101 102 |
# File 'lib/github/kv.rb', line 92 def mget(keys) validate_key_array(keys) Result.new { kvs = GitHub::SQL.results(<<-SQL, :keys => keys, :connection => connection).to_h SELECT `key`, value FROM key_values WHERE `key` IN :keys AND (`expires_at` IS NULL OR `expires_at` > NOW()) SQL keys.map { |key| kvs[key] } } end |
#mset(kvs, expires: nil) ⇒ Object
- mset
-
{ String => String }, expires: Time? -> nil
Sets the specified hash keys to their associated values, setting them to expire at the specified time. Returns nil. Raises on error.
Example:
kv.mset({ "foo" => "bar", "baz" => "quux" })
# => nil
kv.mset({ "expires" => "soon" }, expires: 1.hour.from_now)
# => nil
134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 |
# File 'lib/github/kv.rb', line 134 def mset(kvs, expires: nil) validate_key_value_hash(kvs) validate_expires(expires) if expires rows = kvs.map { |key, value| [key, value, GitHub::SQL::NOW, GitHub::SQL::NOW, expires || GitHub::SQL::NULL] } encapsulate_error do GitHub::SQL.run(<<-SQL, :rows => GitHub::SQL::ROWS(rows), :connection => connection) INSERT INTO key_values (`key`, value, created_at, updated_at, expires_at) VALUES :rows ON DUPLICATE KEY UPDATE value = VALUES(value), updated_at = VALUES(updated_at), expires_at = VALUES(expires_at) SQL end nil end |
#set(key, value, expires: nil) ⇒ Object
- set
-
String, String, expires: Time? -> nil
Sets the specified key to the specified value. Returns nil. Raises on error.
Example:
kv.set("foo", "bar")
# => nil
114 115 116 117 118 119 |
# File 'lib/github/kv.rb', line 114 def set(key, value, expires: nil) validate_key(key) validate_value(value) mset({ key => value }, expires: expires) end |
#setnx(key, value, expires: nil) ⇒ Object
- setnx
-
String, String, expires: Time? -> Boolean
Sets the specified key to the specified value only if it does not already exist.
Returns true if the key was set, false otherwise. Raises on error.
Example:
kv.setnx("foo", "bar")
# => false
kv.setnx("octocat", "monalisa")
# => true
kv.setnx("expires", "soon", expires: 1.hour.from_now)
# => true
214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 |
# File 'lib/github/kv.rb', line 214 def setnx(key, value, expires: nil) validate_key(key) validate_value(value) validate_expires(expires) if expires encapsulate_error { # if the key already exists but has expired, prune it first. We could # achieve the same thing with the right INSERT ... ON DUPLICATE KEY UPDATE # query, but then we would not be able to rely on affected_rows GitHub::SQL.run(<<-SQL, :key => key, :connection => connection) DELETE FROM key_values WHERE `key` = :key AND expires_at <= NOW() SQL sql = GitHub::SQL.run(<<-SQL, :key => key, :value => value, :expires => expires || GitHub::SQL::NULL, :connection => connection) INSERT IGNORE INTO key_values (`key`, value, created_at, updated_at, expires_at) VALUES (:key, :value, NOW(), NOW(), :expires) SQL sql.affected_rows > 0 } end |