request_store_rails 1.0.3 → 2.0.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: 6b370ace6ec755d1dc7fa029ee24f92eb5b9caac
4
- data.tar.gz: 59be0018678daaa9cf65c25305c8170fc41a9055
2
+ SHA256:
3
+ metadata.gz: 7bd1299319b0c1e8167b6d68d55e69d4099439824beeac03f8a9fc0c715ee71b
4
+ data.tar.gz: 7d5a0b52520b5f09405ae262f5eb9c984d8faad49886e343331e76b7b1c88249
5
5
  SHA512:
6
- metadata.gz: ff35f1f352936ce0858d15ec30b4e996a7e70e7d62a31137c0303000d1c374a1efa3e02ac6b03f4a7b9822297a693fc96c799ec002167ad32648a3383519349a
7
- data.tar.gz: 188fda858dd967a796197b6989e16ef88878eafe72d69dd61282b02cca96487168ea3fc7dc4824f89453261f3e7518ad46f9870c5b92f1d901b6100d1a4bd338
6
+ metadata.gz: 1a8fd3b6848bf8b92a74610e1803349388b93cbd64f1454c5df608483fb2283022db0210c4cf7d8c797059dd3aebdd038eedad4214672a6c4eabda6c19bb019d
7
+ data.tar.gz: 1ff7ff9d67e0d00447a904e2e3b80b130fca8a24b92759f6d2fd0d4cdcc8878fb28d958e58e7dd9eb1272faa1e5f7e2f47c99ff9d2d8f6c13446528256f4218b
data/README.md CHANGED
@@ -77,11 +77,11 @@ use RequestStoreRails::Middleware
77
77
  ```
78
78
 
79
79
  ## Multi-Threading
80
- The middleware in the gem sets a thread-local variable `:request_id` in
80
+ The middleware in the gem sets a thread-local variable `:request_store_id` in
81
81
  `Thread.current` for the main thread that is executing the request.
82
82
 
83
83
  If you need to spawn threads within a server that is already using thread-based
84
- concurrency, all you need to do is to make sure that the `:request_id`
84
+ concurrency, all you need to do is to make sure that the `:request_store_id`
85
85
  variable is set for your threads, and you will be able to access the
86
86
  `RequestLocals` as usual.
87
87
 
@@ -93,9 +93,9 @@ class ThreadWithContext
93
93
 
94
94
  # Public: Returns a new Thread that preserves the context of the current request.
95
95
  def ThreadWithContext.new(*args)
96
- request_id = Thread.current[:request_id]
96
+ store_id = RequestLocals.current_store_id
97
97
  Thread.new {
98
- Thread.current[:request_id] = request_id
98
+ RequestLocals.set_current_store_id(store_id)
99
99
  yield *args
100
100
  }
101
101
  end
@@ -133,6 +133,35 @@ if RequestStore != RequestLocals
133
133
  end
134
134
  ```
135
135
 
136
+ ## Usage in Sidekiq
137
+ If your code depends on these global variables, it's likely that you'll need
138
+ to avoid collisions in Sidekiq workers (which would happen if the current store
139
+ id is `nil`).
140
+
141
+ You can use the following middleware, using the job id to identify the store:
142
+
143
+ ```ruby
144
+ class Sidekiq::Middleware::Server::RequestStoreRails
145
+ def call(_worker, job, _queue)
146
+ RequestLocals.set_current_store_id(job['jid'])
147
+ yield
148
+ ensure
149
+ RequestLocals.clear!
150
+ RequestLocals.set_current_store_id(nil)
151
+ end
152
+ end
153
+ ```
154
+
155
+ Make sure to configure it as server middleware:
156
+
157
+ ```ruby
158
+ Sidekiq.configure_server do |config|
159
+ config.server_middleware do |chain|
160
+ chain.add Sidekiq::Middleware::Server::RequestStoreRails
161
+ end
162
+ end
163
+ ```
164
+
136
165
  ## Special Thanks
137
166
  The inspiration for this gem, tests, and a big part of the readme were borrowed
