consistent_random 2.0.0 → 2.1.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +13 -0
- data/README.md +66 -7
- data/VERSION +1 -1
- data/lib/consistent_random/rack_middleware.rb +9 -2
- data/lib/consistent_random/sidekiq_middleware.rb +20 -0
- data/lib/consistent_random.rb +6 -6
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: e59a824de4f8d0a629bf033a675d48f3f5d40b6ffda07f0cf32c8f39d50dc7a2
|
4
|
+
data.tar.gz: '08df13b6bbc9005e38fef21e05768b23eb1c1cbe36cda08694a0ce16bd800baa'
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 31a8b9bb4996cefee885f4c2c3c251931b86db801443bbe9cafc383c882e7e4ae8be133a8d1d6b5032dcd1422c9906b33c2813ad1f857a0e81b2c81074a7a29d
|
7
|
+
data.tar.gz: 76ae572f27d9e1ca92216e77d878b75bd934f0c81a03abdb1e811181a49fdd0e22231ce1a236f019274701aa35d80c16d3e3e6a898a853df85294a82edb561bd
|
data/CHANGELOG.md
CHANGED
@@ -4,6 +4,19 @@ All notable changes to this project will be documented in this file.
|
|
4
4
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
5
5
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
6
6
|
|
7
|
+
## 2.1.1
|
8
|
+
|
9
|
+
### Fixed
|
10
|
+
|
11
|
+
- Fixed typo in `==` method which caused a NoMethodError when comparing ConsistentRandom instances.
|
12
|
+
|
13
|
+
## 2.1.0
|
14
|
+
|
15
|
+
### Added
|
16
|
+
|
17
|
+
- Added optional seed block to the Rack middleware to allow for custom seed values based on the request.
|
18
|
+
- Added helper method `ConsistentRandom::SidekiqMiddleware.install` to install both the client and server middlewares in one call.
|
19
|
+
|
7
20
|
## 2.0.0
|
8
21
|
|
9
22
|
### Changed
|
data/README.md
CHANGED
@@ -8,11 +8,23 @@
|
|
8
8
|
|
9
9
|
This Ruby gem allows you to generate consistent random values tied to a specific name within a defined scope. It ensures that random behavior remains consistent within a particular context.
|
10
10
|
|
11
|
+
Consistent Random is designed to simplify feature rollouts and other scenarios where you need to generate random values, but need those values to remain consistent within defined contexts.
|
12
|
+
|
11
13
|
For example, consider rolling out a new feature to a subset of requests. You may want to do this to allow testing a new feature by only enabling it for 10% of requests. You want to randomize which requests get the new feature, but ensure that within each request, the feature is consistently enabled or disabled across all actions. This gem allows you to achieve that by tying random values to specific names and defining a scope. Within that scope, the same value will be consistently generated for each named variable.
|
12
14
|
|
15
|
+
## Table of Contents
|
16
|
+
- [Usage](#usage)
|
17
|
+
- [Middlewares](#middlewares)
|
18
|
+
- [Rack Middleware](#rack-middleware)
|
19
|
+
- [Sidekiq Middleware](#sidekiq-middleware)
|
20
|
+
- [ActiveJob](#activejob)
|
21
|
+
- [Installation](#installation)
|
22
|
+
- [Contributing](#contributing)
|
23
|
+
- [License](#license)
|
24
|
+
|
13
25
|
## Usage
|
14
26
|
|
15
|
-
To generate consistent random values, you need to define a scope.
|
27
|
+
To generate consistent random values, you need to define a scope. Scopes are defined with the `ConsistentRandom.scope` method. Within the scope block, calls to `ConsistentRandom` will return the same random values for the same name. Scopes are isolated to the block in which they're defined, meaning random values are consistent within each scoped block but independent across threads or separate invocations.
|
16
28
|
|
17
29
|
```ruby
|
18
30
|
ConsistentRandom.scope do
|
@@ -65,11 +77,11 @@ random = ConsistentRandom.new("foobar")
|
|
65
77
|
random.rand != random.rand # => true
|
66
78
|
```
|
67
79
|
|
68
|
-
|
80
|
+
## Middlewares
|
69
81
|
|
70
|
-
The gem provides built-in middlewares for Rack
|
82
|
+
The gem provides built-in middlewares for Rack, Sidekiq, and ActiveJob. These middlewares allow you to automatically scope web requests and propagate consistent random values from the original request to asynchronous jobs.
|
71
83
|
|
72
|
-
|
84
|
+
### Rack Middleware
|
73
85
|
|
74
86
|
In a Rack application:
|
75
87
|
|
@@ -87,14 +99,35 @@ Or in a Rails application:
|
|
87
99
|
config.middleware.use ConsistentRandom::RackMiddleware
|
88
100
|
```
|
89
101
|
|
90
|
-
|
102
|
+
You can also specify a seed value based on the request. This can be useful if you want to generate random values based on a specific request attribute, such as the current user.
|
103
|
+
|
104
|
+
```ruby
|
105
|
+
Rack::Builder.app do
|
106
|
+
use ConsistentRandom::RackMiddleware, ->(env) { env["warden"].user.id }
|
107
|
+
run MyApp
|
108
|
+
end
|
109
|
+
```
|
110
|
+
|
111
|
+
If the seed block returns `nil`, then a random seed will be generated for the request.
|
91
112
|
|
92
|
-
|
113
|
+
### Sidekiq Middleware
|
114
|
+
|
115
|
+
Add the middlewares to your Sidekiq in an initializer:
|
116
|
+
|
117
|
+
```ruby
|
118
|
+
ConsistentRandom::SidekiqMiddleware.install
|
119
|
+
```
|
120
|
+
|
121
|
+
This will install both the client and server middleware. You can also install them manually if you need more control on the order of the middlewares. You should install the client middleware on both the server and client configurations.
|
93
122
|
|
94
123
|
```ruby
|
95
124
|
Sidekiq.configure_server do |config|
|
96
125
|
config.server_middleware do |chain|
|
97
|
-
chain.
|
126
|
+
chain.prepend ConsistentRandom::SidekiqMiddleware
|
127
|
+
end
|
128
|
+
|
129
|
+
config.client_middleware do |chain|
|
130
|
+
chain.add ConsistentRandom::SidekiqClientMiddleware
|
98
131
|
end
|
99
132
|
end
|
100
133
|
|
@@ -119,6 +152,20 @@ class MyWorker
|
|
119
152
|
end
|
120
153
|
```
|
121
154
|
|
155
|
+
You can still specify a custom seed value in your worker if, for example, you want to ensure that values are consistent based on a user when the job is not enqueued from a Rack request.
|
156
|
+
|
157
|
+
```ruby
|
158
|
+
class MyWorker
|
159
|
+
include Sidekiq::Job
|
160
|
+
|
161
|
+
def perform(user_id)
|
162
|
+
ConsistentRandom.scope(user_id) do
|
163
|
+
...
|
164
|
+
end
|
165
|
+
end
|
166
|
+
end
|
167
|
+
```
|
168
|
+
|
122
169
|
### ActiveJob
|
123
170
|
|
124
171
|
You can use consistent random values in your ActiveJob jobs by including the `ConsistentRandom::ActiveJob` module.
|
@@ -147,6 +194,18 @@ class MyJob < ApplicationJob
|
|
147
194
|
end
|
148
195
|
```
|
149
196
|
|
197
|
+
You can still specify a custom seed value in your worker if, for example, you want to ensure that values are consistent based on a user when the job is not enqueued from a Rack request.
|
198
|
+
|
199
|
+
```ruby
|
200
|
+
class MyJob < ApplicationJob
|
201
|
+
def perform(user_id)
|
202
|
+
ConsistentRandom.scope(user_id) do
|
203
|
+
...
|
204
|
+
end
|
205
|
+
end
|
206
|
+
end
|
207
|
+
```
|
208
|
+
|
150
209
|
## Installation
|
151
210
|
|
152
211
|
Add this line to your application's Gemfile:
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
2.
|
1
|
+
2.1.1
|
@@ -4,12 +4,19 @@ class ConsistentRandom
|
|
4
4
|
# Rack middleware that wraps a request with consistent random scope
|
5
5
|
# so that you can generate consistent random values within a request.
|
6
6
|
class RackMiddleware
|
7
|
-
|
7
|
+
# @param app [Object] Rack application to wrap
|
8
|
+
# @param seed_block [Proc, #call, nil] block to generate seed for the request
|
9
|
+
# If provided, the block will be called with the request env and
|
10
|
+
# the return value will be used as the seed for the request. You can
|
11
|
+
# use this to generate a seed based on the request state..
|
12
|
+
def initialize(app, seed_block = nil)
|
8
13
|
@app = app
|
14
|
+
@seed_block = seed_block
|
9
15
|
end
|
10
16
|
|
11
17
|
def call(env)
|
12
|
-
|
18
|
+
seed = @seed_block.call(env) if @seed_block
|
19
|
+
ConsistentRandom.scope(seed) do
|
13
20
|
@app.call(env)
|
14
21
|
end
|
15
22
|
end
|
@@ -8,6 +8,26 @@ class ConsistentRandom
|
|
8
8
|
include Sidekiq::ServerMiddleware
|
9
9
|
end
|
10
10
|
|
11
|
+
class << self
|
12
|
+
def install
|
13
|
+
Sidekiq.configure_server do |config|
|
14
|
+
config.server_middleware do |chain|
|
15
|
+
chain.prepend ConsistentRandom::SidekiqMiddleware
|
16
|
+
end
|
17
|
+
|
18
|
+
config.client_middleware do |chain|
|
19
|
+
chain.add ConsistentRandom::SidekiqClientMiddleware
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
Sidekiq.configure_client do |config|
|
24
|
+
config.client_middleware do |chain|
|
25
|
+
chain.add ConsistentRandom::SidekiqClientMiddleware
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
11
31
|
def call(job_instance, job_payload, queue)
|
12
32
|
ConsistentRandom.scope(job_payload["consistent_random_seed"]) do
|
13
33
|
yield
|
data/lib/consistent_random.rb
CHANGED
@@ -3,15 +3,15 @@
|
|
3
3
|
require "digest/sha1"
|
4
4
|
require "securerandom"
|
5
5
|
|
6
|
-
require_relative "consistent_random/rack_middleware"
|
7
|
-
require_relative "consistent_random/sidekiq_middleware"
|
8
|
-
require_relative "consistent_random/sidekiq_client_middleware"
|
9
|
-
require_relative "consistent_random/active_job"
|
10
|
-
|
11
6
|
class ConsistentRandom
|
12
7
|
SEED_DIVISOR = (2**64 - 1).to_f
|
13
8
|
private_constant :SEED_DIVISOR
|
14
9
|
|
10
|
+
autoload :RackMiddleware, "consistent_random/rack_middleware"
|
11
|
+
autoload :SidekiqMiddleware, "consistent_random/sidekiq_middleware"
|
12
|
+
autoload :SidekiqClientMiddleware, "consistent_random/sidekiq_client_middleware"
|
13
|
+
autoload :ActiveJob, "consistent_random/active_job"
|
14
|
+
|
15
15
|
class << self
|
16
16
|
# Define a scope where consistent random values will be generated.
|
17
17
|
#
|
@@ -103,7 +103,7 @@ class ConsistentRandom
|
|
103
103
|
# the same random number generator. If called outside of a scope, then it will
|
104
104
|
# always return false.
|
105
105
|
def ==(other)
|
106
|
-
other.is_a?(self.class) && other.seed
|
106
|
+
other.is_a?(self.class) && other.seed == seed
|
107
107
|
end
|
108
108
|
|
109
109
|
# Generate a random number generator for the given name. The generator will always
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: consistent_random
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.
|
4
|
+
version: 2.1.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Brian Durand
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2024-
|
11
|
+
date: 2024-11-20 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|