materialist 3.2.0 → 3.3.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.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
|