idempo 1.2.1 → 1.2.2
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/.github/workflows/ci.yml +9 -3
- data/CHANGELOG.md +10 -6
- data/README.md +6 -3
- data/idempo.gemspec +1 -2
- data/lib/idempo/version.rb +1 -1
- data/lib/idempo.rb +12 -0
- metadata +13 -13
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 70c151d3823c956aac177dbf39ee4e5f216b9464a739b134c8a47822a01aa765
|
4
|
+
data.tar.gz: 4306e629c9d0f1bd59ad74bc6e61623e441e4713b88bccb8f69c08e8553dc251
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 5e80a42f84a311e633697123f7213af21b0f79d501937d5963e4dd918eb5cabd5d01174d781b0528d4f51923fc9eb038af20afeb164c8cdd51d2cc1983ea1111
|
7
|
+
data.tar.gz: 4d2ee3d361d009aacc23c42ec38323c9b9373d874c9abbd70596882dbd48d6ed4edcf9eb5c32f44e366aa091e178dfcd71c919b45d6bc1b8c17804094b23629f
|
data/.github/workflows/ci.yml
CHANGED
@@ -15,7 +15,7 @@ jobs:
|
|
15
15
|
strategy:
|
16
16
|
matrix:
|
17
17
|
ruby:
|
18
|
-
-
|
18
|
+
- "2.7"
|
19
19
|
steps:
|
20
20
|
- name: Checkout
|
21
21
|
uses: actions/checkout@v4
|
@@ -37,11 +37,16 @@ jobs:
|
|
37
37
|
name: Specs
|
38
38
|
runs-on: ubuntu-22.04
|
39
39
|
if: github.event_name == 'push' || github.event.pull_request.head.repo.full_name != github.repository
|
40
|
+
env:
|
41
|
+
IDEMPO_RACK_VERSION: ${{ matrix.rack }}
|
40
42
|
strategy:
|
41
43
|
matrix:
|
42
44
|
ruby:
|
43
|
-
-
|
44
|
-
-
|
45
|
+
- "2.7"
|
46
|
+
- "3.2"
|
47
|
+
rack:
|
48
|
+
- "2.0"
|
49
|
+
- "3.0"
|
45
50
|
services:
|
46
51
|
mysql:
|
47
52
|
image: mysql:5.7
|
@@ -65,6 +70,7 @@ jobs:
|
|
65
70
|
steps:
|
66
71
|
- name: Checkout
|
67
72
|
uses: actions/checkout@v4
|
73
|
+
|
68
74
|
- name: Setup Ruby
|
69
75
|
uses: ruby/setup-ruby@v1
|
70
76
|
with:
|
data/CHANGELOG.md
CHANGED
@@ -1,13 +1,17 @@
|
|
1
|
-
##
|
1
|
+
## 1.2.2
|
2
|
+
|
3
|
+
- Support `#to_ary` on Rack response bodies on newer Rails/Rack versions
|
4
|
+
|
5
|
+
## 1.2.1
|
2
6
|
|
3
7
|
- Use autoloading for internal modules. A user using Redis does not have to load the ActiveRecord storage backend, for example
|
4
8
|
- Ensure that the original Rack response body receives a `close` when reading out for caching
|
5
9
|
|
6
|
-
##
|
10
|
+
## 1.2.0
|
7
11
|
|
8
12
|
- Use memory locking in addition to DB locking in `ActiveRecordBackend`
|
9
13
|
|
10
|
-
##
|
14
|
+
## 1.1.0
|
11
15
|
|
12
16
|
- Use modern ActiveRecord migration options for better Rails 7.x compatibility
|
13
17
|
- Ensure Github actions CI can run and uses Postgres appropriately
|
@@ -15,16 +19,16 @@
|
|
15
19
|
- Implement `#prune!` on storage backends
|
16
20
|
- Reformat all code using [standard](https://github.com/standardrb/standard) instead of wetransfer_style as it is both more relaxed and more modern
|
17
21
|
|
18
|
-
##
|
22
|
+
## 1.0.0
|
19
23
|
|
20
24
|
- Release 1.0 as the API can be considered stable and the gem has been in production for years
|
21
25
|
|
22
|
-
##
|
26
|
+
## 0.2.0
|
23
27
|
|
24
28
|
- Allow setting the global default TTL for the cached responses
|
25
29
|
- Allow customisation of the request key computation (so that the client can decide whether to include/exclude `Authorization` and the like)
|
26
30
|
- Extract the error response generating apps into separate modules, to make them easier to override
|
27
31
|
|
28
|
-
##
|
32
|
+
## 0.1.0
|
29
33
|
|
30
34
|
- Initial release
|
data/README.md
CHANGED
@@ -10,7 +10,8 @@ instead of calling your application.
|
|
10
10
|
Idempo supports a number of backends, we recommend using Redis if you have multiple application servers / dynos and MemoryBackend if you are only using one single Puma worker. To initialize with Redis as backend pass the `backend:` parameter when adding the middleware:
|
11
11
|
|
12
12
|
```ruby
|
13
|
-
|
13
|
+
be = Idempo::RedisBackend.new(Rails.application.config.redis_connection_pool)
|
14
|
+
use Idempo, backend: be
|
14
15
|
```
|
15
16
|
|
16
17
|
and to initialize with a memory store as backend:
|
@@ -65,7 +66,8 @@ end
|
|
65
66
|
Then configure Idempo to use the backend (in your `application.rb`):
|
66
67
|
|
67
68
|
```ruby
|
68
|
-
|
69
|
+
be = Idempo::ActiveRecordBackend.new
|
70
|
+
config.middleware.insert Idempo, backend: be
|
69
71
|
```
|
70
72
|
|
71
73
|
In your regular tasks (cron or Rake) you will want to add a call to delete old Idempo responses (there is an index on `expire_at`):
|
@@ -87,7 +89,8 @@ use Idempo, backend: Idempo::RedisBackend.new
|
|
87
89
|
If you have a configured Redis connection pool (and you should) - pass it to the initializer:
|
88
90
|
|
89
91
|
```ruby
|
90
|
-
|
92
|
+
be = Idempo::RedisBackend.new(config.redis_connection_pool)
|
93
|
+
config.middleware.insert Idempo, backend: be
|
91
94
|
```
|
92
95
|
|
93
96
|
All data stored in Redis will have TTLs and will expire automatically. Redis scripts ensure that updates to the stored idempotent responses and locking happen atomically.
|
data/idempo.gemspec
CHANGED
@@ -35,11 +35,10 @@ Gem::Specification.new do |spec|
|
|
35
35
|
spec.executables = spec.files.grep(%r{\Aexe/}) { |f| File.basename(f) }
|
36
36
|
spec.require_paths = ["lib"]
|
37
37
|
|
38
|
-
# Uncomment to register a new dependency of your gem
|
39
|
-
spec.add_dependency "rack"
|
40
38
|
spec.add_dependency "msgpack"
|
41
39
|
spec.add_dependency "measurometer", "~> 1.3"
|
42
40
|
|
41
|
+
spec.add_development_dependency "rack", "~> 3"
|
43
42
|
spec.add_development_dependency "rake", "~> 13.0"
|
44
43
|
spec.add_development_dependency "rspec", "~> 3.0"
|
45
44
|
spec.add_development_dependency "redis", "~> 4"
|
data/lib/idempo/version.rb
CHANGED
data/lib/idempo.rb
CHANGED
@@ -7,6 +7,7 @@ require "measurometer"
|
|
7
7
|
require "msgpack"
|
8
8
|
require "zlib"
|
9
9
|
require "set"
|
10
|
+
require "rack"
|
10
11
|
|
11
12
|
require "idempo/version"
|
12
13
|
|
@@ -57,6 +58,12 @@ class Idempo
|
|
57
58
|
status, headers, body = @app.call(env)
|
58
59
|
|
59
60
|
expires_in_seconds = (headers.delete("X-Idempo-Persist-For-Seconds") || @persist_for_seconds).to_i
|
61
|
+
|
62
|
+
# In some cases `body` could respond to to_ary. In this case, we don't need to call .close on body afterwards.
|
63
|
+
#
|
64
|
+
# @see https://github.com/rack/rack/blob/main/SPEC.rdoc#the-body-
|
65
|
+
body = body.to_ary if rack_v3? && body.respond_to?(:to_ary)
|
66
|
+
|
60
67
|
if response_may_be_persisted?(status, headers, body)
|
61
68
|
# Body is replaced with a cached version since a Rack response body is not rewindable
|
62
69
|
marshaled_response, body = serialize_response(status, headers, body)
|
@@ -76,6 +83,10 @@ class Idempo
|
|
76
83
|
|
77
84
|
private
|
78
85
|
|
86
|
+
def rack_v3?
|
87
|
+
Gem::Version.new(Rack.release) >= Gem::Version.new("3.0")
|
88
|
+
end
|
89
|
+
|
79
90
|
def from_persisted_response(marshaled_response)
|
80
91
|
if marshaled_response[-2..] != ":1"
|
81
92
|
raise Error, "Unknown serialization of the marshaled response"
|
@@ -104,6 +115,7 @@ class Idempo
|
|
104
115
|
# does not
|
105
116
|
[deflated_message_packed_str, body_chunks]
|
106
117
|
ensure
|
118
|
+
# This will not be applied to response bodies of Array type.
|
107
119
|
rack_response_body.close if rack_response_body.respond_to?(:close)
|
108
120
|
end
|
109
121
|
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: idempo
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.2.
|
4
|
+
version: 1.2.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Julik Tarkhanov
|
@@ -9,10 +9,10 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: exe
|
11
11
|
cert_chain: []
|
12
|
-
date: 2024-
|
12
|
+
date: 2024-09-20 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
|
-
name:
|
15
|
+
name: msgpack
|
16
16
|
requirement: !ruby/object:Gem::Requirement
|
17
17
|
requirements:
|
18
18
|
- - ">="
|
@@ -26,33 +26,33 @@ dependencies:
|
|
26
26
|
- !ruby/object:Gem::Version
|
27
27
|
version: '0'
|
28
28
|
- !ruby/object:Gem::Dependency
|
29
|
-
name:
|
29
|
+
name: measurometer
|
30
30
|
requirement: !ruby/object:Gem::Requirement
|
31
31
|
requirements:
|
32
|
-
- - "
|
32
|
+
- - "~>"
|
33
33
|
- !ruby/object:Gem::Version
|
34
|
-
version: '
|
34
|
+
version: '1.3'
|
35
35
|
type: :runtime
|
36
36
|
prerelease: false
|
37
37
|
version_requirements: !ruby/object:Gem::Requirement
|
38
38
|
requirements:
|
39
|
-
- - "
|
39
|
+
- - "~>"
|
40
40
|
- !ruby/object:Gem::Version
|
41
|
-
version: '
|
41
|
+
version: '1.3'
|
42
42
|
- !ruby/object:Gem::Dependency
|
43
|
-
name:
|
43
|
+
name: rack
|
44
44
|
requirement: !ruby/object:Gem::Requirement
|
45
45
|
requirements:
|
46
46
|
- - "~>"
|
47
47
|
- !ruby/object:Gem::Version
|
48
|
-
version: '
|
49
|
-
type: :
|
48
|
+
version: '3'
|
49
|
+
type: :development
|
50
50
|
prerelease: false
|
51
51
|
version_requirements: !ruby/object:Gem::Requirement
|
52
52
|
requirements:
|
53
53
|
- - "~>"
|
54
54
|
- !ruby/object:Gem::Version
|
55
|
-
version: '
|
55
|
+
version: '3'
|
56
56
|
- !ruby/object:Gem::Dependency
|
57
57
|
name: rake
|
58
58
|
requirement: !ruby/object:Gem::Requirement
|
@@ -220,7 +220,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
220
220
|
- !ruby/object:Gem::Version
|
221
221
|
version: '0'
|
222
222
|
requirements: []
|
223
|
-
rubygems_version: 3.
|
223
|
+
rubygems_version: 3.3.7
|
224
224
|
signing_key:
|
225
225
|
specification_version: 4
|
226
226
|
summary: Idempotency keys for all.
|