kybus-storage 0.1.3
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/lib/kybus/storage.rb +4 -0
- data/lib/kybus/storage/datasource/exceptions.rb +35 -0
- data/lib/kybus/storage/datasource/id_generators.rb +24 -0
- data/lib/kybus/storage/datasource/json_repository.rb +59 -0
- data/lib/kybus/storage/datasource/model.rb +61 -0
- data/lib/kybus/storage/datasource/repository.rb +47 -0
- data/lib/kybus/storage/datasource/sequel.rb +54 -0
- data/lib/kybus/storage/factory.rb +30 -0
- data/lib/kybus/storage/repository.rb +26 -0
- data/lib/kybus/version.rb +7 -0
- metadata +209 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 267acec6efe373f72b3ad93d62e35024e16488f00d545e7c6397f1d84eeb6aed
|
4
|
+
data.tar.gz: ffe13306342e8912e4e0099a7a3578bc31ac64c1c16b79e357ba505d7f2f9940
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: c05cca8825043a1b24d795429b40c16bee12a312e14a055df1886d0fdb9fad2322bcd8dff739493eda0abff6a7ea635c7642283f47823a9db36c009d4a422071
|
7
|
+
data.tar.gz: a15ef29b8950a5c4b94bd6d6ad4b969a17ec480ddbab72aad657d0487f156d5296ac8a26b07d7564b8b09f95dedfc7a868f547cfcf5475627e4c2bb3401b89f3
|
@@ -0,0 +1,35 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'kybus/exceptions'
|
4
|
+
module Kybus
|
5
|
+
module Storage
|
6
|
+
module Exceptions
|
7
|
+
# Exception used when there is an object trying to be created but it
|
8
|
+
# already exists.
|
9
|
+
class ObjectAlreadyExists < Kybus::Exceptions::AntFail
|
10
|
+
attr_reader :id
|
11
|
+
def initialize(id, object)
|
12
|
+
@id = id
|
13
|
+
super("Object #{id} already exists", nil, object)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
# Exception used when a value on a model violates the restrictions
|
18
|
+
# from the validators.
|
19
|
+
class ValidationErrors < Kybus::Exceptions::AntFail
|
20
|
+
def initialize(data)
|
21
|
+
super('Error while validating object', 'ValidationErrors', data)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
# Exception used when it is requested an object that can not be found.
|
26
|
+
class ObjectNotFound < Kybus::Exceptions::AntFail
|
27
|
+
attr_reader :id
|
28
|
+
def initialize(id)
|
29
|
+
@id = id
|
30
|
+
super("Object #{id} does not exist", nil, id: id)
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Kybus
|
4
|
+
module Storage
|
5
|
+
module Datasource
|
6
|
+
# This class was meant to handle the complexity of extracting the
|
7
|
+
# primary key from an object that belongs to a model. This might get
|
8
|
+
# deprecated or suffer a huge refactor.
|
9
|
+
class IDGenerators
|
10
|
+
extend DRY::ResourceInjector
|
11
|
+
def self.[](key)
|
12
|
+
resource(:generators, key)
|
13
|
+
end
|
14
|
+
|
15
|
+
def self.normalize_id(object, key)
|
16
|
+
object.is_a?(Hash) || object.nil? ? object[key] : object
|
17
|
+
end
|
18
|
+
|
19
|
+
id_generator = ->(id, key) { normalize_id(id, key) }
|
20
|
+
register(:generators, :id, id_generator)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,59 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative 'repository'
|
4
|
+
require_relative 'id_generators'
|
5
|
+
require_relative 'model'
|
6
|
+
require 'fileutils'
|
7
|
+
|
8
|
+
module Kybus
|
9
|
+
module Storage
|
10
|
+
module Datasource
|
11
|
+
# Stores objects as a plain json file inside the specified folder.
|
12
|
+
# Uses this for testing purpouse.
|
13
|
+
class JSONRepository < Repository
|
14
|
+
def self.from_config(conf)
|
15
|
+
folder = conf['storage']
|
16
|
+
folder.gsub!('$name', conf['schema_name']) if conf['schema_name']
|
17
|
+
if conf['schema'].nil?
|
18
|
+
# TODO: decouple use of classes
|
19
|
+
new(folder, conf['primary_key'].to_sym,
|
20
|
+
IDGenerators[:id])
|
21
|
+
else
|
22
|
+
# TODO: This line is very high coupled to kybus-nanoservice
|
23
|
+
new(folder, conf['schema']::PRIMARY_KEY, IDGenerators[:id])
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
def initialize(folder, id, id_generator)
|
28
|
+
@path = folder
|
29
|
+
FileUtils.mkdir_p folder
|
30
|
+
super(id, id_generator)
|
31
|
+
end
|
32
|
+
|
33
|
+
def get(id)
|
34
|
+
path = full_path(id)
|
35
|
+
raise(ObjectNotFound, id) unless File.file?(path)
|
36
|
+
|
37
|
+
contents = File.read(path)
|
38
|
+
JSON.parse(contents, symbolize_names: true)
|
39
|
+
end
|
40
|
+
|
41
|
+
def create_(data)
|
42
|
+
store(data)
|
43
|
+
data
|
44
|
+
end
|
45
|
+
|
46
|
+
def store(data)
|
47
|
+
id = data[@id]
|
48
|
+
File.write(full_path(id), data.to_json)
|
49
|
+
end
|
50
|
+
|
51
|
+
private
|
52
|
+
|
53
|
+
def full_path(id)
|
54
|
+
"#{@path}/#{id}.json"
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
@@ -0,0 +1,61 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'json'
|
4
|
+
require_relative 'id_generators'
|
5
|
+
|
6
|
+
module Kybus
|
7
|
+
module Storage
|
8
|
+
module Datasource
|
9
|
+
# Wraps an object inside a model, this will allow to validate that
|
10
|
+
# values are inside the restrictions. It dependes on a repository
|
11
|
+
# for storing values.
|
12
|
+
class Model
|
13
|
+
attr_reader :data
|
14
|
+
attr_writer :data
|
15
|
+
|
16
|
+
# :nocov: #
|
17
|
+
def run_validations!
|
18
|
+
puts 'WARN: model with no validations'
|
19
|
+
end
|
20
|
+
# :nocov: #
|
21
|
+
|
22
|
+
def []=(key, val)
|
23
|
+
@data[key] = val
|
24
|
+
end
|
25
|
+
|
26
|
+
def [](key)
|
27
|
+
@data[key]
|
28
|
+
end
|
29
|
+
|
30
|
+
def store
|
31
|
+
run_validations!
|
32
|
+
@repository.store(@data)
|
33
|
+
end
|
34
|
+
|
35
|
+
def create
|
36
|
+
run_validations!
|
37
|
+
@repository.create(@data)
|
38
|
+
end
|
39
|
+
|
40
|
+
def initialize(data)
|
41
|
+
@data = data
|
42
|
+
end
|
43
|
+
|
44
|
+
attr_writer :repository
|
45
|
+
|
46
|
+
def to_json(options = nil)
|
47
|
+
@data.to_json(options)
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
# This class is for explicit usage of models without validations
|
52
|
+
class EmptyModel < Model
|
53
|
+
def run_validations!; end
|
54
|
+
|
55
|
+
def to_h
|
56
|
+
@data
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
@@ -0,0 +1,47 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative 'exceptions'
|
4
|
+
|
5
|
+
module Kybus
|
6
|
+
module Storage
|
7
|
+
module Datasource
|
8
|
+
# Base class for repositories. The ID generator might get deprecated.
|
9
|
+
# It provides the interface for storing objects inside any persistance
|
10
|
+
# provider implemented.
|
11
|
+
# TODO: Find a better strategy for primary key handling.
|
12
|
+
class Repository
|
13
|
+
include Exceptions
|
14
|
+
def initialize(id, id_generator)
|
15
|
+
@id = id
|
16
|
+
@id_generator = id_generator
|
17
|
+
end
|
18
|
+
|
19
|
+
def create_initial_object(id)
|
20
|
+
return id if @id.nil? && id.is_a?(Hash)
|
21
|
+
|
22
|
+
object = { @id => @id_generator.call(id, @id) }
|
23
|
+
object.merge!(id) if id.is_a?(Hash)
|
24
|
+
object
|
25
|
+
end
|
26
|
+
|
27
|
+
def create(id = nil)
|
28
|
+
data = create_initial_object(id)
|
29
|
+
existent = exist?(data[@id])
|
30
|
+
raise(ObjectAlreadyExists.new(data[@id], existent)) if existent
|
31
|
+
|
32
|
+
create_(data)
|
33
|
+
end
|
34
|
+
|
35
|
+
def exist?(id)
|
36
|
+
# Not the better solution, but works for objects that don't contain
|
37
|
+
# a unique id.
|
38
|
+
return if id.nil?
|
39
|
+
|
40
|
+
get(id)
|
41
|
+
rescue ObjectNotFound
|
42
|
+
nil
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
@@ -0,0 +1,54 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative 'repository'
|
4
|
+
|
5
|
+
module Kybus
|
6
|
+
module Storage
|
7
|
+
module Datasource
|
8
|
+
# Repository that fetch and store objects using a sequel connection
|
9
|
+
# as resource.
|
10
|
+
class Sequel < Repository
|
11
|
+
def self.from_config(conf)
|
12
|
+
conf['table'] ||= conf['schema_name']
|
13
|
+
conn = ::Sequel.connect(conf['endpoint'], conf)[conf['table'].to_sym]
|
14
|
+
if conf['schema'].nil?
|
15
|
+
# TODO: decouple use of classes
|
16
|
+
new(conn, conf['primary_key'].to_sym,
|
17
|
+
IDGenerators[:id])
|
18
|
+
else
|
19
|
+
# TODO: This line is very high coupled to kybus-nanoservice
|
20
|
+
new(conn, conf['schema']::PRIMARY_KEY, IDGenerators[:id])
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
def initialize(sequel_object, id, id_generator)
|
25
|
+
@sequel = sequel_object
|
26
|
+
super(id, id_generator)
|
27
|
+
end
|
28
|
+
|
29
|
+
def get(id)
|
30
|
+
result = @sequel.where(@id.to_sym => id).first
|
31
|
+
raise(ObjectNotFound, id) if result.nil?
|
32
|
+
|
33
|
+
result
|
34
|
+
end
|
35
|
+
|
36
|
+
def create_(data)
|
37
|
+
id = @sequel.insert(data)
|
38
|
+
data[@id] ||= id
|
39
|
+
data
|
40
|
+
end
|
41
|
+
|
42
|
+
def store(data)
|
43
|
+
data2 = data.dup
|
44
|
+
data2.delete(@id)
|
45
|
+
@sequel.where(@id => data[@id]).update(data2)
|
46
|
+
end
|
47
|
+
|
48
|
+
def connection
|
49
|
+
@sequel.db
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Kybus
|
4
|
+
module Storage
|
5
|
+
# charge of sending objects into storage and fetching also from them.
|
6
|
+
class Factory
|
7
|
+
include Kybus::DRY::ResourceInjector
|
8
|
+
|
9
|
+
def initialize(model)
|
10
|
+
@model = model
|
11
|
+
end
|
12
|
+
|
13
|
+
def create(data, source = resource(:default))
|
14
|
+
repository = resource(source)
|
15
|
+
model = @model.new(data)
|
16
|
+
model.repository = repository
|
17
|
+
model.create
|
18
|
+
model
|
19
|
+
end
|
20
|
+
|
21
|
+
def get(id, source = resource(:default))
|
22
|
+
repository = resource(source)
|
23
|
+
data = repository.get(id)
|
24
|
+
model = @model.new(data)
|
25
|
+
model.repository = repository
|
26
|
+
model
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative 'datasource/json_repository'
|
4
|
+
require_relative 'datasource/sequel'
|
5
|
+
require_relative 'factory'
|
6
|
+
|
7
|
+
module Kybus
|
8
|
+
module Storage
|
9
|
+
# Singleton storing all the implemented repositories. It also allows to
|
10
|
+
# register new repositories for extension.
|
11
|
+
module Repository
|
12
|
+
extend Kybus::DRY::ResourceInjector
|
13
|
+
include Kybus::Storage::Datasource
|
14
|
+
|
15
|
+
register(:repositories, :json, JSONRepository)
|
16
|
+
register(:repositories, 'json', JSONRepository)
|
17
|
+
register(:repositories, :sequel, Sequel)
|
18
|
+
register(:repositories, 'sequel', Sequel)
|
19
|
+
|
20
|
+
def self.from_config(schema, sets, default)
|
21
|
+
conf = default.merge(sets || {}).merge('schema' => schema)
|
22
|
+
resource(:repositories, conf['name']).from_config(conf)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
metadata
ADDED
@@ -0,0 +1,209 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: kybus-storage
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.3
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Gilberto Vargas
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2021-06-15 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: kybus-core
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '0.1'
|
20
|
+
type: :development
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '0.1'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: minitest
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '5.11'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '5.11'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: mocha
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '1.8'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '1.8'
|
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.12'
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - "~>"
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '0.12'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: rack-minitest
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - "~>"
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '0.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.0'
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: rake
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - "~>"
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '12.3'
|
90
|
+
type: :development
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - "~>"
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: '12.3'
|
97
|
+
- !ruby/object:Gem::Dependency
|
98
|
+
name: rdoc
|
99
|
+
requirement: !ruby/object:Gem::Requirement
|
100
|
+
requirements:
|
101
|
+
- - "~>"
|
102
|
+
- !ruby/object:Gem::Version
|
103
|
+
version: '6.1'
|
104
|
+
type: :development
|
105
|
+
prerelease: false
|
106
|
+
version_requirements: !ruby/object:Gem::Requirement
|
107
|
+
requirements:
|
108
|
+
- - "~>"
|
109
|
+
- !ruby/object:Gem::Version
|
110
|
+
version: '6.1'
|
111
|
+
- !ruby/object:Gem::Dependency
|
112
|
+
name: sequel
|
113
|
+
requirement: !ruby/object:Gem::Requirement
|
114
|
+
requirements:
|
115
|
+
- - "~>"
|
116
|
+
- !ruby/object:Gem::Version
|
117
|
+
version: '5.20'
|
118
|
+
type: :development
|
119
|
+
prerelease: false
|
120
|
+
version_requirements: !ruby/object:Gem::Requirement
|
121
|
+
requirements:
|
122
|
+
- - "~>"
|
123
|
+
- !ruby/object:Gem::Version
|
124
|
+
version: '5.20'
|
125
|
+
- !ruby/object:Gem::Dependency
|
126
|
+
name: simplecov
|
127
|
+
requirement: !ruby/object:Gem::Requirement
|
128
|
+
requirements:
|
129
|
+
- - "~>"
|
130
|
+
- !ruby/object:Gem::Version
|
131
|
+
version: '0.16'
|
132
|
+
type: :development
|
133
|
+
prerelease: false
|
134
|
+
version_requirements: !ruby/object:Gem::Requirement
|
135
|
+
requirements:
|
136
|
+
- - "~>"
|
137
|
+
- !ruby/object:Gem::Version
|
138
|
+
version: '0.16'
|
139
|
+
- !ruby/object:Gem::Dependency
|
140
|
+
name: sqlite3
|
141
|
+
requirement: !ruby/object:Gem::Requirement
|
142
|
+
requirements:
|
143
|
+
- - "~>"
|
144
|
+
- !ruby/object:Gem::Version
|
145
|
+
version: '1.4'
|
146
|
+
type: :development
|
147
|
+
prerelease: false
|
148
|
+
version_requirements: !ruby/object:Gem::Requirement
|
149
|
+
requirements:
|
150
|
+
- - "~>"
|
151
|
+
- !ruby/object:Gem::Version
|
152
|
+
version: '1.4'
|
153
|
+
- !ruby/object:Gem::Dependency
|
154
|
+
name: webmock
|
155
|
+
requirement: !ruby/object:Gem::Requirement
|
156
|
+
requirements:
|
157
|
+
- - "~>"
|
158
|
+
- !ruby/object:Gem::Version
|
159
|
+
version: '3.5'
|
160
|
+
type: :development
|
161
|
+
prerelease: false
|
162
|
+
version_requirements: !ruby/object:Gem::Requirement
|
163
|
+
requirements:
|
164
|
+
- - "~>"
|
165
|
+
- !ruby/object:Gem::Version
|
166
|
+
version: '3.5'
|
167
|
+
description: |2
|
168
|
+
This module helps to design persistance modules that are very configurable
|
169
|
+
about where and how to store data.
|
170
|
+
email:
|
171
|
+
- tachoguitar@gmail.com
|
172
|
+
executables: []
|
173
|
+
extensions: []
|
174
|
+
extra_rdoc_files: []
|
175
|
+
files:
|
176
|
+
- lib/kybus/storage.rb
|
177
|
+
- lib/kybus/storage/datasource/exceptions.rb
|
178
|
+
- lib/kybus/storage/datasource/id_generators.rb
|
179
|
+
- lib/kybus/storage/datasource/json_repository.rb
|
180
|
+
- lib/kybus/storage/datasource/model.rb
|
181
|
+
- lib/kybus/storage/datasource/repository.rb
|
182
|
+
- lib/kybus/storage/datasource/sequel.rb
|
183
|
+
- lib/kybus/storage/factory.rb
|
184
|
+
- lib/kybus/storage/repository.rb
|
185
|
+
- lib/kybus/version.rb
|
186
|
+
homepage: https://github.com/tachomex/kybus
|
187
|
+
licenses:
|
188
|
+
- MIT
|
189
|
+
metadata: {}
|
190
|
+
post_install_message:
|
191
|
+
rdoc_options: []
|
192
|
+
require_paths:
|
193
|
+
- lib
|
194
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
195
|
+
requirements:
|
196
|
+
- - ">="
|
197
|
+
- !ruby/object:Gem::Version
|
198
|
+
version: '0'
|
199
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
200
|
+
requirements:
|
201
|
+
- - ">="
|
202
|
+
- !ruby/object:Gem::Version
|
203
|
+
version: '0'
|
204
|
+
requirements: []
|
205
|
+
rubygems_version: 3.1.4
|
206
|
+
signing_key:
|
207
|
+
specification_version: 4
|
208
|
+
summary: Implements storage modules for kybus framework
|
209
|
+
test_files: []
|