ocean-dynamo 1.0.8 → 1.1.0
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 +4 -4
- data/README.rdoc +87 -51
- data/lib/ocean-dynamo/associations/has_many.rb +1 -4
- data/lib/ocean-dynamo/persistence.rb +2 -2
- data/lib/ocean-dynamo/tables.rb +30 -5
- data/lib/ocean-dynamo/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 5a5d6a93318aea2c36029d1f40d3496ad5cc16a1
|
4
|
+
data.tar.gz: 17f2f4d1edf4885662aea89e61948924d7e2bfdb
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: d3f9aff5b1b2f3402946acb6c5806b32582e3baeefa758ea4d35183386cde1bb937e88204a8feb8fddabc107b16c13540c334bd0ddf04ce91b39822e9a3c6284
|
7
|
+
data.tar.gz: 1cfb33f43e6888a7f7f7417900baf99b9d777ef2797a52d96f5af36e090bedd46f2543210f62237f7e4db547570a67094cb1bd3e094ec13e36671b11154fe1eb
|
data/README.rdoc
CHANGED
@@ -18,16 +18,65 @@ closely and is of course based on ActiveModel.
|
|
18
18
|
|
19
19
|
The attribute and persistence layer of OceanDynamo is modeled on that of ActiveRecord:
|
20
20
|
there's +save+, +save!+, +create+, +update+, +update!+, +update_attributes+, +find_each+,
|
21
|
-
+destroy_all+, +delete_all+ and all the other
|
22
|
-
is always to implement as much of the ActiveRecord
|
23
|
-
compromising scalability. This makes the task of switching
|
24
|
-
|
25
|
-
Thanks to its structural similarity to ActiveRecord, OceanDynamo works with FactoryGirl.
|
21
|
+
+destroy_all+, +delete_all+, +read_attribute+, +write_attribute+ and all the other
|
22
|
+
methods you're used to. The design goal is always to implement as much of the ActiveRecord
|
23
|
+
interface as possible, without compromising scalability. This makes the task of switching
|
24
|
+
from SQL to no-SQL much easier.
|
26
25
|
|
27
26
|
OceanDynamo uses only primary indices to retrieve related table items and collections,
|
28
27
|
which means it will scale without limits.
|
29
28
|
|
30
|
-
|
29
|
+
OceanDynamo is fully usable as an ActiveModel and can be used by Rails
|
30
|
+
controllers. Thanks to its structural similarity to ActiveRecord, OceanDynamo works
|
31
|
+
with FactoryGirl.
|
32
|
+
|
33
|
+
|
34
|
+
=== Current State
|
35
|
+
|
36
|
+
* Local secondary indices are now supported! See below for more information.
|
37
|
+
* Version 2 of the AWS Ruby SDK is now used. This required an internal reorganisation,
|
38
|
+
but it also gives us access to local and global secondary indices.
|
39
|
+
* Work begun on association proxies, etc.
|
40
|
+
|
41
|
+
|
42
|
+
=== Future milestones
|
43
|
+
|
44
|
+
* Association proxies, to implement ActiveRecord-style method chaining, e.g.:
|
45
|
+
<code>blog_entry.comments.build(body: "Cool!").save!</code>
|
46
|
+
* The +has_and_belongs_to_many+ assocation.
|
47
|
+
* A generator to install the <tt>config/aws.yml</tt> file.
|
48
|
+
|
49
|
+
|
50
|
+
=== Current use
|
51
|
+
|
52
|
+
OceanDynamo is used as a central component in Ocean, a Rails framework and development
|
53
|
+
pipeline for creating highly scalable HATEOAS microservice SOAs in the cloud.
|
54
|
+
* http://wiki.oceanframework.net
|
55
|
+
|
56
|
+
Ocean uses OceanDynamo to implement highly scalable job queues and authentication.
|
57
|
+
It will be used increasingly as features are added to OceanDynamo and will eventually
|
58
|
+
replace all ActiveRecord tables in Ocean.
|
59
|
+
|
60
|
+
However, OceanDynamo can of course also be used stand-alone.
|
61
|
+
|
62
|
+
|
63
|
+
== Documentation
|
64
|
+
|
65
|
+
* Ocean-dynamo gem on Rubygems: https://rubygems.org/gems/ocean-dynamo
|
66
|
+
* Ocean-dynamo gem API: http://rubydoc.info/gems/ocean-dynamo/frames
|
67
|
+
* Ocean-dynamo source and wiki: https://github.org/OceanDev/ocean-dynamo
|
68
|
+
* AWS DynamoDB Ruby SDK v2: http://docs.aws.amazon.com/sdkforruby/api/Aws/DynamoDB.html
|
69
|
+
|
70
|
+
|
71
|
+
== Contributing
|
72
|
+
|
73
|
+
Contributions are welcome. Fork in the usual way. OceanDynamo is developed using
|
74
|
+
TDD: the specs are extensive and test coverage is very near to 100 percent. Pull requests
|
75
|
+
will not be considered unless all tests pass and coverage is equally high or higher.
|
76
|
+
All contributed code must therefore also be exhaustively tested.
|
77
|
+
|
78
|
+
|
79
|
+
=== Examples
|
31
80
|
|
32
81
|
==== Basic syntax
|
33
82
|
|
@@ -45,7 +94,7 @@ The following example shows the basic syntax for declaring a DynamoDB-based sche
|
|
45
94
|
attribute :started_at, :datetime
|
46
95
|
attribute :last_completed_step, :integer
|
47
96
|
attribute :finished_at, :datetime
|
48
|
-
attribute :destroy_at, :datetime
|
97
|
+
attribute :destroy_at, :datetime, local_secondary_index: true
|
49
98
|
attribute :created_by
|
50
99
|
attribute :updated_by
|
51
100
|
attribute :succeeded, :boolean, default: false
|
@@ -73,8 +122,8 @@ value will return the empty string, <tt>""</tt>.
|
|
73
122
|
+dynamo_schema+ takes args and many options. Here's the full syntax:
|
74
123
|
|
75
124
|
dynamo_schema(
|
76
|
-
table_hash_key
|
77
|
-
table_range_key
|
125
|
+
table_hash_key = :id, # The name of the hash key attribute
|
126
|
+
table_range_key = nil, # The name of the range key attribute (or nil)
|
78
127
|
table_name: compute_table_name, # The basename of the DynamoDB table
|
79
128
|
table_name_prefix: nil, # A basename prefix string or nil
|
80
129
|
table_name_suffix: nil, # A basename suffix string or nil
|
@@ -166,32 +215,40 @@ Nevertheless, as we now have switched to v2 of the DynamoDB API, we will be addi
|
|
166
215
|
the possibility to define both local and secondary indices for Tables.
|
167
216
|
|
168
217
|
|
169
|
-
===
|
170
|
-
|
171
|
-
OceanDynamo is fully usable as an ActiveModel and can be used by Rails
|
172
|
-
controllers. OceanDynamo implements much of the infrastructure of ActiveRecord;
|
173
|
-
for instance, +read_attribute+, +write_attribute+, and much of the control logic and
|
174
|
-
internal organisation.
|
175
|
-
|
176
|
-
* Version 2 of the AWS Ruby SDK is now used. This required an internal reorganisation,
|
177
|
-
but it also gives us access to local and global secondary indices.
|
178
|
-
* Work begun on collection proxies, etc.
|
218
|
+
=== Local Secondary Indices
|
179
219
|
|
180
|
-
|
220
|
+
We now have basic support for local secondary indices. Up to five attributes can
|
221
|
+
be declared as local secondary indices, in the following manner:
|
181
222
|
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
223
|
+
class Authentication < OceanDynamo::Table
|
224
|
+
dynamo_schema(:username, :expires_at,
|
225
|
+
timestamps: nil, locking: false
|
226
|
+
table_name_suffix: Api.basename_suffix) do
|
227
|
+
attribute :token, :string, local_secondary_index: true
|
228
|
+
attribute :max_age, :integer
|
229
|
+
attribute :created_at, :datetime
|
230
|
+
attribute :expires_at, :datetime
|
231
|
+
attribute :api_user_id, :string
|
232
|
+
end
|
233
|
+
end
|
188
234
|
|
235
|
+
The items of the above table can be accessed by using the hash key :username and
|
236
|
+
the range key :expires_at. The +local_secondary_index+ declaration makes it possible
|
237
|
+
to access items using the same hash key :username but with :token as an alternate
|
238
|
+
range key. Local secondary indices all use the same hash key as the primary index,
|
239
|
+
substituting another attribute instead as the range key.
|
189
240
|
|
190
|
-
|
241
|
+
NB: The primary index [:username, :expires_at] requires all items to have a unique
|
242
|
+
combination of keys. Secondary indices don't require the range key to be unique for
|
243
|
+
the same hash key. This means that secondary index searches always will return a
|
244
|
+
collection.
|
191
245
|
|
192
|
-
|
193
|
-
|
194
|
-
|
246
|
+
We will add support for specifying that a secondary index is to be used in +find_each+
|
247
|
+
and its derivatives, but for now you will have to specify this explicitly in the
|
248
|
+
options passed to +in_batches+, +query+, and +scan+.
|
249
|
+
* +query+: http://docs.aws.amazon.com/sdkforruby/api/Aws/DynamoDB/Table.html#query-instance_method.
|
250
|
+
* +scan+: http://docs.aws.amazon.com/sdkforruby/api/Aws/DynamoDB/Table.html#scan-instance_method
|
251
|
+
* +in_batches+, +find_each+: lib/ocean-dynamo/queries.rb
|
195
252
|
|
196
253
|
|
197
254
|
== Installation
|
@@ -219,27 +276,6 @@ Enter your AWS credentials in the latter file. Eventually, there
|
|
219
276
|
will be a generator to copy these files for you, but for now you need to do it manually.
|
220
277
|
|
221
278
|
|
222
|
-
== Documentation
|
223
|
-
|
224
|
-
* Ocean-dynamo gem on Rubygems: https://rubygems.org/gems/ocean-dynamo
|
225
|
-
* Ocean-dynamo gem API: http://rubydoc.info/gems/ocean-dynamo/frames
|
226
|
-
* Ocean-dynamo source and wiki: https://github.org/OceanDev/ocean-dynamo
|
227
|
-
* AWS DynamoDB Ruby SDK v2: http://docs.aws.amazon.com/sdkforruby/api/Aws/DynamoDB.html
|
228
|
-
|
229
|
-
You might also want to take a look at Ocean, a Rails framework and development pipeline
|
230
|
-
for creating highly scalable HATEOAS microservice SOAs in the cloud. Ocean uses
|
231
|
-
OceanDynamo as a central component:
|
232
|
-
* http://wiki.oceanframework.net
|
233
|
-
|
234
|
-
|
235
|
-
== Contributing
|
236
|
-
|
237
|
-
Contributions are welcome. Fork in the usual way. OceanDynamo is developed using
|
238
|
-
TDD: the specs are extensive and test coverage is very near to 100 percent. Pull requests
|
239
|
-
will not be considered unless all tests pass and coverage is equally high or higher.
|
240
|
-
All contributed code must therefore also be exhaustively tested.
|
241
|
-
|
242
|
-
|
243
279
|
== Running the specs
|
244
280
|
|
245
281
|
To run the specs for the OceanDynamo gem, you must first install DynamoDB Local.
|
@@ -113,10 +113,7 @@ module OceanDynamo
|
|
113
113
|
def condition_options(child_class)
|
114
114
|
hash_key = child_class.table_hash_key
|
115
115
|
range_key = child_class.table_range_key
|
116
|
-
|
117
|
-
ean["#H"] = hash_key.to_s
|
118
|
-
ean["#R"] = range_key.to_s if range_key
|
119
|
-
{ expression_attribute_names: ean,
|
116
|
+
{ expression_attribute_names: { "#H" => hash_key, "#R" => range_key },
|
120
117
|
key_condition_expression: "#H = :hashval AND #R >= :rangeval",
|
121
118
|
expression_attribute_values: { ":hashval" => id, ":rangeval" => "0" }
|
122
119
|
}
|
@@ -50,8 +50,8 @@ module OceanDynamo
|
|
50
50
|
#
|
51
51
|
def delete_all
|
52
52
|
_late_connect?
|
53
|
-
ean = { "#H" => table_hash_key
|
54
|
-
ean["#R"] = table_range_key
|
53
|
+
ean = { "#H" => table_hash_key }
|
54
|
+
ean["#R"] = table_range_key if table_range_key
|
55
55
|
options = {
|
56
56
|
consistent_read: true,
|
57
57
|
projection_expression: "#H" + (table_range_key ? ", #R" : ""),
|
data/lib/ocean-dynamo/tables.rb
CHANGED
@@ -44,7 +44,7 @@ module OceanDynamo
|
|
44
44
|
|
45
45
|
|
46
46
|
def establish_db_connection
|
47
|
-
setup_dynamo
|
47
|
+
setup_dynamo
|
48
48
|
if table_exists?(dynamo_table)
|
49
49
|
wait_until_table_is_active
|
50
50
|
self.table_connected = true
|
@@ -95,17 +95,19 @@ module OceanDynamo
|
|
95
95
|
|
96
96
|
|
97
97
|
def create_table
|
98
|
-
attrs = table_attribute_definitions
|
98
|
+
attrs = table_attribute_definitions # This already includes secondary indices
|
99
99
|
keys = table_key_schema
|
100
100
|
options = {
|
101
101
|
table_name: table_full_name,
|
102
|
+
attribute_definitions: attrs,
|
103
|
+
key_schema: keys,
|
102
104
|
provisioned_throughput: {
|
103
105
|
read_capacity_units: table_read_capacity_units,
|
104
106
|
write_capacity_units: table_write_capacity_units
|
105
|
-
}
|
106
|
-
attribute_definitions: attrs,
|
107
|
-
key_schema: keys
|
107
|
+
}
|
108
108
|
}
|
109
|
+
lsi = local_secondary_indexes.collect { |n| local_secondary_index_declaration n }
|
110
|
+
options[:local_secondary_indexes] = lsi unless lsi.blank?
|
109
111
|
dynamo_resource.create_table(options)
|
110
112
|
sleep 1 until dynamo_table.table_status == "ACTIVE"
|
111
113
|
setup_dynamo
|
@@ -126,10 +128,33 @@ module OceanDynamo
|
|
126
128
|
end
|
127
129
|
|
128
130
|
|
131
|
+
def local_secondary_indexes
|
132
|
+
@local_secondary_indexes ||= begin
|
133
|
+
result = []
|
134
|
+
fields.each do |name, metadata|
|
135
|
+
(result << name) if metadata["local_secondary_index"]
|
136
|
+
end
|
137
|
+
result
|
138
|
+
end
|
139
|
+
end
|
140
|
+
|
141
|
+
|
142
|
+
def local_secondary_index_declaration(name)
|
143
|
+
{ index_name: name,
|
144
|
+
key_schema: [{ attribute_name: table_hash_key.to_s, key_type: "HASH" },
|
145
|
+
{ attribute_name: name.to_s, key_type: "RANGE" }],
|
146
|
+
projection: { projection_type: "KEYS_ONLY" }
|
147
|
+
}
|
148
|
+
end
|
149
|
+
|
150
|
+
|
129
151
|
def table_attribute_definitions
|
130
152
|
attrs = []
|
131
153
|
attrs << { attribute_name: table_hash_key.to_s, attribute_type: attribute_type(table_hash_key) }
|
132
154
|
attrs << { attribute_name: table_range_key.to_s, attribute_type: attribute_type(table_range_key) } if table_range_key
|
155
|
+
local_secondary_indexes.each do |name|
|
156
|
+
attrs << { attribute_name: name, attribute_type: attribute_type(name) }
|
157
|
+
end
|
133
158
|
attrs
|
134
159
|
end
|
135
160
|
|
data/lib/ocean-dynamo/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: ocean-dynamo
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.0
|
4
|
+
version: 1.1.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Peter Bengtson
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2015-09-
|
11
|
+
date: 2015-09-18 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: aws-sdk
|