dyna_model 0.0.1 → 0.0.2

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: ca4e3bd3b871756a2b5fad4bf362c334bbf804af
4
- data.tar.gz: ac13badc8bca36d88787d6cbdb6134af19c69a93
3
+ metadata.gz: 254b9c0ebdd7a60601af697b4702fa53d9dc3f0e
4
+ data.tar.gz: 9129d092e187f9284e1853d63e744ffa56e9d84a
5
5
  SHA512:
6
- metadata.gz: 23243b46398ab0517a2f6a7c57e1fdbbe3f4f63c8d55b8c1a8a73abe8de75a297395ad8554d06101c02cb472de16a696e738a509b46002427812b4efa6279e49
7
- data.tar.gz: 32f20b9e28c107825230eb53dfd18b092f6626e91e66a4b1fd859b0523c4f5c38c1566d2e77e9417ec80b8612c4c91ba24269f47a74379eecc1611ee37b0b38a
6
+ metadata.gz: 3dd8cca0fe4249f173fceb88d4a29b706409de9a017049844493a6066ef67f2238548bddd18b9278d5ba390eeeb0910d82c103ad4db3ffe4e7171903433d164f
7
+ data.tar.gz: 9c27a58d8bb188a5a29bf49c4ab6163ae9d3f3525d85e4d6a16f6466a586c31aed0e744a36ba7de1ff31b37f4d0aefd0a50cf95ca1bbb07cce6122d5defd1ab7
data/README.md CHANGED
@@ -76,6 +76,16 @@ rake ddb:destroy CLASS=Dude
76
76
  rake ddb:destroy CLASS=all
