idempotent-request 0.1.4 → 0.1.5

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
- 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.