lhs 10.1.1 → 11.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitignore +1 -0
- data/Gemfile.activesupport4 +4 -0
- data/Gemfile.activesupport5 +4 -0
- data/README.md +34 -5
- data/Rakefile +1 -2
- data/cider-ci.yml +3 -1
- data/cider-ci/bin/bundle +11 -1
- data/cider-ci/jobs/rspec-activesupport-4.yml +26 -0
- data/cider-ci/jobs/rspec-activesupport-5.yml +26 -0
- data/cider-ci/jobs/{rspec.yml → rspec-activesupport-latest.yml} +3 -3
- data/cider-ci/task_components/rspec.yml +1 -2
- data/lhs.gemspec +2 -3
- data/lib/lhs.rb +9 -1
- data/lib/lhs/concerns/lhs/configuration.rb +18 -0
- data/lib/lhs/concerns/record/request.rb +14 -0
- data/lib/lhs/concerns/record/request_cycle_cache/interceptor.rb +38 -0
- data/lib/lhs/concerns/record/request_cycle_cache/request_cycle_thread_registry.rb +13 -0
- data/lib/lhs/config.rb +11 -0
- data/lib/lhs/railtie.rb +20 -0
- data/lib/lhs/record.rb +1 -0
- data/lib/lhs/version.rb +1 -1
- data/spec/autoloading_spec.rb +4 -4
- data/spec/dummy/app/controllers/request_cycle_cache_controller.rb +25 -0
- data/spec/dummy/app/models/user.rb +2 -2
- data/spec/dummy/config/environments/test.rb +0 -4
- data/spec/dummy/config/routes.rb +4 -53
- data/spec/record/includes_warning_spec.rb +1 -1
- data/spec/record/request_spec.rb +3 -2
- data/spec/request_cycle_cache/main_spec.rb +90 -0
- data/spec/support/request_cycle_cache.rb +7 -0
- metadata +23 -24
- data/spec/dummy/config/initializers/lhc.rb +0 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 47b77a705ee21920e7c48515fdf200b60bb2be61
|
4
|
+
data.tar.gz: d85c7e29b814b6ddda3c0729c1adfb405cc6e873
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 6351281d1b7f3d3c5cc08fe91ac35f6a747d6ffa543a41b9a6737e2634bc714fe1a340453ab887030af652063afdd3305c4da811ef1bafaab8acb89ba0cd12bf
|
7
|
+
data.tar.gz: 8aef3ee080ad5d7b6d0937138434ab2758b3941dfdfcc4fddbc38beb5a1dc16507b2929a4069dbc8ee5fbb09c4a59757a1adbfc3f1bab0cb23f8644fa43f0cf1
|
data/.gitignore
CHANGED
data/README.md
CHANGED
@@ -3,6 +3,21 @@ LHS
|
|
3
3
|
|
4
4
|
LHS uses [LHC](//github.com/local-ch/LHC) for http requests.
|
5
5
|
|
6
|
+
## Quickstart
|
7
|
+
|
8
|
+
```
|
9
|
+
gem 'lhs'
|
10
|
+
```
|
11
|
+
|
12
|
+
LHS comes with Request Cycle Cache – enabled by default. It requires [LHC Caching Interceptor](https://github.com/local-ch/lhc/blob/master/docs/interceptors/caching.md) to be enabled:
|
13
|
+
|
14
|
+
```ruby
|
15
|
+
# intializers/lhc.rb
|
16
|
+
LHC.configure do |config|
|
17
|
+
config.interceptors = [LHC::Caching]
|
18
|
+
end
|
19
|
+
```
|
20
|
+
|
6
21
|
## Very Short Introduction
|
7
22
|
|
8
23
|
Access data that is provided by an http json service with ease using a LHS::Record.
|
@@ -27,15 +42,13 @@ Please store all defined LHS::Records in `app/models` as they are not autoloaded
|
|
27
42
|
|
28
43
|
You setup a LHS::Record by configuring one or multiple endpoints. You can also add request options for an endpoint (see following example).
|
29
44
|
|
30
|
-
The following example uses the `LHC::Caching` interceptor from [lhc-core-interceptors](https://github.com/local-ch/lhc-core-interceptors#cache-interceptor).
|
31
|
-
|
32
45
|
```ruby
|
33
46
|
class Record < LHS::Record
|
34
47
|
|
35
48
|
endpoint ':service/v2/association/:association_id/records'
|
36
49
|
endpoint ':service/v2/association/:association_id/records/:id'
|
37
|
-
endpoint ':service/v2/records',
|
38
|
-
endpoint ':service/v2/records/:id',
|
50
|
+
endpoint ':service/v2/records', auth: { basic: 'PASSWORD' }
|
51
|
+
endpoint ':service/v2/records/:id', auth: { basic: 'PASSWORD' }
|
39
52
|
|
40
53
|
end
|
41
54
|
```
|
@@ -179,7 +192,7 @@ record = Record.where(color: 'blue')
|
|
179
192
|
|
180
193
|
If no record is found an error is raised.
|
181
194
|
|
182
|
-
`find` can also be used to find a single
|
195
|
+
`find` can also be used to find a single unique record with parameters:
|
183
196
|
|
184
197
|
```ruby
|
185
198
|
Record.find(association_id: 123, id: 456)
|
@@ -262,6 +275,22 @@ You can apply options to the request chain. Those options will be forwarded to t
|
|
262
275
|
authenticated_record.update(name: 'Steve')
|
263
276
|
```
|
264
277
|
|
278
|
+
## Request Cycle Cache
|
279
|
+
|
280
|
+
By default, LHS does not perform the same http request during one request cycle multiple times.
|
281
|
+
|
282
|
+
It uses the [LHC Caching Interceptor](https://github.com/local-ch/lhc/blob/master/docs/interceptors/caching.md) as caching mechanism base and sets a unique request id for every request cycle with Railties to ensure data is just cached within one request cycle and not shared with other requests.
|
283
|
+
|
284
|
+
Only GET requests are considered for caching by using LHC Caching Interceptor's `cache_methods` option internaly and considers request headers when caching requests, so requests with different headers are not served from cache.
|
285
|
+
|
286
|
+
The LHS Request Cycle Cache is opt-out, so it's enabled by default and will require you to enable the [LHC Caching Interceptor](https://github.com/local-ch/lhc/blob/master/docs/interceptors/caching.md) in your project.
|
287
|
+
|
288
|
+
If you want to disable the LHS Request Cycle Cache, simply disable it within configuration:
|
289
|
+
|
290
|
+
```ruby
|
291
|
+
LHS.config.request_cycle_cache_enabled = false
|
292
|
+
```
|
293
|
+
|
265
294
|
## Batch processing
|
266
295
|
|
267
296
|
**Be careful using methods for batch processing. They could result in a lot of HTTP requests!**
|
data/Rakefile
CHANGED
data/cider-ci.yml
CHANGED
data/cider-ci/bin/bundle
CHANGED
@@ -15,13 +15,23 @@ DIGEST=$(git ls-tree HEAD --\
|
|
15
15
|
cider-ci.yml cider-ci Gemfile.lock \
|
16
16
|
| openssl dgst -sha1 | cut -d ' ' -f 2)
|
17
17
|
|
18
|
+
if [ ! -z ${ACTIVESUPPORT:-} ]; then
|
19
|
+
DIGEST=$(echo "$DIGEST $ACTIVESUPPORT")
|
20
|
+
fi
|
21
|
+
|
18
22
|
DIGEST=$(echo "$DIGEST $PATH" \
|
19
23
|
| openssl dgst -sha1 | cut -d ' ' -f 2)
|
20
24
|
|
21
25
|
CACHE_SIGNATURE_FILE="/tmp/bundle_cache_signature_${DIGEST}"
|
22
26
|
|
23
27
|
if [ ! -f $CACHE_SIGNATURE_FILE ] ; then
|
24
|
-
|
28
|
+
if [ ! -z ${ACTIVESUPPORT:-} ]; then
|
29
|
+
echo "BUNDLE_GEMFILE=Gemfile.activesupport$ACTIVESUPPORT bundle install"
|
30
|
+
BUNDLE_GEMFILE=Gemfile.activesupport$ACTIVESUPPORT bundle install
|
31
|
+
else
|
32
|
+
echo "bundle install"
|
33
|
+
bundle install
|
34
|
+
fi
|
25
35
|
touch $CACHE_SIGNATURE_FILE
|
26
36
|
fi
|
27
37
|
|
@@ -0,0 +1,26 @@
|
|
1
|
+
rspec-active-support-v4:
|
2
|
+
name: 'rspec with ActiveSupport v4'
|
3
|
+
|
4
|
+
run_when:
|
5
|
+
'some HEAD has been updated':
|
6
|
+
type: branch
|
7
|
+
include_match: ^.*$
|
8
|
+
|
9
|
+
context:
|
10
|
+
|
11
|
+
script_defaults:
|
12
|
+
template_environment_variables: true
|
13
|
+
|
14
|
+
task_defaults:
|
15
|
+
environment_variables:
|
16
|
+
ACTIVESUPPORT: '4'
|
17
|
+
max_trials: 2
|
18
|
+
dispatch_storm_delay_duration: 1 Seconds
|
19
|
+
include:
|
20
|
+
- cider-ci/task_components/ruby.yml
|
21
|
+
- cider-ci/task_components/bundle.yml
|
22
|
+
- cider-ci/task_components/rspec.yml
|
23
|
+
|
24
|
+
tasks:
|
25
|
+
all-rspec:
|
26
|
+
name: All rspec tests, using ActiveSupport v4
|
@@ -0,0 +1,26 @@
|
|
1
|
+
rspec-active-support-v5:
|
2
|
+
name: 'rspec with ActiveSupport v5'
|
3
|
+
|
4
|
+
run_when:
|
5
|
+
'some HEAD has been updated':
|
6
|
+
type: branch
|
7
|
+
include_match: ^.*$
|
8
|
+
|
9
|
+
context:
|
10
|
+
|
11
|
+
script_defaults:
|
12
|
+
template_environment_variables: true
|
13
|
+
|
14
|
+
task_defaults:
|
15
|
+
environment_variables:
|
16
|
+
ACTIVESUPPORT: '5'
|
17
|
+
max_trials: 2
|
18
|
+
dispatch_storm_delay_duration: 1 Seconds
|
19
|
+
include:
|
20
|
+
- cider-ci/task_components/ruby.yml
|
21
|
+
- cider-ci/task_components/bundle.yml
|
22
|
+
- cider-ci/task_components/rspec.yml
|
23
|
+
|
24
|
+
tasks:
|
25
|
+
all-rspec:
|
26
|
+
name: All rspec tests, using ActiveSupport v5
|
@@ -1,5 +1,5 @@
|
|
1
|
-
rspec:
|
2
|
-
name: 'rspec'
|
1
|
+
rspec-active-support-latest:
|
2
|
+
name: 'rspec with ActiveSupport latest'
|
3
3
|
|
4
4
|
run_when:
|
5
5
|
'some HEAD has been updated':
|
@@ -21,4 +21,4 @@ rspec:
|
|
21
21
|
|
22
22
|
tasks:
|
23
23
|
all-rspec:
|
24
|
-
name: All rspec tests
|
24
|
+
name: All rspec tests, using ActiveSupport latest
|
@@ -17,13 +17,12 @@ scripts:
|
|
17
17
|
set -eux
|
18
18
|
mkdir -p tmp/cache
|
19
19
|
export PATH=~/.rubies/$RUBY/bin:$PATH
|
20
|
-
bundle exec rspec
|
20
|
+
if [ ! -z ${ACTIVESUPPORT:-} ]; then BUNDLE_GEMFILE=Gemfile.activesupport$ACTIVESUPPORT bundle exec rspec; else bundle exec rspec; fi
|
21
21
|
|
22
22
|
start_when:
|
23
23
|
'bundled':
|
24
24
|
script_key: bundle
|
25
25
|
|
26
|
-
|
27
26
|
trial_attachments:
|
28
27
|
logs:
|
29
28
|
include_match: log\/.*\.log$
|
data/lhs.gemspec
CHANGED
@@ -20,9 +20,8 @@ Gem::Specification.new do |s|
|
|
20
20
|
s.requirements << 'Ruby >= 2.0.0'
|
21
21
|
s.required_ruby_version = '>= 2.0.0'
|
22
22
|
|
23
|
-
s.add_dependency 'lhc', '>=
|
24
|
-
s.add_dependency '
|
25
|
-
s.add_dependency 'activesupport', '> 4'
|
23
|
+
s.add_dependency 'lhc', '>= 5.0.2'
|
24
|
+
s.add_dependency 'activesupport', '> 4.2'
|
26
25
|
|
27
26
|
s.add_development_dependency 'rspec-rails', '>= 3.0.0'
|
28
27
|
s.add_development_dependency 'rails', '>= 4.0.0'
|
data/lib/lhs.rb
CHANGED
@@ -1,6 +1,8 @@
|
|
1
1
|
require 'lhc'
|
2
|
+
Dir[File.dirname(__FILE__) + '/lhs/concerns/lhs/*.rb'].sort.each { |file| require file }
|
2
3
|
|
3
4
|
module LHS
|
5
|
+
include Configuration
|
4
6
|
class RequireLhsRecords
|
5
7
|
def initialize(app)
|
6
8
|
@app = app
|
@@ -19,7 +21,13 @@ module LHS
|
|
19
21
|
end
|
20
22
|
end
|
21
23
|
|
22
|
-
Gem.find_files('lhs/**/*.rb')
|
24
|
+
Gem.find_files('lhs/**/*.rb')
|
25
|
+
.sort
|
26
|
+
.reject do |path|
|
27
|
+
(!defined?(Rails) && File.basename(path).include?('railtie.rb')) # don't require railtie if Rails is not around
|
28
|
+
end.each do |path|
|
29
|
+
require path
|
30
|
+
end
|
23
31
|
|
24
32
|
# Preload all the LHS::Records that are defined in app/models
|
25
33
|
class Engine < Rails::Engine
|
@@ -0,0 +1,18 @@
|
|
1
|
+
require 'active_support'
|
2
|
+
|
3
|
+
module LHS
|
4
|
+
module Configuration
|
5
|
+
extend ActiveSupport::Concern
|
6
|
+
|
7
|
+
module ClassMethods
|
8
|
+
def config
|
9
|
+
LHS::Config.instance
|
10
|
+
end
|
11
|
+
|
12
|
+
def configure
|
13
|
+
LHS::Config.instance.reset
|
14
|
+
yield config
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -377,9 +377,23 @@ class LHS::Record
|
|
377
377
|
options[:url] = compute_url!(options[:params]) unless options.key?(:url)
|
378
378
|
merge_explicit_params!(options[:params])
|
379
379
|
options.delete(:params) if options[:params] && options[:params].empty?
|
380
|
+
inject_request_cycle_cache!(options)
|
380
381
|
options
|
381
382
|
end
|
382
383
|
|
384
|
+
# Injects options into request, that enable the LHS::Record::RequestCycleCache::Interceptor
|
385
|
+
def inject_request_cycle_cache!(options)
|
386
|
+
return unless LHS.config.request_cycle_cache_enabled
|
387
|
+
interceptors = options[:interceptors] || LHC.config.interceptors
|
388
|
+
if interceptors.include?(LHC::Caching)
|
389
|
+
# Ensure LHS::RequestCycleCache interceptor is prepend
|
390
|
+
interceptors = interceptors.unshift(LHS::Record::RequestCycleCache::Interceptor)
|
391
|
+
options[:interceptors] = interceptors
|
392
|
+
else
|
393
|
+
warn(LHS::Record::REQUEST_CYCLE_CACHE_WARNING)
|
394
|
+
end
|
395
|
+
end
|
396
|
+
|
383
397
|
# LHC supports only one error handler, merge all error handlers to one
|
384
398
|
# and reraise
|
385
399
|
def merge_error_handlers(handlers)
|
@@ -0,0 +1,38 @@
|
|
1
|
+
require 'active_support'
|
2
|
+
|
3
|
+
class LHS::Record
|
4
|
+
|
5
|
+
module RequestCycleCache
|
6
|
+
extend ActiveSupport::Concern
|
7
|
+
|
8
|
+
REQUEST_CYCLE_CACHE_WARNING = "[WARNING] Can't enable LHS::RequestCycleCache as LHC::Caching interceptor is not enabled/configured (see https://github.com/local-ch/lhc/blob/master/docs/interceptors/caching.md#caching-interceptor)!".freeze
|
9
|
+
|
10
|
+
class Interceptor < LHC::Interceptor
|
11
|
+
|
12
|
+
VERSION = 1
|
13
|
+
CACHED_METHODS = [:get].freeze
|
14
|
+
|
15
|
+
def before_request(request)
|
16
|
+
request.options = request.options.merge({
|
17
|
+
cache: true,
|
18
|
+
cache_expires_in: 5.minutes,
|
19
|
+
cache_race_condition_ttl: 5.seconds,
|
20
|
+
cache_key: cache_key_for(request),
|
21
|
+
cached_methods: CACHED_METHODS
|
22
|
+
}.merge(request.options))
|
23
|
+
end
|
24
|
+
|
25
|
+
private
|
26
|
+
|
27
|
+
def cache_key_for(request)
|
28
|
+
[
|
29
|
+
"LHS_REQUEST_CYCLE_CACHE(v#{VERSION})",
|
30
|
+
request.method.upcase,
|
31
|
+
[request.url, request.params.presence].compact.join('?'),
|
32
|
+
"REQUEST=#{LHS::Record::RequestCycleCache::RequestCycleThreadRegistry.request_id}",
|
33
|
+
"HEADERS=#{request.headers.hash}"
|
34
|
+
].join(' ')
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
require 'active_support'
|
2
|
+
|
3
|
+
class LHS::Record
|
4
|
+
|
5
|
+
module RequestCycleCache
|
6
|
+
class RequestCycleThreadRegistry
|
7
|
+
# Using ActiveSupports PerThreadRegistry to be able to support Active Support v4.
|
8
|
+
# Will switch to thread_mattr_accessor (which comes with Activesupport) when we dropping support for Active Support v5.
|
9
|
+
extend ActiveSupport::PerThreadRegistry
|
10
|
+
attr_accessor :request_id
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
data/lib/lhs/config.rb
ADDED
data/lib/lhs/railtie.rb
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
module LHS
|
2
|
+
class Railtie < Rails::Railtie
|
3
|
+
initializer "lhs.hook_into_controller_initialization" do
|
4
|
+
class ActionController::Base
|
5
|
+
|
6
|
+
def initialize
|
7
|
+
prepare_lhs_request_cycle_cache
|
8
|
+
super
|
9
|
+
end
|
10
|
+
|
11
|
+
private
|
12
|
+
|
13
|
+
def prepare_lhs_request_cycle_cache
|
14
|
+
return unless LHS.config.request_cycle_cache_enabled
|
15
|
+
LHS::Record::RequestCycleCache::RequestCycleThreadRegistry.request_id = [Time.now.to_f, request.object_id].join('#')
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
data/lib/lhs/record.rb
CHANGED
data/lib/lhs/version.rb
CHANGED
data/spec/autoloading_spec.rb
CHANGED
@@ -6,13 +6,13 @@ describe LHS, type: :request do
|
|
6
6
|
because it's necessary for endpoint-to-record-class-discovery",
|
7
7
|
cleanup_before: false do
|
8
8
|
all_endpoints = LHS::Record::Endpoints.all
|
9
|
-
expect(all_endpoints['
|
10
|
-
expect(all_endpoints['
|
9
|
+
expect(all_endpoints['http://datastore/v2/users']).to be
|
10
|
+
expect(all_endpoints['http://datastore/v2/users/:id']).to be
|
11
11
|
expect(
|
12
|
-
User.endpoints.detect { |endpoint| endpoint.url == '
|
12
|
+
User.endpoints.detect { |endpoint| endpoint.url == 'http://datastore/v2/users' }
|
13
13
|
).to be
|
14
14
|
expect(
|
15
|
-
User.endpoints.detect { |endpoint| endpoint.url == '
|
15
|
+
User.endpoints.detect { |endpoint| endpoint.url == 'http://datastore/v2/users/:id' }
|
16
16
|
).to be
|
17
17
|
end
|
18
18
|
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
class RequestCycleCacheController < ApplicationController
|
2
|
+
def simple
|
3
|
+
User.find(1) # first request
|
4
|
+
user = User.find(1) # second request that should be serverd from request cycle cache
|
5
|
+
render json: user.to_json
|
6
|
+
end
|
7
|
+
|
8
|
+
def no_caching_interceptor
|
9
|
+
User.options(interceptors: []).find(1) # first request
|
10
|
+
user = User.options(interceptors: []).find(1) # second request
|
11
|
+
render json: user.to_json
|
12
|
+
end
|
13
|
+
|
14
|
+
def parallel
|
15
|
+
User.find(1, 2) # first request
|
16
|
+
users = User.find(1, 2) # second request that should be serverd from request cycle cache
|
17
|
+
render json: users.to_json
|
18
|
+
end
|
19
|
+
|
20
|
+
def headers
|
21
|
+
User.find(1) # first request
|
22
|
+
user = User.options(headers: { 'Authentication' => 'Bearer 123' }).find(1) # second request that should NOT be serverd from request cycle cache as the headers are different
|
23
|
+
render json: user.to_json
|
24
|
+
end
|
25
|
+
end
|
@@ -12,10 +12,6 @@ Rails.application.configure do
|
|
12
12
|
# preloads Rails for running tests, you may have to set it to true.
|
13
13
|
config.eager_load = false
|
14
14
|
|
15
|
-
# Configure static asset server for tests with Cache-Control for performance.
|
16
|
-
config.public_file_server.enabled = true
|
17
|
-
config.public_file_server.headers = { 'Cache-Control' => 'public, max-age=3600' }
|
18
|
-
|
19
15
|
# Show full error reports and disable caching.
|
20
16
|
config.consider_all_requests_local = true
|
21
17
|
config.action_controller.perform_caching = false
|
data/spec/dummy/config/routes.rb
CHANGED
@@ -1,56 +1,7 @@
|
|
1
1
|
Rails.application.routes.draw do
|
2
|
-
# The priority is based upon order of creation: first created -> highest priority.
|
3
|
-
# See how all your routes lay out with "rake routes".
|
4
|
-
|
5
|
-
# You can have the root of your site routed with "root"
|
6
2
|
root 'application#root'
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
# Example of named route that can be invoked with purchase_url(id: product.id)
|
12
|
-
# get 'products/:id/purchase' => 'catalog#purchase', as: :purchase
|
13
|
-
|
14
|
-
# Example resource route (maps HTTP verbs to controller actions automatically):
|
15
|
-
# resources :products
|
16
|
-
|
17
|
-
# Example resource route with options:
|
18
|
-
# resources :products do
|
19
|
-
# member do
|
20
|
-
# get 'short'
|
21
|
-
# post 'toggle'
|
22
|
-
# end
|
23
|
-
#
|
24
|
-
# collection do
|
25
|
-
# get 'sold'
|
26
|
-
# end
|
27
|
-
# end
|
28
|
-
|
29
|
-
# Example resource route with sub-resources:
|
30
|
-
# resources :products do
|
31
|
-
# resources :comments, :sales
|
32
|
-
# resource :seller
|
33
|
-
# end
|
34
|
-
|
35
|
-
# Example resource route with more complex sub-resources:
|
36
|
-
# resources :products do
|
37
|
-
# resources :comments
|
38
|
-
# resources :sales do
|
39
|
-
# get 'recent', on: :collection
|
40
|
-
# end
|
41
|
-
# end
|
42
|
-
|
43
|
-
# Example resource route with concerns:
|
44
|
-
# concern :toggleable do
|
45
|
-
# post 'toggle'
|
46
|
-
# end
|
47
|
-
# resources :posts, concerns: :toggleable
|
48
|
-
# resources :photos, concerns: :toggleable
|
49
|
-
|
50
|
-
# Example resource route within a namespace:
|
51
|
-
# namespace :admin do
|
52
|
-
# # Directs /admin/products/* to Admin::ProductsController
|
53
|
-
# # (app/controllers/admin/products_controller.rb)
|
54
|
-
# resources :products
|
55
|
-
# end
|
3
|
+
get 'request_cycle_cache/simple' => 'request_cycle_cache#simple'
|
4
|
+
get 'request_cycle_cache/no_caching_interceptor' => 'request_cycle_cache#no_caching_interceptor'
|
5
|
+
get 'request_cycle_cache/parallel' => 'request_cycle_cache#parallel'
|
6
|
+
get 'request_cycle_cache/headers' => 'request_cycle_cache#headers'
|
56
7
|
end
|
@@ -37,7 +37,7 @@ describe LHS::Record do
|
|
37
37
|
expect(lambda {
|
38
38
|
Customer.includes(:contracts).find(1)
|
39
39
|
}).to output(
|
40
|
-
|
40
|
+
%r{\[WARNING\] You included `http://datastore/customers/1/contracts`, but this endpoint is paginated. You might want to use `includes_all` instead of `includes` \(https://github.com/local-ch/lhs#includes_all-for-paginated-endpoints\)\.}
|
41
41
|
).to_stderr
|
42
42
|
end
|
43
43
|
end
|
data/spec/record/request_spec.rb
CHANGED
@@ -13,8 +13,9 @@ describe LHS::Record do
|
|
13
13
|
end
|
14
14
|
|
15
15
|
it 'is using params as query params explicitly when provided in params namespace' do
|
16
|
-
stub_request(:get, "#{datastore}/content-ads/123/feedbacks?campaign_id=456").to_return(status: 200)
|
17
|
-
Record.where(campaign_id: 123, params: { campaign_id: '456' })
|
16
|
+
request = stub_request(:get, "#{datastore}/content-ads/123/feedbacks?campaign_id=456").to_return(status: 200)
|
17
|
+
Record.where(campaign_id: 123, params: { campaign_id: '456' }).to_a
|
18
|
+
assert_requested(request)
|
18
19
|
end
|
19
20
|
end
|
20
21
|
end
|
@@ -0,0 +1,90 @@
|
|
1
|
+
require 'rails_helper'
|
2
|
+
require 'lhc/test/cache_helper.rb'
|
3
|
+
|
4
|
+
describe 'Request Cycle Cache', type: :request do
|
5
|
+
let!(:request) do
|
6
|
+
stub_request(:get, "http://datastore/v2/users/1").to_return(body: { name: 'Steve' }.to_json)
|
7
|
+
end
|
8
|
+
|
9
|
+
let!(:second_request) do
|
10
|
+
stub_request(:get, "http://datastore/v2/users/2").to_return(body: { name: 'Peter' }.to_json)
|
11
|
+
end
|
12
|
+
|
13
|
+
before(:each) do
|
14
|
+
class User < LHS::Record
|
15
|
+
endpoint 'http://datastore/v2/users'
|
16
|
+
endpoint 'http://datastore/v2/users/:id'
|
17
|
+
end
|
18
|
+
LHC.configure do |config|
|
19
|
+
config.interceptors = [LHC::Caching]
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
it 'serves requests that are exactly the same during one request cycle from the cache',
|
24
|
+
cleanup_before: false, request_cycle_cache: true do
|
25
|
+
get '/request_cycle_cache/simple'
|
26
|
+
expect(request).to have_been_made.once
|
27
|
+
|
28
|
+
# Second Request, Second Cycle, requests again
|
29
|
+
get '/request_cycle_cache/simple'
|
30
|
+
expect(request).to have_been_made.times(2)
|
31
|
+
end
|
32
|
+
|
33
|
+
it 'does not serve from request cycle cache when cache interceptor is not hooked in, but logs a warning',
|
34
|
+
cleanup_before: false, request_cycle_cache: true do
|
35
|
+
expect(lambda do
|
36
|
+
get '/request_cycle_cache/no_caching_interceptor'
|
37
|
+
end).to output(
|
38
|
+
%r{\[WARNING\] Can't enable LHS::RequestCycleCache as LHC::Caching interceptor is not enabled/configured \(see https://github.com/local-ch/lhc/blob/master/docs/interceptors/caching.md#caching-interceptor\)!}
|
39
|
+
).to_stderr
|
40
|
+
expect(request).to have_been_made.times(2)
|
41
|
+
end
|
42
|
+
|
43
|
+
it 'serves requests also from cache when LHS/LHC makes requests in parallel',
|
44
|
+
cleanup_before: false, request_cycle_cache: true do
|
45
|
+
get '/request_cycle_cache/parallel'
|
46
|
+
expect(request).to have_been_made.once
|
47
|
+
expect(second_request).to have_been_made.once
|
48
|
+
end
|
49
|
+
|
50
|
+
it 'sets different uniq request ids as base for request cycle caching for different requests',
|
51
|
+
cleanup_before: false, request_cycle_cache: true do
|
52
|
+
get '/request_cycle_cache/simple'
|
53
|
+
first_request_id = LHS::Record::RequestCycleCache::RequestCycleThreadRegistry.request_id
|
54
|
+
second_request_id = nil
|
55
|
+
thread = Thread.new do
|
56
|
+
get '/request_cycle_cache/simple'
|
57
|
+
second_request_id = LHS::Record::RequestCycleCache::RequestCycleThreadRegistry.request_id
|
58
|
+
end
|
59
|
+
thread.join
|
60
|
+
expect(first_request_id).not_to be_nil
|
61
|
+
expect(second_request_id).not_to be_nil
|
62
|
+
expect(first_request_id).not_to eq second_request_id
|
63
|
+
end
|
64
|
+
|
65
|
+
context 'disabled request cycle cache' do
|
66
|
+
it 'does not serve from request cycle cache when cache interceptor is not hooked in, and does not warn if request cycle cache is explicitly disabled',
|
67
|
+
cleanup_before: false do
|
68
|
+
expect(lambda do
|
69
|
+
get '/request_cycle_cache/no_caching_interceptor'
|
70
|
+
end).not_to output(
|
71
|
+
%r{\[WARNING\] Can't enable LHS::RequestCycleCache as LHC::Caching interceptor is not enabled/configured \(see https://github.com/local-ch/lhc/blob/master/docs/interceptors/caching.md#caching-interceptor\)!}
|
72
|
+
).to_stderr
|
73
|
+
expect(request).to have_been_made.times(2)
|
74
|
+
end
|
75
|
+
|
76
|
+
it 'DOES NOT serve requests that are exactly the same during one request cycle from the cache, when request cycle cache is disabled',
|
77
|
+
cleanup_before: false do
|
78
|
+
get '/request_cycle_cache/simple'
|
79
|
+
expect(request).to have_been_made.times(2)
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
context 'headers' do
|
84
|
+
it 'considers the request headers when setting the cache key',
|
85
|
+
cleanup_before: false, request_cycle_cache: true do
|
86
|
+
get '/request_cycle_cache/headers'
|
87
|
+
expect(request).to have_been_made.times(2)
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: lhs
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
4
|
+
version: 11.0.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- https://github.com/local-ch/lhs/graphs/contributors
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2017-
|
11
|
+
date: 2017-04-27 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: lhc
|
@@ -16,42 +16,28 @@ dependencies:
|
|
16
16
|
requirements:
|
17
17
|
- - ">="
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version:
|
19
|
+
version: 5.0.2
|
20
20
|
type: :runtime
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
24
|
- - ">="
|
25
25
|
- !ruby/object:Gem::Version
|
26
|
-
version:
|
27
|
-
- !ruby/object:Gem::Dependency
|
28
|
-
name: lhc-core-interceptors
|
29
|
-
requirement: !ruby/object:Gem::Requirement
|
30
|
-
requirements:
|
31
|
-
- - ">="
|
32
|
-
- !ruby/object:Gem::Version
|
33
|
-
version: 2.0.1
|
34
|
-
type: :runtime
|
35
|
-
prerelease: false
|
36
|
-
version_requirements: !ruby/object:Gem::Requirement
|
37
|
-
requirements:
|
38
|
-
- - ">="
|
39
|
-
- !ruby/object:Gem::Version
|
40
|
-
version: 2.0.1
|
26
|
+
version: 5.0.2
|
41
27
|
- !ruby/object:Gem::Dependency
|
42
28
|
name: activesupport
|
43
29
|
requirement: !ruby/object:Gem::Requirement
|
44
30
|
requirements:
|
45
31
|
- - ">"
|
46
32
|
- !ruby/object:Gem::Version
|
47
|
-
version: '4'
|
33
|
+
version: '4.2'
|
48
34
|
type: :runtime
|
49
35
|
prerelease: false
|
50
36
|
version_requirements: !ruby/object:Gem::Requirement
|
51
37
|
requirements:
|
52
38
|
- - ">"
|
53
39
|
- !ruby/object:Gem::Version
|
54
|
-
version: '4'
|
40
|
+
version: '4.2'
|
55
41
|
- !ruby/object:Gem::Dependency
|
56
42
|
name: rspec-rails
|
57
43
|
requirement: !ruby/object:Gem::Requirement
|
@@ -177,13 +163,17 @@ files:
|
|
177
163
|
- ".rubocop.yml"
|
178
164
|
- ".ruby-version"
|
179
165
|
- Gemfile
|
166
|
+
- Gemfile.activesupport4
|
167
|
+
- Gemfile.activesupport5
|
180
168
|
- README.md
|
181
169
|
- Rakefile
|
182
170
|
- cider-ci.yml
|
183
171
|
- cider-ci/bin/bundle
|
184
172
|
- cider-ci/bin/ruby_install
|
185
173
|
- cider-ci/bin/ruby_version
|
186
|
-
- cider-ci/jobs/rspec.yml
|
174
|
+
- cider-ci/jobs/rspec-activesupport-4.yml
|
175
|
+
- cider-ci/jobs/rspec-activesupport-5.yml
|
176
|
+
- cider-ci/jobs/rspec-activesupport-latest.yml
|
187
177
|
- cider-ci/jobs/rubocop.yml
|
188
178
|
- cider-ci/task_components/bundle.yml
|
189
179
|
- cider-ci/task_components/rspec.yml
|
@@ -202,6 +192,7 @@ files:
|
|
202
192
|
- lib/lhs/concerns/item/save.rb
|
203
193
|
- lib/lhs/concerns/item/update.rb
|
204
194
|
- lib/lhs/concerns/item/validation.rb
|
195
|
+
- lib/lhs/concerns/lhs/configuration.rb
|
205
196
|
- lib/lhs/concerns/proxy/accessors.rb
|
206
197
|
- lib/lhs/concerns/proxy/create.rb
|
207
198
|
- lib/lhs/concerns/proxy/link.rb
|
@@ -219,7 +210,10 @@ files:
|
|
219
210
|
- lib/lhs/concerns/record/model.rb
|
220
211
|
- lib/lhs/concerns/record/pagination.rb
|
221
212
|
- lib/lhs/concerns/record/request.rb
|
213
|
+
- lib/lhs/concerns/record/request_cycle_cache/interceptor.rb
|
214
|
+
- lib/lhs/concerns/record/request_cycle_cache/request_cycle_thread_registry.rb
|
222
215
|
- lib/lhs/concerns/record/scope.rb
|
216
|
+
- lib/lhs/config.rb
|
223
217
|
- lib/lhs/data.rb
|
224
218
|
- lib/lhs/endpoint.rb
|
225
219
|
- lib/lhs/errors.rb
|
@@ -229,6 +223,7 @@ files:
|
|
229
223
|
- lib/lhs/pagination/page.rb
|
230
224
|
- lib/lhs/pagination/start.rb
|
231
225
|
- lib/lhs/proxy.rb
|
226
|
+
- lib/lhs/railtie.rb
|
232
227
|
- lib/lhs/record.rb
|
233
228
|
- lib/lhs/version.rb
|
234
229
|
- script/ci/build.sh
|
@@ -262,6 +257,7 @@ files:
|
|
262
257
|
- spec/dummy/app/assets/stylesheets/application.css
|
263
258
|
- spec/dummy/app/controllers/application_controller.rb
|
264
259
|
- spec/dummy/app/controllers/concerns/.keep
|
260
|
+
- spec/dummy/app/controllers/request_cycle_cache_controller.rb
|
265
261
|
- spec/dummy/app/helpers/application_helper.rb
|
266
262
|
- spec/dummy/app/mailers/.keep
|
267
263
|
- spec/dummy/app/models/.keep
|
@@ -284,7 +280,6 @@ files:
|
|
284
280
|
- spec/dummy/config/initializers/cookies_serializer.rb
|
285
281
|
- spec/dummy/config/initializers/filter_parameter_logging.rb
|
286
282
|
- spec/dummy/config/initializers/inflections.rb
|
287
|
-
- spec/dummy/config/initializers/lhc.rb
|
288
283
|
- spec/dummy/config/initializers/mime_types.rb
|
289
284
|
- spec/dummy/config/initializers/session_store.rb
|
290
285
|
- spec/dummy/config/initializers/wrap_parameters.rb
|
@@ -359,12 +354,14 @@ files:
|
|
359
354
|
- spec/record/where_chains_spec.rb
|
360
355
|
- spec/record/where_spec.rb
|
361
356
|
- spec/record/where_values_hash_spec.rb
|
357
|
+
- spec/request_cycle_cache/main_spec.rb
|
362
358
|
- spec/spec_helper.rb
|
363
359
|
- spec/support/cleanup.rb
|
364
360
|
- spec/support/fixtures/json/feedback.json
|
365
361
|
- spec/support/fixtures/json/feedbacks.json
|
366
362
|
- spec/support/fixtures/json/localina_content_ad.json
|
367
363
|
- spec/support/load_json.rb
|
364
|
+
- spec/support/request_cycle_cache.rb
|
368
365
|
- spec/views/form_for_spec.rb
|
369
366
|
homepage: https://github.com/local-ch/lhs
|
370
367
|
licenses:
|
@@ -387,7 +384,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
387
384
|
requirements:
|
388
385
|
- Ruby >= 2.0.0
|
389
386
|
rubyforge_project:
|
390
|
-
rubygems_version: 2.
|
387
|
+
rubygems_version: 2.6.8
|
391
388
|
signing_key:
|
392
389
|
specification_version: 4
|
393
390
|
summary: Rails gem providing an easy, active-record-like interface for http json services
|
@@ -421,6 +418,7 @@ test_files:
|
|
421
418
|
- spec/dummy/app/assets/stylesheets/application.css
|
422
419
|
- spec/dummy/app/controllers/application_controller.rb
|
423
420
|
- spec/dummy/app/controllers/concerns/.keep
|
421
|
+
- spec/dummy/app/controllers/request_cycle_cache_controller.rb
|
424
422
|
- spec/dummy/app/helpers/application_helper.rb
|
425
423
|
- spec/dummy/app/mailers/.keep
|
426
424
|
- spec/dummy/app/models/.keep
|
@@ -443,7 +441,6 @@ test_files:
|
|
443
441
|
- spec/dummy/config/initializers/cookies_serializer.rb
|
444
442
|
- spec/dummy/config/initializers/filter_parameter_logging.rb
|
445
443
|
- spec/dummy/config/initializers/inflections.rb
|
446
|
-
- spec/dummy/config/initializers/lhc.rb
|
447
444
|
- spec/dummy/config/initializers/mime_types.rb
|
448
445
|
- spec/dummy/config/initializers/session_store.rb
|
449
446
|
- spec/dummy/config/initializers/wrap_parameters.rb
|
@@ -518,10 +515,12 @@ test_files:
|
|
518
515
|
- spec/record/where_chains_spec.rb
|
519
516
|
- spec/record/where_spec.rb
|
520
517
|
- spec/record/where_values_hash_spec.rb
|
518
|
+
- spec/request_cycle_cache/main_spec.rb
|
521
519
|
- spec/spec_helper.rb
|
522
520
|
- spec/support/cleanup.rb
|
523
521
|
- spec/support/fixtures/json/feedback.json
|
524
522
|
- spec/support/fixtures/json/feedbacks.json
|
525
523
|
- spec/support/fixtures/json/localina_content_ad.json
|
526
524
|
- spec/support/load_json.rb
|
525
|
+
- spec/support/request_cycle_cache.rb
|
527
526
|
- spec/views/form_for_spec.rb
|