77
77
  ```
78
78
 
79
+ ## Elasticsearch::Model compatible adapter
80
+ ```
81
+ require 'dyna_model/adapters/elasticsearch/dyna_model_adapter'
82
+ class Item
83
+ include DynaModel::Document
84
+ include Elasticsearch::Model
85
+ include Elasticsearch::Model::Callbacks
86
+ end
87
+ ```
88
+
79
89
  # AWS::Record
80
90
  * http://docs.aws.amazon.com/AWSRubySDK/latest/AWS/Record.html
81
91
  * https://github.com/aws/aws-sdk-ruby/blob/master/lib/aws/record/abstract_base.rb
@@ -0,0 +1,86 @@
1
+ module Elasticsearch
2
+ module Model
3
+ module Adapter
4
+ module DynaModelAdapter
5
+
6
+ Adapter.register self, lambda { |klass| !!defined?(::DynaModel::Document) && klass.ancestors.include?(::DynaModel::Document) }
7
+
8
+ module Records
9
+
10
+ def records
11
+ records_arr = klass.read_multiple(ids, format: :array)
12
+ records_arr.sort_by { |e| response.response['hits']['hits'].index { |hit| hit['_id'].to_s == e.id.to_s } }
13
+ end
14
+
15
+ # Intercept call to sorting methods, so we can ignore the order from Elasticsearch
16
+ %w| asc desc order_by |.each do |name|
17
+ define_method name do |*args|
18
+ raise "TODO - not supported yet"
19
+ end
20
+ end
21
+ end
22
+
23
+ module Callbacks
24
+ def self.included(base)
25
+ base.after_create { |document| document.__elasticsearch__.index_document }
26
+ base.after_update { |document| document.__elasticsearch__.update_document }
27
+ base.after_destroy { |document| document.__elasticsearch__.delete_document }
28
+ end
29
+ end
30
+
31
+ module Importing
32
+
33
+ def __find_in_batches(options={}, &block)
34
+ items = []
35
+
36
+ # Use 1/4 or read provision
37
+ read_provision = self.dynamo_db_table.table_schema[:provisioned_throughput][:read_capacity_units]
38
+ raise "read_provision not set for class!" unless read_provision
39
+ default_batch_size = (read_provision / 2.0).floor
40
+ batch_size = options[:batch_size] || default_batch_size
41
+ puts "Indexing via scan with batch size of #{batch_size}..."
42
+
43
+ # :consumed_capacity
44
+ scan_idx = 0
45
+ results_hash = {}
46
+ while scan_idx == 0 || (results_hash && results_hash[:last_evaluated_key])
47
+ puts "Batch iteration #{scan_idx+1}..."
48
+ scan_options = {
49
+ batch: batch_size,
50
+ manual_batching: true,
51
+ return_consumed_capacity: :total
52
+ }
53
+ scan_options.merge!(exclusive_start_key: results_hash[:last_evaluated_key]) if results_hash[:last_evaluated_key]
54
+ scan_options.merge!(scan_filter: options[:scan_filter]) if options[:scan_filter]
55
+ results_hash = self.scan(scan_options)
56
+
57
+ unless results_hash[:results].blank?
58
+ puts "Indexing #{results_hash[:results].size} results..."
59
+ batch_for_bulk = results_hash[:results].map { |a| { index: {
60
+ _id: a.id,
61
+ data: a.__elasticsearch__.as_indexed_json
62
+ } } }
63
+ yield batch_for_bulk
64
+ end
65
+
66
+ # If more results to scan, sleep to throttle...
67
+ # Local Dynamo is not returning consumed_capacity 2014-01-12
68
+ if results_hash[:last_evaluated_key] && results_hash[:consumed_capacity]
69
+ # try to keep read usage under 50% of read_provision
70
+ sleep_time = results_hash[:consumed_capacity][:capacity_units].to_f / (read_provision / 2.0)
71
+ puts "Sleeping for #{sleep_time}..."
72
+ sleep(sleep_time)
73
+ end
74
+
75
+ scan_idx += 1
76
+ end
77
+
78
+ end
79
+
80
+ end
81
+
82
+ end
83
+
84
+ end
85
+ end
86
+ end
@@ -34,6 +34,17 @@ module DynaModel
34
34
  end
35
35
  super
36
36
  end
37
+
38
+ # OVERRIDE
39
+ # https://github.com/aws/aws-sdk-ruby/blob/master/lib/aws/record/abstract_base.rb#L76
40
+ # AWS::Record::AbstractBase for :select attributes
41
+ public
42
+ def attributes
43
+ attributes = AWS::Core::IndifferentHash.new
44
+ (self.instance_variable_get("@_selected_attributes") || self.class.attributes.keys).inject(attributes) do |hash,attr_name|
45
+ hash.merge(attr_name => __send__(attr_name))
46
+ end
47
+ end
37
48
  end
38
49
 
39
50
  include ActiveModel::Conversion
@@ -47,6 +58,10 @@ module DynaModel
47
58
  include DynaModel::Schema
48
59
  include DynaModel::Query
49
60
 
61
+ def id
62
+ self.dynamo_db_guid
63
+ end
64
+
50
65
  def to_param
51
66
  self.dynamo_db_guid
52
67
  end
@@ -64,7 +79,7 @@ module DynaModel
64
79
  end
65
80
 
66
81
  def all_attributes_loaded?
67
- self.instance_variable_get("@_select") == :all
82
+ self.instance_variable_get("@_select").nil? && self.instance_variable_get("@_select") == :all
68
83
  end
69
84
 
70
85
  # When only partial attributes were selected (via GSI or projected attributes on an index)
@@ -30,18 +30,26 @@ module DynaModel
30
30
  end
31
31
 
32
32
  def read_multiple(keys, options={})
33
+ options[:format] = (options[:format] && options[:format] == :array) ? :array : :hash
33
34
  results_map = {}
34
- results = self.dynamo_db_table.batch_get_item(keys, options)
35
- results[:responses][self.dynamo_db_table_name(options[:shard_name])].each do |result|
36
- attrs = Response.strip_attr_types(result)
37
- obj = self.obj_from_attrs(attrs, options)
38
- if self.dynamo_db_table.range_keys.present? && primary_range_key = self.dynamo_db_table.range_keys.find{|rk| rk[:primary_range_key] }
39
- (results_map[attrs[self.dynamo_db_table.hash_key[:attribute_name]]] ||= {})[attrs[primary_range_key[:attribute_name]]] = obj
40
- else
41
- results_map[attrs[self.dynamo_db_table.hash_key[:attribute_name]]] = obj
35
+ results_arr = []
36
+ if keys.present?
37
+ results = self.dynamo_db_table.batch_get_item(keys, options)
38
+ results[:responses][self.dynamo_db_table_name(options[:shard_name])].each do |result|
39
+ attrs = Response.strip_attr_types(result)
40
+ obj = self.obj_from_attrs(attrs, options)
41
+ if options[:format] == :array
42
+ results_arr << obj
43
+ else
44
+ if self.dynamo_db_table.range_keys.present? && primary_range_key = self.dynamo_db_table.range_keys.find{|rk| rk[:primary_range_key] }
45
+ (results_map[attrs[self.dynamo_db_table.hash_key[:attribute_name]]] ||= {})[attrs[primary_range_key[:attribute_name]]] = obj
46
+ else
47
+ results_map[attrs[self.dynamo_db_table.hash_key[:attribute_name]]] = obj
48
+ end
49
+ end
42
50
  end
43
51
  end
44
- results_map
52
+ options[:format] == :array ? results_arr : results_map
45
53
  end
46
54
 
47
55
  # Read results up to the limit
@@ -281,16 +281,13 @@ module DynaModel
281
281
  keys.each do |k|
282
282
  key_request = {}
283
283
  if @primary_range_key
284
- hash_value = k[:hash_value]
284
+ hash_value, range_value = k.split(@model.guid_delimiter)
285
285
  else
286
- raise ArgumentError, "expected keys to be in the form of ['hash key here'] for table with no range keys" if hash_value.is_a?(Hash)
287
286
  hash_value = k
288
287
  end
289
- raise ArgumentError, "every key must include a :hash_value" if hash_value.blank?
290
288
  key_request[@hash_key[:attribute_name]] = { @hash_key[:attribute_type] => hash_value.to_s }
291
289
  if @primary_range_key
292
- range_value = k[:range_value]
293
- raise ArgumentError, "every key must include a :range_value" if range_value.blank?
290
+ raise ArgumentError, "every key must include a range_value" if range_value.blank?
294
291
  key_request[@primary_range_key[:attribute_name]] = { @primary_range_key[:attribute_type] => range_value.to_s }
295
292
  end
296
293
  keys_request << key_request
@@ -1,3 +1,3 @@
1
1
  module DynaModel
2
- VERSION = "0.0.1"
2
+ VERSION = "0.0.2"
3
3
  end
@@ -99,7 +99,7 @@ describe "DynaModel::Query" do
99
99
  multi[@cacher2.key].should_not be_nil
100
100
  @user = User.create(@user_attrs)
101
101
  @user2 = User.create(@user2_attrs)
102
- multi = User.read_multiple([{hash_value: @user.hashy, range_value: @user.ranger}, {hash_value: @user2.hashy, range_value: @user2.ranger}])
102
+ multi = User.read_multiple([@user.dynamo_db_guid, @user2.dynamo_db_guid])
103
103
  multi[@user.hashy].should_not be_nil
104
104
  multi[@user.hashy][@user.ranger.to_s].should_not be_nil
105
105
  multi[@user2.hashy].should_not be_nil
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: dyna_model
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1
4
+ version: 0.0.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Cary Dunn
@@ -136,6 +136,7 @@ files:
136
136
  - Rakefile
137
137
  - dyna_model.gemspec
138
138
  - lib/dyna_model.rb
139
+ - lib/dyna_model/adapters/elasticsearch/dyna_model_adapter.rb
139
140
  - lib/dyna_model/attributes.rb
140
141
  - lib/dyna_model/aws/record/attributes/serialized_attr.rb
141
142
  - lib/dyna_model/config.rb