kayvee 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.gitignore +16 -0
- data/.rspec +2 -0
- data/.travis.yml +3 -0
- data/Gemfile +3 -0
- data/LICENSE.txt +22 -0
- data/README.md +41 -0
- data/Rakefile +7 -0
- data/bin/console +7 -0
- data/kayvee.gemspec +30 -0
- data/lib/ext/string.rb +20 -0
- data/lib/kayvee.rb +10 -0
- data/lib/kayvee/clients.rb +7 -0
- data/lib/kayvee/clients/key_value_store_client.rb +56 -0
- data/lib/kayvee/clients/memory.rb +36 -0
- data/lib/kayvee/clients/redis.rb +43 -0
- data/lib/kayvee/clients/s3.rb +102 -0
- data/lib/kayvee/clients/test.rb +9 -0
- data/lib/kayvee/key.rb +55 -0
- data/lib/kayvee/store.rb +80 -0
- data/lib/kayvee/version.rb +4 -0
- data/spec/integration_spec.rb +39 -0
- data/spec/kayvee/clients/s3_spec.rb +31 -0
- data/spec/kayvee/key_spec.rb +75 -0
- data/spec/kayvee/store_spec.rb +43 -0
- data/spec/kayvee_spec.rb +7 -0
- data/spec/spec_helper.rb +8 -0
- metadata +177 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 7b7440687be4ffbb147a691a428c880bc65de7d1
|
4
|
+
data.tar.gz: 1b40a0dcdbf76535d2d1ce659f4b0bd729a7072c
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 18fc9d630e81cfb4d31eac0db406121e8c40e77a86cfec796a8533fabf91295adfebac6e3cc9c424628c8ec314319d02a1d3fedbd18e5bc50f4378bf5b3f9c32
|
7
|
+
data.tar.gz: e423182c89d0705fc8775f9acdf560f2625bd73842d210d8477ed9c1ee0ad25ff06866e8019d83c7de9a02437312a1d454cdb41c164cd1571a26bfc28cbf17c0
|
data/.gitignore
ADDED
data/.rspec
ADDED
data/.travis.yml
ADDED
data/Gemfile
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2016 Taylor Finnell
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,41 @@
|
|
1
|
+
# Kayvee
|
2
|
+
|
3
|
+
A simple key value store with multiple backing implementations.
|
4
|
+
|
5
|
+
## Installation
|
6
|
+
|
7
|
+
Add this line to your application's Gemfile:
|
8
|
+
|
9
|
+
```ruby
|
10
|
+
gem 'kayvee'
|
11
|
+
```
|
12
|
+
|
13
|
+
And then execute:
|
14
|
+
|
15
|
+
$ bundle
|
16
|
+
|
17
|
+
Or install it yourself as:
|
18
|
+
|
19
|
+
$ gem install kayvee
|
20
|
+
|
21
|
+
## Usage
|
22
|
+
|
23
|
+
```
|
24
|
+
store = Kayvee::Store.new(:s3, aws_access_key: '', ... )
|
25
|
+
key = store.set('hello', 'world')
|
26
|
+
key.read
|
27
|
+
=> 'world'
|
28
|
+
|
29
|
+
store = Kayvee::Store.new(:redis, host: 'redis://locahost')
|
30
|
+
key = store.set('hello', 'world')
|
31
|
+
key.read
|
32
|
+
=> 'world'
|
33
|
+
```
|
34
|
+
|
35
|
+
## Contributing
|
36
|
+
|
37
|
+
1. Fork it ( https://github.com/[my-github-username]/kayvee/fork )
|
38
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
39
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
40
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
41
|
+
5. Create a new Pull Request
|
data/Rakefile
ADDED
data/bin/console
ADDED
data/kayvee.gemspec
ADDED
@@ -0,0 +1,30 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'kayvee/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = 'kayvee'
|
8
|
+
spec.version = Kayvee::VERSION
|
9
|
+
spec.authors = ['Taylor Finnell']
|
10
|
+
spec.email = ['tmfinnell@gmail.com']
|
11
|
+
spec.summary = %q{Key value library with numerous backing implementations.}
|
12
|
+
spec.description = %q{Key value library with numerous backing implementations.}
|
13
|
+
spec.homepage = "http://github.com/taylorfinnell"
|
14
|
+
spec.license = "MIT"
|
15
|
+
|
16
|
+
spec.files = `git ls-files -z`.split("\x0")
|
17
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
18
|
+
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
19
|
+
spec.require_paths = ['lib', 'lib/ext']
|
20
|
+
|
21
|
+
|
22
|
+
spec.add_development_dependency 'bundler', '~> 1.7'
|
23
|
+
spec.add_development_dependency 'rake', '~> 10.0'
|
24
|
+
spec.add_development_dependency 'rspec'
|
25
|
+
spec.add_development_dependency 'pry'
|
26
|
+
spec.add_development_dependency 'dotenv'
|
27
|
+
|
28
|
+
spec.add_development_dependency 's3'
|
29
|
+
spec.add_development_dependency 'redis'
|
30
|
+
end
|
data/lib/ext/string.rb
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
class String
|
2
|
+
def constantize
|
3
|
+
names = self.split('::')
|
4
|
+
names.shift if names.empty? || names.first.empty?
|
5
|
+
|
6
|
+
constant = Object
|
7
|
+
names.each do |name|
|
8
|
+
constant = constant.const_get(name, false) || constant.const_missing(name)
|
9
|
+
end
|
10
|
+
constant
|
11
|
+
end
|
12
|
+
|
13
|
+
def demodulize
|
14
|
+
if i = self.rindex('::')
|
15
|
+
self[(i+2)..-1]
|
16
|
+
else
|
17
|
+
self
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
data/lib/kayvee.rb
ADDED
@@ -0,0 +1,56 @@
|
|
1
|
+
module Kayvee
|
2
|
+
module Clients
|
3
|
+
# Represents the interfaces required to have a proper client for the
|
4
|
+
# Kayvee::Store
|
5
|
+
#
|
6
|
+
# @see Kayvee::Store
|
7
|
+
# @see Kayvee::Clients
|
8
|
+
module KeyValueStoreClient
|
9
|
+
# Raised when a client has not implemented a required method
|
10
|
+
InterfaceNotImplementedError = Class.new(NotImplementedError)
|
11
|
+
|
12
|
+
# Raised in validate_config! if invalid config is found
|
13
|
+
OptionMissingError = Class.new(NotImplementedError)
|
14
|
+
|
15
|
+
def self.included(base)
|
16
|
+
base.send(:include, InstanceMethods)
|
17
|
+
end
|
18
|
+
|
19
|
+
module InstanceMethods
|
20
|
+
attr_reader :options
|
21
|
+
|
22
|
+
# @param [String] path the path to convert to a url
|
23
|
+
#
|
24
|
+
# @return [String] the url
|
25
|
+
def url(path)
|
26
|
+
raise InterfaceNotImplementedError.new
|
27
|
+
end
|
28
|
+
|
29
|
+
# @param [String] path the path to read
|
30
|
+
#
|
31
|
+
# @return [String\nil] the read string or nil if key does not exist
|
32
|
+
def read(path)
|
33
|
+
raise InterfaceNotImplementedError.new
|
34
|
+
end
|
35
|
+
|
36
|
+
# @param [String] path the path to read
|
37
|
+
# @param [String] value the value to set
|
38
|
+
#
|
39
|
+
# @return [Key] the key modified
|
40
|
+
def write(path, value)
|
41
|
+
raise InterfaceNotImplementedError.new
|
42
|
+
end
|
43
|
+
|
44
|
+
def write_io(path, io)
|
45
|
+
raise InterfaceNotImplementedError.new
|
46
|
+
end
|
47
|
+
|
48
|
+
private
|
49
|
+
|
50
|
+
def validate_options!
|
51
|
+
raise InterfaceNotImplementedError.new
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
module Kayvee
|
2
|
+
module Clients
|
3
|
+
# An in memory kv store
|
4
|
+
class Memory
|
5
|
+
include KeyValueStoreClient
|
6
|
+
|
7
|
+
# @param [Hash] options for the client
|
8
|
+
def initialize(options)
|
9
|
+
@options = options
|
10
|
+
validate_options!
|
11
|
+
@store = {}
|
12
|
+
end
|
13
|
+
|
14
|
+
# @param [String] path the path to read
|
15
|
+
#
|
16
|
+
# @return [String\nil] the read string or nil if key does not exist
|
17
|
+
def read(path)
|
18
|
+
@store[path]
|
19
|
+
end
|
20
|
+
|
21
|
+
# @param [String] path the path to read
|
22
|
+
# @param [String] value the value to set
|
23
|
+
#
|
24
|
+
# @return [Key] the modified key
|
25
|
+
def write(path, value)
|
26
|
+
@store[path] = value
|
27
|
+
end
|
28
|
+
|
29
|
+
private
|
30
|
+
|
31
|
+
def validate_options!
|
32
|
+
true
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
begin
|
2
|
+
require 'redis'
|
3
|
+
rescue LoadError => e
|
4
|
+
raise "You must include the 'redis' gem in your Gemfile"
|
5
|
+
end
|
6
|
+
|
7
|
+
module Kayvee
|
8
|
+
module Clients
|
9
|
+
# An redis backed kv store
|
10
|
+
class Redis
|
11
|
+
include KeyValueStoreClient
|
12
|
+
|
13
|
+
# @param [Hash] options for the client
|
14
|
+
def initialize(options)
|
15
|
+
@options = options
|
16
|
+
validate_options!
|
17
|
+
|
18
|
+
@store = ::Redis.new(url: 'redis://localhost')
|
19
|
+
end
|
20
|
+
|
21
|
+
# @param [String] path the path to read
|
22
|
+
#
|
23
|
+
# @return [String\nil] the read string or nil if key does not exist
|
24
|
+
def read(path)
|
25
|
+
@store.get(path)
|
26
|
+
end
|
27
|
+
|
28
|
+
# @param [String] path the path to read
|
29
|
+
# @param [String] value the value to set
|
30
|
+
#
|
31
|
+
# @return [Key] the modified key
|
32
|
+
def write(path, value)
|
33
|
+
@store.set(path, value)
|
34
|
+
end
|
35
|
+
|
36
|
+
private
|
37
|
+
|
38
|
+
def validate_options!
|
39
|
+
true
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
@@ -0,0 +1,102 @@
|
|
1
|
+
begin
|
2
|
+
require 's3'
|
3
|
+
rescue LoadError => e
|
4
|
+
raise "You must include the s3 gem in your Gemfile"
|
5
|
+
end
|
6
|
+
|
7
|
+
module Kayvee
|
8
|
+
module Clients
|
9
|
+
# An s3 backed kv store
|
10
|
+
class S3
|
11
|
+
include KeyValueStoreClient
|
12
|
+
|
13
|
+
InvalidBucketError = Class.new(StandardError)
|
14
|
+
|
15
|
+
def initialize(options)
|
16
|
+
@options = options
|
17
|
+
validate_options!
|
18
|
+
|
19
|
+
@s3 = ::S3::Service.new(access_key_id: aws_access_key,
|
20
|
+
secret_access_key: aws_secret_key)
|
21
|
+
end
|
22
|
+
|
23
|
+
# Gets an s3 url for the key
|
24
|
+
#
|
25
|
+
# @param [String] path the path to read
|
26
|
+
#
|
27
|
+
# @return [String] the url
|
28
|
+
def url(path)
|
29
|
+
get(path).temporary_url
|
30
|
+
end
|
31
|
+
|
32
|
+
# @param [String] path the path to read
|
33
|
+
#
|
34
|
+
# @return [String\nil] the read string or nil if key does not exist
|
35
|
+
def read(path)
|
36
|
+
begin
|
37
|
+
value = nil
|
38
|
+
obj = get(path)
|
39
|
+
value = obj.content if obj
|
40
|
+
value
|
41
|
+
rescue ::S3::Error::NoSuchKey => e
|
42
|
+
nil
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
# @param [String/IO] path the path to read
|
47
|
+
# @param [String] value the value to set
|
48
|
+
#
|
49
|
+
# @return [Key] the modified key
|
50
|
+
def write(path, value)
|
51
|
+
obj = build(path)
|
52
|
+
obj.content = value
|
53
|
+
obj.save
|
54
|
+
end
|
55
|
+
|
56
|
+
def exists?(path)
|
57
|
+
get(path).exists?
|
58
|
+
end
|
59
|
+
|
60
|
+
private
|
61
|
+
|
62
|
+
def build(path)
|
63
|
+
bucket.objects.build(path)
|
64
|
+
end
|
65
|
+
|
66
|
+
def get(path)
|
67
|
+
bucket.objects.find(path)
|
68
|
+
end
|
69
|
+
|
70
|
+
def bucket
|
71
|
+
if bucket = @s3.buckets.find(bucket_name)
|
72
|
+
bucket
|
73
|
+
else
|
74
|
+
raise InvalidBucketError, "bucket #{bucket_name} is invalid"
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
def validate_options!
|
79
|
+
raise OptionMissingError.new, 'missing aws key' unless aws_access_key
|
80
|
+
raise OptionMissingError.new, 'missing aws secret' unless aws_secret_key
|
81
|
+
raise OptionMissingError.new, 'missing bucket name' unless bucket_name
|
82
|
+
raise OptionMissingError.new, 'missing prefix' unless prefix
|
83
|
+
end
|
84
|
+
|
85
|
+
def prefix
|
86
|
+
options[:prefix]
|
87
|
+
end
|
88
|
+
|
89
|
+
def bucket_name
|
90
|
+
options[:bucket_name]
|
91
|
+
end
|
92
|
+
|
93
|
+
def aws_access_key
|
94
|
+
options[:aws_access_key]
|
95
|
+
end
|
96
|
+
|
97
|
+
def aws_secret_key
|
98
|
+
options[:aws_secret_key]
|
99
|
+
end
|
100
|
+
end
|
101
|
+
end
|
102
|
+
end
|
data/lib/kayvee/key.rb
ADDED
@@ -0,0 +1,55 @@
|
|
1
|
+
module Kayvee
|
2
|
+
# Represents a key that can hold a value.
|
3
|
+
class Key
|
4
|
+
# The path of the key
|
5
|
+
# @todo this should be named key, probably
|
6
|
+
attr_reader :path
|
7
|
+
|
8
|
+
# @param [Kayvee::Clients::KeyValueStoreClient] client the client to use to back the key
|
9
|
+
# @param [String] path the path of the key
|
10
|
+
# @param [String] value the value of the key
|
11
|
+
def initialize(client, path, value = nil)
|
12
|
+
@client = client
|
13
|
+
@path = path
|
14
|
+
@value = value
|
15
|
+
@mutex = Mutex.new
|
16
|
+
end
|
17
|
+
|
18
|
+
def exists?
|
19
|
+
begin
|
20
|
+
@client.exists?(@path)
|
21
|
+
rescue ::S3::Error::NoSuchKey => e
|
22
|
+
nil
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
# Returns a public url for the given path
|
27
|
+
def url
|
28
|
+
@mutex.synchronize { @client.url(@path) }
|
29
|
+
end
|
30
|
+
|
31
|
+
# Reads the value of the key, if the value is been read it returns it. If the value
|
32
|
+
# has not yet been read it reaches out to the client
|
33
|
+
#
|
34
|
+
# @return [String\nil] the value of the key or nil if key does not exist
|
35
|
+
def read
|
36
|
+
@mutex.synchronize do
|
37
|
+
@value ||= @client.read(@path)
|
38
|
+
@value
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
# Writes a contents string to the key
|
43
|
+
#
|
44
|
+
# @param [String] contents the contents to set in the key
|
45
|
+
#
|
46
|
+
# @return the modified or created key
|
47
|
+
def write(contents)
|
48
|
+
@mutex.synchronize do
|
49
|
+
@value = contents
|
50
|
+
@client.write(@path, @value)
|
51
|
+
self
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
data/lib/kayvee/store.rb
ADDED
@@ -0,0 +1,80 @@
|
|
1
|
+
module Kayvee
|
2
|
+
# Represents a simple key value store. Provides multiple backing stores.
|
3
|
+
#
|
4
|
+
# @example Basic Useage
|
5
|
+
# store = Kayvee::Store.new(:s3, aws_access_key: '', ... )
|
6
|
+
# key = store.set('hello', 'world')
|
7
|
+
# key.read
|
8
|
+
# => 'world'
|
9
|
+
#
|
10
|
+
# store = Kayvee::Store.new(:redis, host: 'redis://locahost')
|
11
|
+
# key = store.set('hello', 'world')
|
12
|
+
# key.read
|
13
|
+
# => 'world'
|
14
|
+
#
|
15
|
+
# @see Kayvee::Clients::S3
|
16
|
+
# @see Kayvee::Clients::Redis
|
17
|
+
# @see Kayvee::Clients::Memory
|
18
|
+
# @see Kayvee::Clients::Test
|
19
|
+
class Store
|
20
|
+
# Raised when a client implementation can not be found.
|
21
|
+
ClientNotFound = Class.new(Exception)
|
22
|
+
|
23
|
+
# The internal client driving the store
|
24
|
+
attr_reader :client
|
25
|
+
|
26
|
+
# @param [Symbol] client the symbol representing the client to use. :s3, :redis, :memory, :test
|
27
|
+
# @param [Options] options the config for the client implementation
|
28
|
+
#
|
29
|
+
# @see Kayvee::Clients::S3
|
30
|
+
# @see Kayvee::Clients::Redis
|
31
|
+
# @see Kayvee::Clients::Memory
|
32
|
+
# @see Kayvee::Clients::Test
|
33
|
+
def initialize(client = :s3, options = {})
|
34
|
+
load_client(client)
|
35
|
+
@client = instantiate_client(client, options)
|
36
|
+
end
|
37
|
+
|
38
|
+
# Sets a given key to a given value
|
39
|
+
#
|
40
|
+
# @param [String] path the path to set
|
41
|
+
# @param [String] value the value to set
|
42
|
+
#
|
43
|
+
# @return [Key] the newly created or modified key object
|
44
|
+
def set(path, value)
|
45
|
+
key = Kayvee::Key.new(@client, path)
|
46
|
+
key.write(value)
|
47
|
+
key
|
48
|
+
end
|
49
|
+
alias :[]= :set
|
50
|
+
|
51
|
+
# Gets a given keys value
|
52
|
+
#
|
53
|
+
# @param [String] path the path to set
|
54
|
+
#
|
55
|
+
# @return [Key] the value of the key
|
56
|
+
def get(path)
|
57
|
+
Kayvee::Key.new(@client, path)
|
58
|
+
end
|
59
|
+
alias :[] :get
|
60
|
+
|
61
|
+
private
|
62
|
+
|
63
|
+
def instantiate_client(client, options)
|
64
|
+
begin
|
65
|
+
klass = "Kayvee::Clients::#{client.capitalize}".constantize
|
66
|
+
klass.new(options)
|
67
|
+
rescue NameError
|
68
|
+
raise ClientNotFound.new
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
def load_client(client)
|
73
|
+
begin
|
74
|
+
require "kayvee/clients/#{client}"
|
75
|
+
rescue LoadError => load_error
|
76
|
+
raise LoadError.new("Cannot find Kayvee::Clients::#{client.capitalize} adapter '#{client}' (#{load_error.message})")
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'securerandom'
|
3
|
+
|
4
|
+
module Kayvee
|
5
|
+
[:redis, :s3, :memory].each do |impl|
|
6
|
+
describe "a working #{impl} implementation" do
|
7
|
+
before do
|
8
|
+
@opts = {}
|
9
|
+
|
10
|
+
case impl
|
11
|
+
when :s3
|
12
|
+
@opts.merge!({
|
13
|
+
aws_access_key: ENV['AWS_ACCESS_KEY'],
|
14
|
+
aws_secret_key: ENV['AWS_SECRET_KEY'],
|
15
|
+
bucket_name: ENV['AWS_BUCKET'],
|
16
|
+
prefix: ENV['AWS_PREFIX']
|
17
|
+
})
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
it 'can get and set keys' do
|
22
|
+
key = SecureRandom.uuid
|
23
|
+
value = 'test'
|
24
|
+
|
25
|
+
store = Store.new(impl, @opts)
|
26
|
+
store.set(key, value)
|
27
|
+
|
28
|
+
expect(store.get(key).read).to eq(value)
|
29
|
+
end
|
30
|
+
|
31
|
+
it 'can handle non existant keys' do
|
32
|
+
key = SecureRandom.uuid
|
33
|
+
store = Store.new(impl, @opts)
|
34
|
+
|
35
|
+
expect(store.get(key).read).to eq(nil)
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'kayvee/clients/s3'
|
3
|
+
|
4
|
+
module Kayvee
|
5
|
+
module Clients
|
6
|
+
describe S3 do
|
7
|
+
before do
|
8
|
+
@s3 = S3.new({
|
9
|
+
aws_access_key: ENV['AWS_ACCESS_KEY'],
|
10
|
+
aws_secret_key: ENV['AWS_SECRET_KEY'],
|
11
|
+
bucket_name: ENV['AWS_BUCKET'],
|
12
|
+
prefix: ENV['AWS_PREFIX']
|
13
|
+
})
|
14
|
+
end
|
15
|
+
|
16
|
+
describe '#write' do
|
17
|
+
it 'can write a string' do
|
18
|
+
@s3.write('test', 'sup')
|
19
|
+
|
20
|
+
expect(@s3.read('test')).to eq('sup')
|
21
|
+
end
|
22
|
+
|
23
|
+
it 'can write an io' do
|
24
|
+
@s3.write('test', StringIO.new('sup'))
|
25
|
+
|
26
|
+
expect(@s3.read('test')).to eq('sup')
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,75 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'kayvee/clients/test'
|
3
|
+
|
4
|
+
module Kayvee
|
5
|
+
describe Key do
|
6
|
+
before do
|
7
|
+
@options = {}
|
8
|
+
@client = Clients::Test.new(@options)
|
9
|
+
@path = double
|
10
|
+
@value = double
|
11
|
+
end
|
12
|
+
|
13
|
+
describe 'initialize' do
|
14
|
+
it 'sets a client and path' do
|
15
|
+
key = Key.new(@client, @path)
|
16
|
+
|
17
|
+
expect(key.path).to eq(@path)
|
18
|
+
expect(key.instance_variable_get(:@client)).to eq(@client)
|
19
|
+
expect(key.instance_variable_get(:@value)).to eq(nil)
|
20
|
+
end
|
21
|
+
|
22
|
+
it 'can set a value' do
|
23
|
+
key = Key.new(@client, @path, @value)
|
24
|
+
|
25
|
+
expect(key.path).to eq(@path)
|
26
|
+
expect(key.instance_variable_get(:@client)).to eq(@client)
|
27
|
+
expect(key.instance_variable_get(:@value)).to eq(@value)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
describe 'read' do
|
32
|
+
it 'returns the value if set' do
|
33
|
+
key = Key.new(@client, @path, @value)
|
34
|
+
|
35
|
+
expect(key.read).to eq(@value)
|
36
|
+
end
|
37
|
+
|
38
|
+
it 'returns nil if the value is not set' do
|
39
|
+
key = Key.new(@client, @path)
|
40
|
+
|
41
|
+
expect(key.read).to eq(nil)
|
42
|
+
end
|
43
|
+
|
44
|
+
it 'returns the written value' do
|
45
|
+
key = Key.new(@client, @path)
|
46
|
+
key.write(@value)
|
47
|
+
|
48
|
+
expect(key.read).to eq(@value)
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
describe 'write' do
|
53
|
+
it 'sets the key value' do
|
54
|
+
key = Key.new(@client, @path)
|
55
|
+
key.write(@value)
|
56
|
+
|
57
|
+
expect(key.read).to eq(@value)
|
58
|
+
end
|
59
|
+
|
60
|
+
it 'writes the value via the client' do
|
61
|
+
key = Key.new(@client, @path)
|
62
|
+
key.write(@value)
|
63
|
+
|
64
|
+
expect(key.read).to eq(@value)
|
65
|
+
end
|
66
|
+
|
67
|
+
it 'returns the key' do
|
68
|
+
key = Key.new(@client, @path)
|
69
|
+
ret = key.write(@value)
|
70
|
+
|
71
|
+
expect(ret).to be_a(Kayvee::Key)
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
module Kayvee
|
4
|
+
describe Store do
|
5
|
+
describe 'initialize' do
|
6
|
+
it 'creates a client from a symbol' do
|
7
|
+
store = Store.new(:test)
|
8
|
+
|
9
|
+
expect(store.client).to be_a(Kayvee::Clients::Test)
|
10
|
+
end
|
11
|
+
|
12
|
+
it 'passes options to the client' do
|
13
|
+
options = double
|
14
|
+
expect(Kayvee::Clients::Test).to receive(:new).with(options)
|
15
|
+
|
16
|
+
Store.new(:test, options)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
describe 'get' do
|
21
|
+
it 'returns a key object with for the given path' do
|
22
|
+
store = Kayvee::Store.new(:test)
|
23
|
+
key = store.get('test')
|
24
|
+
|
25
|
+
expect(key).to be_a(Kayvee::Key)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
describe 'set' do
|
30
|
+
it 'sets a key\'s value and returns the key' do
|
31
|
+
path, value = 'test', 'test'
|
32
|
+
|
33
|
+
expect_any_instance_of(Kayvee::Key).to receive(:write).with(value)
|
34
|
+
|
35
|
+
store = Kayvee::Store.new(:test)
|
36
|
+
key = store.set(path, value)
|
37
|
+
|
38
|
+
expect(key).to be_a(Kayvee::Key)
|
39
|
+
expect(key.path).to eq(path)
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
data/spec/kayvee_spec.rb
ADDED
data/spec/spec_helper.rb
ADDED
metadata
ADDED
@@ -0,0 +1,177 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: kayvee
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Taylor Finnell
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2016-06-06 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: bundler
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '1.7'
|
20
|
+
type: :development
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '1.7'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: rake
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '10.0'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '10.0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: rspec
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - ">="
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - ">="
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: pry
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - ">="
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - ">="
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '0'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: dotenv
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - ">="
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '0'
|
76
|
+
type: :development
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - ">="
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '0'
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: s3
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - ">="
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '0'
|
90
|
+
type: :development
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - ">="
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: '0'
|
97
|
+
- !ruby/object:Gem::Dependency
|
98
|
+
name: redis
|
99
|
+
requirement: !ruby/object:Gem::Requirement
|
100
|
+
requirements:
|
101
|
+
- - ">="
|
102
|
+
- !ruby/object:Gem::Version
|
103
|
+
version: '0'
|
104
|
+
type: :development
|
105
|
+
prerelease: false
|
106
|
+
version_requirements: !ruby/object:Gem::Requirement
|
107
|
+
requirements:
|
108
|
+
- - ">="
|
109
|
+
- !ruby/object:Gem::Version
|
110
|
+
version: '0'
|
111
|
+
description: Key value library with numerous backing implementations.
|
112
|
+
email:
|
113
|
+
- tmfinnell@gmail.com
|
114
|
+
executables:
|
115
|
+
- console
|
116
|
+
extensions: []
|
117
|
+
extra_rdoc_files: []
|
118
|
+
files:
|
119
|
+
- ".gitignore"
|
120
|
+
- ".rspec"
|
121
|
+
- ".travis.yml"
|
122
|
+
- Gemfile
|
123
|
+
- LICENSE.txt
|
124
|
+
- README.md
|
125
|
+
- Rakefile
|
126
|
+
- bin/console
|
127
|
+
- kayvee.gemspec
|
128
|
+
- lib/ext/string.rb
|
129
|
+
- lib/kayvee.rb
|
130
|
+
- lib/kayvee/clients.rb
|
131
|
+
- lib/kayvee/clients/key_value_store_client.rb
|
132
|
+
- lib/kayvee/clients/memory.rb
|
133
|
+
- lib/kayvee/clients/redis.rb
|
134
|
+
- lib/kayvee/clients/s3.rb
|
135
|
+
- lib/kayvee/clients/test.rb
|
136
|
+
- lib/kayvee/key.rb
|
137
|
+
- lib/kayvee/store.rb
|
138
|
+
- lib/kayvee/version.rb
|
139
|
+
- spec/integration_spec.rb
|
140
|
+
- spec/kayvee/clients/s3_spec.rb
|
141
|
+
- spec/kayvee/key_spec.rb
|
142
|
+
- spec/kayvee/store_spec.rb
|
143
|
+
- spec/kayvee_spec.rb
|
144
|
+
- spec/spec_helper.rb
|
145
|
+
homepage: http://github.com/taylorfinnell
|
146
|
+
licenses:
|
147
|
+
- MIT
|
148
|
+
metadata: {}
|
149
|
+
post_install_message:
|
150
|
+
rdoc_options: []
|
151
|
+
require_paths:
|
152
|
+
- lib
|
153
|
+
- lib/ext
|
154
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
155
|
+
requirements:
|
156
|
+
- - ">="
|
157
|
+
- !ruby/object:Gem::Version
|
158
|
+
version: '0'
|
159
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
160
|
+
requirements:
|
161
|
+
- - ">="
|
162
|
+
- !ruby/object:Gem::Version
|
163
|
+
version: '0'
|
164
|
+
requirements: []
|
165
|
+
rubyforge_project:
|
166
|
+
rubygems_version: 2.4.5
|
167
|
+
signing_key:
|
168
|
+
specification_version: 4
|
169
|
+
summary: Key value library with numerous backing implementations.
|
170
|
+
test_files:
|
171
|
+
- spec/integration_spec.rb
|
172
|
+
- spec/kayvee/clients/s3_spec.rb
|
173
|
+
- spec/kayvee/key_spec.rb
|
174
|
+
- spec/kayvee/store_spec.rb
|
175
|
+
- spec/kayvee_spec.rb
|
176
|
+
- spec/spec_helper.rb
|
177
|
+
has_rdoc:
|