idempotent-request 0.1.4 → 0.1.5

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA256:
3
- metadata.gz: 5cebd804243368dfc14a6199bd3d51f40ebaa149cf697e1793a63f6559f2de23
4
- data.tar.gz: 0a9082b74528e9fb15a5fe8981755d004cc325d9a8fa9373acd94352b62335a6
2
+ SHA1:
3
+ metadata.gz: 1408d4cc1f8842db0668e7a857a9d0dc461f0d82
4
+ data.tar.gz: f26a1f4dd85c156717b08bd308df2dcfc1c07706
5
5
  SHA512:
6
- metadata.gz: f5917e4b4f23d74fa2bfcc4b5a2faef9c140a3b77f8b69c63b8d0cac10dab638bbe3b04d842b0a6a8ec54350251717f72a41004078d30d3c53bf7f229def6188
7
- data.tar.gz: 9bb5f2d94fc04a58fcd6118312622eaa7211c189461a4dd28491b0b433b8a90b22a7fcfa9c21a499239e76cf59cea6f8aab4a05198fd2cc808c8d7b441d4e21d
6
+ metadata.gz: 37d1cb66a774f725ebceb176ec8ac013f8699b87983a8dc64d78beb32a8864fb9dcf93857a6e463f45d75f885c0bf6d4718e54d07dc5403c60e0566333473b52
7
+ data.tar.gz: 8289a677da35316332fe57eb6167e412aaff6078d1aa4ed2a6813b715bda991c0e41c311f2b890ce8f5e68840959fb23b9fed14ec8f6e8d602fee513bd4e1d5c
@@ -1,5 +1,9 @@
1
1
  # Idempotent Request Changelog #
2
2
 
3
+ ## v0.1.4 ##
4
+
5
+ * Fix an issue, when http response from backend != 200..226 caused lock to be taken
6
+
3
7
  ## v0.1.3 ##
4
8
 
5
9
  * Fix an issue, when concurrent requests sent to an endpoint won't be protected by idempotency until the 1st request is finished
@@ -27,5 +27,5 @@ Gem::Specification.new do |spec|
27
27
  spec.add_development_dependency 'rake', '~> 10.0'
28
28
  spec.add_development_dependency 'rspec', '~> 3.0'
29
29
  spec.add_development_dependency 'fakeredis', '~> 0.6'
30
- spec.add_development_dependency 'pry', '~> 0.11'
30
+ spec.add_development_dependency 'byebug', '~> 10.0'
31
31
  end
@@ -4,6 +4,7 @@ module IdempotentRequest
4
4
  @app = app
5
5
  @config = config
6
6
  @policy = config.fetch(:policy)
7
+ @notifier = ActiveSupport::Notifications if defined?(ActiveSupport::Notifications)
7
8
  end
8
9
 
9
10
  def call(env)
@@ -13,10 +14,12 @@ module IdempotentRequest
13
14
 
14
15
  def process(env)
15
16
  set_request(env)
17
+ request.env['idempotent.request'] = {}
16
18
  return app.call(request.env) unless process?
17
- read_idempotent_request ||
18
- write_idempotent_request ||
19
- concurrent_request_response
19
+ request.env['idempotent.request']['key'] = request.key
20
+ response = read_idempotent_request || write_idempotent_request || concurrent_request_response
21
+ instrument(request)
22
+ response
20
23
  end
21
24
 
22
25
  private
@@ -26,19 +29,30 @@ module IdempotentRequest
26
29
  end
27
30
 
28
31
  def read_idempotent_request
29
- storage.read
32
+ request.env['idempotent.request']['read'] = storage.read
30
33
  end
31
34
 
32
35
  def write_idempotent_request
33
36
  return unless storage.lock
34
- storage.write(*app.call(request.env))
37
+ begin
38
+ result = app.call(request.env)
39
+ request.env['idempotent.request']['write'] = result
40
+ storage.write(*result)
41
+ ensure
42
+ request.env['idempotent.request']['unlocked'] = storage.unlock
43
+ result
44
+ end
35
45
  end
36
46
 
37
47
  def concurrent_request_response