138
167
  from the really cool [`request_store`](https://github.com/steveklabnik/request_store) gem.
@@ -5,8 +5,8 @@ require 'concurrent'
5
5
  # Public: Provides per-request global storage, by offering an interface that is
6
6
  # very similar to Rails.cache, or Hash.
7
7
  #
8
- # The store may be shared between threads, as long as the :request_id
9
- # thread-local variable is set.
8
+ # The store may be shared between threads, as long as the current store id is
9
+ # set as a thread-local variable.
10
10
  #
11
11
  # Intended to work in collaboration with the RequestStoreRails middleware, that
12
12
  # will clear the request local variables after each request.
@@ -14,11 +14,15 @@ class RequestLocals
14
14
  include Singleton
15
15
  extend Forwardable
16
16
 
17
+ # Internal: The key of the thread-local variable the library uses to store the
18
+ # identifier of the current store, used during the request lifecycle.
19
+ REQUEST_STORE_ID = :request_store_id
20
+
17
21
  class << self
18
22
  extend Forwardable
19
23
 
20
24
  # Public: Public methods of RequestLocals, they are delegated to the Singleton instance.
21
- def_delegators :instance, :clear!, :clear_all!, :[], :[]=, :fetch, :delete, :exist?, :key?, :empty?
25
+ def_delegators :instance, :clear!, :clear_all!, :current_store_id, :[], :[]=, :fetch, :delete, :exist?, :key?, :empty?
22
26
 
23
27
  # Public: There is no accounting for taste, RequestLocals[:foo] vs RequestLocals.store[:foo]
24
28
  alias_method :store, :instance
@@ -46,7 +50,7 @@ class RequestLocals
46
50
  #
47
51
  # Returns nothing.
48
52
  def clear!
49
- @cache.delete(current_request_id)
53
+ @cache.delete(current_store_id)
50
54
  end
51
55
 
52
56
  # Public: Clears all the request-local variable stores.
@@ -75,6 +79,19 @@ class RequestLocals
75
79
  store.compute_if_absent(key, &block)
76
80
  end
77
81
 
82
+ # Public: The current request is inferred from the current thread.
83
+ #
84
+ # NOTE: It's very important to set the current store id when spawning new
85
+ # threads within a single request, using `RequestLocals.set_current_store_id`.
86
+ def current_store_id
87
+ Thread.current[REQUEST_STORE_ID]
88
+ end
89
+
90
+ # Public: Changes the store RequestLocals will read from in the current thread.
91
+ def self.set_current_store_id(id)
92
+ Thread.current[REQUEST_STORE_ID] = id
93
+ end
94
+
78
95
  protected
79
96
 
80
97
  # Internal: Returns the structure that holds the request-local variables for
@@ -82,14 +99,7 @@ protected
82
99
  #
83
100
  # Returns a ThreadSafe::Cache.
84
101
  def store
85
- @cache.compute_if_absent(current_request_id) { new_store }
86
- end
87
-
88
- # Internal: The current request is inferred from the current thread. It's very
89
- # important to pass on the :request_id thread local variable when spawning new
90
- # threads within a single request.
91
- def current_request_id
92
- Thread.current[:request_id]
102
+ @cache.compute_if_absent(current_store_id) { new_store }
93
103
  end
94
104
 
95
105
  # Internal: Returns a new empty structure where the request-local variables
@@ -2,29 +2,33 @@ require 'securerandom'
2
2
 
3
3
  module RequestStoreRails
4
4
 
5
- # Public: Middleware that takes care of setting the thread-local variable
6
- # :request_id, which enables RequestLocals to associate threads and requests.
5
+ # Public: Middleware that takes care of setting a thread-local variable, which
6
+ # enables RequestLocals to associate threads with the store for a request.
7
7
  class Middleware
8
8
 
9
9
  def initialize(app)
10
10
  @app = app
11
11
  end
12
12
 
13
- # Internal: Assigns the :request_id thread-local variable, and cleans up all
14
- # the request-local variables after the request.
13
+ # Internal: Assigns a thread-local variable to identify the current store,
14
+ # and cleans up all the variables stored for the request once it finishes.
15
15
  def call(env)
16
- Thread.current[:request_id] = extract_request_id(env)
16
+ RequestLocals.set_current_store_id(extract_request_id(env))
17
17
  @app.call(env)
18
18
  ensure
19
19
  RequestLocals.clear!
20
- Thread.current[:request_id] = nil
20
+ RequestLocals.set_current_store_id(nil)
21
21
  end
22
22
 
23
23
  protected
24
24
 
25
25
  # Internal: Extracts the request id from the environment, or generates one.
26
+ #
27
+ # NOTE: We always generate an id to prevent accidental conflicts from an
28
+ # externally provided one, but subclasses of this middleware might override
29
+ # it.
26
30
  def extract_request_id(env)
27
- env['action_dispatch.request_id'] || env['HTTP_X_REQUEST_ID'] || SecureRandom.hex(16)
31
+ SecureRandom.uuid
28
32
  end
29
33
  end
30
34
  end
@@ -1,4 +1,4 @@
1
1
  module RequestStoreRails
2
2
 
3
- VERSION = '1.0.3'
3
+ VERSION = '2.0.0'
4
4
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: request_store_rails
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.3
4
+ version: 2.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Máximo Mussini
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2017-06-06 00:00:00.000000000 Z
11
+ date: 2019-05-20 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rake
@@ -86,8 +86,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
86
86
  - !ruby/object:Gem::Version
87
87
  version: '0'
88
88
  requirements: []
89
- rubyforge_project:
90
- rubygems_version: 2.6.11
89
+ rubygems_version: 3.0.3
91
90
  signing_key:
92
91
  specification_version: 4
93
92
  summary: Per-request global storage for Rails