materialist 3.2.0 → 3.3.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +12 -3
- data/RELEASE_NOTES.md +13 -3
- data/lib/configuration.rb +2 -1
- data/lib/materialist.rb +1 -1
- data/lib/materialist/materializer/internals/dsl.rb +6 -2
- data/lib/materialist/materializer/internals/field_mapping.rb +3 -1
- data/lib/materialist/materializer/internals/link_href_mapping.rb +12 -2
- data/lib/materialist/materializer/internals/link_mapping.rb +16 -1
- data/lib/materialist/materializer/internals/materializer.rb +6 -38
- data/lib/materialist/workers/event.rb +7 -1
- data/spec/materialist/materializer_spec.rb +5 -0
- data/spec/materialist/workers/event_spec.rb +14 -0
- data/spec/schema.rb +1 -0
- 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: f551f35e47a806f9f5e3b475feb35358f4a034b5
|
4
|
+
data.tar.gz: 8134a56b74346d367618b99b09604c0ded38a815
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 2a647bde4177b45a090e8a91a1a34b1dde10f1ac38adbe8d1588c161182113cd8f065511edd59f08a82e38721ebaa1260650af9840d4e1f032160a4739561af1
|
7
|
+
data.tar.gz: c660872899ce6526370260e7852d886ecd34abf2a4c0cdaf7178b11680c524db318ade68d8640ce00aa2a50630158f4242f20eec20f79b49f496b877c6a0c678
|
data/README.md
CHANGED
@@ -75,8 +75,9 @@ end
|
|
75
75
|
|
76
76
|
- `topics` (only when using in `.subscribe`): A string array of topics to be used.
|
77
77
|
If not provided nothing would be materialized.
|
78
|
-
- `sidekiq_options` (optional, default: `{ retry: 10 }`) -- See [Sidekiq docs](https://github.com/mperham/sidekiq/wiki/Advanced-Options#workers) for list of
|
78
|
+
- `sidekiq_options` (optional, default: `{ retry: 10 }`) -- See [Sidekiq docs](https://github.com/mperham/sidekiq/wiki/Advanced-Options#workers) for list of options
|
79
79
|
- `metrics_client` (optional) -- You can pass your `STATSD` instance
|
80
|
+
- `notice_error` (optional) -- You can pass a lambda accepting two parameters (`exception` and `event`) -- Typical use case is to enrich error and send to NewRelic APM
|
80
81
|
|
81
82
|
### Routemaster Configuration
|
82
83
|
|
@@ -160,8 +161,8 @@ Here is what each part of the DSL mean:
|
|
160
161
|
|
161
162
|
#### `sidekiq_options <options>`
|
162
163
|
allows to override options for the Sidekiq job which does the materialization.
|
163
|
-
Typically it will specify which queue to put the job on or how many times
|
164
|
-
should the job try to retry. These options override the options specified in
|
164
|
+
Typically it will specify which queue to put the job on or how many times
|
165
|
+
should the job try to retry. These options override the options specified in
|
165
166
|
`Materialist.configuration.sidekiq_options`.
|
166
167
|
|
167
168
|
#### `persist_to <model_name>`
|
@@ -180,6 +181,14 @@ describes mapping a resource key to a database column.
|
|
180
181
|
#### `capture_link_href <key>, as: <column>`
|
181
182
|
describes mapping a link href (as it appears on the hateous response) to a database column.
|
182
183
|
|
184
|
+
You can optionally provide a block for parsing the url:
|
185
|
+
|
186
|
+
```ruby
|
187
|
+
capture_link_href :rider, as: :rider_id do |url|
|
188
|
+
url.split('/').last
|
189
|
+
end
|
190
|
+
```
|
191
|
+
|
183
192
|
#### `link <key>, enable_caching: <enable_caching> (default: false)`
|
184
193
|
describes materializing from a relation of the resource. This can be nested to any depth as shown above.
|
185
194
|
|
data/RELEASE_NOTES.md
CHANGED
@@ -1,8 +1,18 @@
|
|
1
|
+
## Next
|
2
|
+
|
3
|
+
_description of next release_
|
4
|
+
|
5
|
+
## 3.3.0
|
6
|
+
|
7
|
+
Features:
|
8
|
+
- Add support for parsing url when using `capture_link_href`
|
9
|
+
- Add support for providing `notice_error` on configuration.
|
10
|
+
|
1
11
|
## 3.2.0
|
2
12
|
|
3
13
|
Features:
|
4
14
|
- For linked resources specified by `link` an option to `enable_caching` can now be explicitly set. This
|
5
|
-
tells Routemaster to use or not use the drain cache.
|
15
|
+
tells Routemaster to use or not use the drain cache.
|
6
16
|
|
7
17
|
## 3.1.0
|
8
18
|
|
@@ -12,8 +22,8 @@ Features:
|
|
12
22
|
|
13
23
|
Notes:
|
14
24
|
|
15
|
-
Materialist::EventWorker has been moved to Materialist::Workers::Event, but the original has
|
16
|
-
been left there for backwards compatibility. It will be removed in a later major release.
|
25
|
+
Materialist::EventWorker has been moved to Materialist::Workers::Event, but the original has
|
26
|
+
been left there for backwards compatibility. It will be removed in a later major release.
|
17
27
|
|
18
28
|
## 3.0.0
|
19
29
|
|
data/lib/configuration.rb
CHANGED
@@ -14,12 +14,13 @@ module Materialist
|
|
14
14
|
end
|
15
15
|
|
16
16
|
class Configuration
|
17
|
-
attr_accessor :topics, :sidekiq_options, :metrics_client
|
17
|
+
attr_accessor :topics, :sidekiq_options, :metrics_client, :notice_error
|
18
18
|
|
19
19
|
def initialize
|
20
20
|
@topics = []
|
21
21
|
@sidekiq_options = {}
|
22
22
|
@metrics_client = NullMetricsClient
|
23
|
+
@notice_error = nil
|
23
24
|
end
|
24
25
|
|
25
26
|
class NullMetricsClient
|
data/lib/materialist.rb
CHANGED
@@ -10,8 +10,12 @@ module Materialist
|
|
10
10
|
__materialist_dsl_mapping_stack.last << FieldMapping.new(key: key, as: as)
|
11
11
|
end
|
12
12
|
|
13
|
-
def capture_link_href(key, as
|
14
|
-
__materialist_dsl_mapping_stack.last << LinkHrefMapping.new(
|
13
|
+
def capture_link_href(key, as:, &url_parser_block)
|
14
|
+
__materialist_dsl_mapping_stack.last << LinkHrefMapping.new(
|
15
|
+
key: key,
|
16
|
+
as: as,
|
17
|
+
url_parser: url_parser_block
|
18
|
+
)
|
15
19
|
end
|
16
20
|
|
17
21
|
def link(key, enable_caching: false)
|
@@ -2,12 +2,22 @@ module Materialist
|
|
2
2
|
module Materializer
|
3
3
|
module Internals
|
4
4
|
class LinkHrefMapping
|
5
|
-
def initialize(key:, as:)
|
5
|
+
def initialize(key:, as:, url_parser: nil)
|
6
6
|
@key = key
|
7
7
|
@as = as
|
8
|
+
@url_parser = url_parser
|
8
9
|
end
|
9
10
|
|
10
|
-
|
11
|
+
def map(resource)
|
12
|
+
return unless link = resource.body._links[@key]
|
13
|
+
{ @as => url_parser.call(link.href) }
|
14
|
+
end
|
15
|
+
|
16
|
+
private
|
17
|
+
|
18
|
+
def url_parser
|
19
|
+
@url_parser || ->url { url }
|
20
|
+
end
|
11
21
|
end
|
12
22
|
end
|
13
23
|
end
|
@@ -8,7 +8,22 @@ module Materialist
|
|
8
8
|
@mapping = []
|
9
9
|
end
|
10
10
|
|
11
|
-
|
11
|
+
def map(resource)
|
12
|
+
return unless linked_resource = linked_resource(resource)
|
13
|
+
mapping.map{ |m| m.map(linked_resource) }.compact.reduce(&:merge)
|
14
|
+
end
|
15
|
+
|
16
|
+
attr_reader :mapping
|
17
|
+
|
18
|
+
private
|
19
|
+
|
20
|
+
def linked_resource(resource)
|
21
|
+
return unless resource.body._links.include?(@key)
|
22
|
+
return unless sub_resource = resource.send(@key)
|
23
|
+
sub_resource.show(enable_caching: @enable_caching)
|
24
|
+
rescue Routemaster::Errors::ResourceNotFound
|
25
|
+
nil
|
26
|
+
end
|
12
27
|
end
|
13
28
|
end
|
14
29
|
end
|
@@ -75,7 +75,7 @@ module Materialist
|
|
75
75
|
})
|
76
76
|
end
|
77
77
|
|
78
|
-
def
|
78
|
+
def mappings
|
79
79
|
options.fetch :mapping
|
80
80
|
end
|
81
81
|
|
@@ -112,49 +112,17 @@ module Materialist
|
|
112
112
|
end
|
113
113
|
|
114
114
|
def attributes
|
115
|
-
|
115
|
+
mappings.map{ |m| m.map(root_resource) }.compact.reduce(&:merge) || {}
|
116
116
|
end
|
117
117
|
|
118
118
|
def root_resource
|
119
|
-
@_root_resource ||=
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
return {} unless resource
|
124
|
-
|
125
|
-
mapping.inject({}) do |result, m|
|
126
|
-
case m
|
127
|
-
when FieldMapping
|
128
|
-
result.tap { |r| r[m.as] = resource.body[m.key] }
|
129
|
-
when LinkHrefMapping
|
130
|
-
result.tap do |r|
|
131
|
-
if resource.body._links.include?(m.key)
|
132
|
-
r[m.as] = resource.body._links[m.key].href
|
133
|
-
end
|
134
|
-
end
|
135
|
-
when LinkMapping
|
136
|
-
resource.body._links.include?(m.key) ?
|
137
|
-
result.merge(build_attributes(linked_resource(resource, m), m.mapping || [])) :
|
138
|
-
result
|
139
|
-
else
|
140
|
-
result
|
141
|
-
end
|
119
|
+
@_root_resource ||= begin
|
120
|
+
api_client.get(url, options: { enable_caching: false })
|
121
|
+
rescue Routemaster::Errors::ResourceNotFound
|
122
|
+
nil
|
142
123
|
end
|
143
124
|
end
|
144
125
|
|
145
|
-
def linked_resource(resource, mapping)
|
146
|
-
resource_at(resource.send(mapping.key).url, enable_caching: mapping.enable_caching)
|
147
|
-
end
|
148
|
-
|
149
|
-
def resource_at(url, enable_caching: false)
|
150
|
-
api_client.get(url, options: { enable_caching: enable_caching })
|
151
|
-
rescue Routemaster::Errors::ResourceNotFound
|
152
|
-
# this is due to a race condition between an upsert event
|
153
|
-
# and a :delete event
|
154
|
-
# when this happens we should silently ignore the case
|
155
|
-
nil
|
156
|
-
end
|
157
|
-
|
158
126
|
def api_client
|
159
127
|
@_api_client ||= Routemaster::APIClient.new(
|
160
128
|
response_class: Routemaster::Responses::HateoasResponse
|
@@ -16,8 +16,9 @@ module Materialist
|
|
16
16
|
|
17
17
|
report_latency(topic, timestamp) if timestamp
|
18
18
|
report_stats(topic, action, :success)
|
19
|
-
rescue
|
19
|
+
rescue Exception => exception
|
20
20
|
report_stats(topic, action, :failure)
|
21
|
+
notice_error(exception, event)
|
21
22
|
raise
|
22
23
|
end
|
23
24
|
|
@@ -38,6 +39,11 @@ module Materialist
|
|
38
39
|
tags: ["action:#{action}", "topic:#{topic}"]
|
39
40
|
)
|
40
41
|
end
|
42
|
+
|
43
|
+
def notice_error(exception, event)
|
44
|
+
return unless handler = Materialist.configuration.notice_error
|
45
|
+
handler.call(exception, event)
|
46
|
+
end
|
41
47
|
end
|
42
48
|
end
|
43
49
|
end
|
@@ -15,6 +15,9 @@ RSpec.describe Materialist::Materializer do
|
|
15
15
|
capture :name
|
16
16
|
capture :age, as: :how_old
|
17
17
|
capture_link_href :city, as: :city_url
|
18
|
+
capture_link_href :city, as: :city_id do |url|
|
19
|
+
url.split('/').last.to_i
|
20
|
+
end
|
18
21
|
capture_link_href :account, as: :account_url
|
19
22
|
|
20
23
|
materialize_link :city
|
@@ -81,6 +84,8 @@ RSpec.describe Materialist::Materializer do
|
|
81
84
|
expect(inserted.timezone).to eq city_body[:timezone]
|
82
85
|
expect(inserted.country_tld).to eq country_body[:tld]
|
83
86
|
expect(inserted.account_url).to be_nil
|
87
|
+
expect(inserted.city_url).to eq city_url
|
88
|
+
expect(inserted.city_id).to eq 1
|
84
89
|
end
|
85
90
|
|
86
91
|
it "materializes linked record separately in db" do
|
@@ -48,6 +48,20 @@ RSpec.describe Materialist::Workers::Event do
|
|
48
48
|
)
|
49
49
|
expect{ perform }.to raise_error error
|
50
50
|
end
|
51
|
+
|
52
|
+
context 'when there is notice_error configured' do
|
53
|
+
let(:configuration) { Materialist::Configuration.new.tap{ |c| c.notice_error = func } }
|
54
|
+
let(:func) { double }
|
55
|
+
|
56
|
+
before do
|
57
|
+
allow(Materialist).to receive(:configuration).and_return configuration
|
58
|
+
end
|
59
|
+
|
60
|
+
it 'calls the configured notice_error func' do
|
61
|
+
expect(func).to receive(:call).with(error, event)
|
62
|
+
expect{ perform }.to raise_error error
|
63
|
+
end
|
64
|
+
end
|
51
65
|
end
|
52
66
|
|
53
67
|
context 'when event has a timestamp' do
|
data/spec/schema.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: materialist
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 3.
|
4
|
+
version: 3.3.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Mo Valipour
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2018-
|
11
|
+
date: 2018-05-02 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: sidekiq
|