38
- [429, {}, []]
48
+ status = 429
49
+ headers = { 'Content-Type' => 'application/json' }
50
+ body = [ Oj.dump('error' => 'Concurrent requests detected') ]
51
+ request.env['idempotent.request']['concurrent_request_response'] = true
52
+ Rack::Response.new(body, status, headers).finish
39
53
  end
40
54
 
41
- attr_reader :app, :env, :config, :request, :policy
55
+ attr_reader :app, :env, :config, :request, :policy, :notifier
42
56
 
43
57
  def process?
44
58
  !request.key.to_s.empty? && should_be_idempotent?
@@ -49,6 +63,10 @@ module IdempotentRequest
49
63
  policy.new(request).should?
50
64
  end
51
65
 
66
+ def instrument(request)
67
+ notifier.instrument('idempotent.request', request: request) if notifier
68
+ end
69
+
52
70
  def set_request(env)
53
71
  @env = env
54
72
  @request ||= Request.new(env, config)
@@ -9,7 +9,7 @@ module IdempotentRequest
9
9
  end
10
10
 
11
11
  def lock(key)
12
- setnx_with_expiration(lock_key(key), true)
12
+ setnx_with_expiration(lock_key(key), Time.now.to_f)
13
13
  end
14
14
 
15
15
  def unlock(key)
@@ -22,10 +22,9 @@ module IdempotentRequest
22
22
  private
23
23
 
24
24
  def header_name
25
- key = @header_name
26
- .to_s
27
- .upcase
28
- .gsub('-', '_')
25
+ key = @header_name.to_s
26
+ .upcase
27
+ .tr('-', '_')
29
28
 
30
29
  key.start_with?('HTTP_') ? key : "HTTP_#{key}"
31
30
  end
@@ -30,8 +30,6 @@ module IdempotentRequest
30
30
 
31
31
  if (200..226).cover?(status)
32
32
  storage.write(key, payload(status, headers, response))
33
- else
34
- unlock
35
33
  end
36
34
 
37
35
  data
@@ -46,11 +44,9 @@ module IdempotentRequest
46
44
  end
47
45
 
48
46
  def payload(status, headers, response)
49
- Oj.dump({
50
- status: status,
51
- headers: headers.to_h,
52
- response: Array(response)
53
- })
47
+ Oj.dump(status: status,
48
+ headers: headers.to_h,
49
+ response: Array(response))
54
50
  end
55
51
 
56
52
  def run_callback(action, args)
@@ -1,3 +1,3 @@
1
1
  module IdempotentRequest
2
- VERSION = "0.1.4"
2
+ VERSION = "0.1.5"
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: idempotent-request
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.4
4
+ version: 0.1.5
5
5
  platform: ruby
6
6
  authors:
7
7
  - Dmytro Zakharov
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2018-07-16 00:00:00.000000000 Z
11
+ date: 2018-12-13 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rack
@@ -95,19 +95,19 @@ dependencies:
95
95
  - !ruby/object:Gem::Version
96
96
  version: '0.6'
97
97
  - !ruby/object:Gem::Dependency
98
- name: pry
98
+ name: byebug
99
99
  requirement: !ruby/object:Gem::Requirement
100
100
  requirements:
101
101
  - - "~>"
102
102
  - !ruby/object:Gem::Version
103
- version: '0.11'
103
+ version: '10.0'
104
104
  type: :development
105
105
  prerelease: false
106
106
  version_requirements: !ruby/object:Gem::Requirement
107
107
  requirements:
108
108
  - - "~>"
109
109
  - !ruby/object:Gem::Version
110
- version: '0.11'
110
+ version: '10.0'
111
111
  description:
112
112
  email:
113
113
  - dmytro@qonto.eu
@@ -153,7 +153,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
153
153
  version: '0'
154
154
  requirements: []
155
155
  rubyforge_project:
156
- rubygems_version: 2.7.7
156
+ rubygems_version: 2.6.14
157
157
  signing_key:
158
158
  specification_version: 4
159
159
  summary: Rack middleware ensuring at most once requests for mutating endpoints.