request_store_rails 1.0.3 → 2.0.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 +5 -5
- data/README.md +33 -4
- data/lib/request_locals.rb +22 -12
- data/lib/request_store_rails/middleware.rb +11 -7
- data/lib/request_store_rails/version.rb +1 -1
- metadata +3 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 7bd1299319b0c1e8167b6d68d55e69d4099439824beeac03f8a9fc0c715ee71b
|
4
|
+
data.tar.gz: 7d5a0b52520b5f09405ae262f5eb9c984d8faad49886e343331e76b7b1c88249
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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 `:
|
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 `:
|
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
|
-
|
96
|
+
store_id = RequestLocals.current_store_id
|
97
97
|
Thread.new {
|
98
|
-
|
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.
|
data/lib/request_locals.rb
CHANGED
@@ -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
|
9
|
-
# thread-local variable
|
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(
|
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(
|
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
|
6
|
-
#
|
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
|
14
|
-
# the
|
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
|
-
|
16
|
+
RequestLocals.set_current_store_id(extract_request_id(env))
|
17
17
|
@app.call(env)
|
18
18
|
ensure
|
19
19
|
RequestLocals.clear!
|
20
|
-
|
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
|
-
|
31
|
+
SecureRandom.uuid
|
28
32
|
end
|
29
33
|
end
|
30
34
|
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:
|
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:
|
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
|
-
|
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
|