network_resiliency 0.0.2 → 0.1.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: d085dba12da295ad4c4bb4d540acb3b865c8d8486b9bdf6d812e74430efcd55f
4
- data.tar.gz: 24d61f1205ecba15f7acbda327d91be3ca0c74dd0955c2fe03338f873435d478
3
+ metadata.gz: 07f28c3158ada0009efdc0d9b68162419d227d088b24b3827a43dc5923ca8081
4
+ data.tar.gz: 645bd61e91ac8b939713376de77cedcd1f79e254a558b0b09cd26ba0280abe68
5
5
  SHA512:
6
- metadata.gz: 91e9bcd5141345e0117be83f1e01951a11f6ffc8b100c1776a0ba3a2ac2bde19642369875ee79d995f8c4f3bbc0742f72c67102295bdecb2e9afd681597f555c
7
- data.tar.gz: df13161c53527c10143d7c11b56ac7cc2a75189eb58b2d698d2f9940dd50a894a3e6dae8680764a6773c68c6dc107faf8613b457c5edeb1dc7c65200fe97e491
6
+ metadata.gz: 47b0bbe65d83b4acad810673904a13d57c898a00193fb48432b690d31932d19e52d397363195917f9e3dd8b1631084bdfd193094e8f570fb914ab490db9fd544
7
+ data.tar.gz: dd8f225e3bcf5d597838e405fa8c80b7228fdc5aacdf326b38c9fdb0eae72eae60bf00e0be1eed970547014b5f820557635cfd6422741e91c0e6e2cc22935bc6
data/CHANGELOG.md CHANGED
@@ -1,3 +1,19 @@
1
+ ### v0.1.0 (2023-09-26)
2
+ - rework faraday adapter
3
+ - faraday
4
+ - adapter scoped enabled
5
+ - scope rspec helper
6
+ - adapter tag
7
+ - enable disable block mode
8
+ - drop ruby 2.7 support
9
+ - resiliency
10
+ - pointer
11
+ - code coverage upgrade
12
+ - requirements
13
+ - http adapter
14
+ - mock http server
15
+ - add ddtrace to dev
16
+
1
17
  ### v0.0.2 (2023-05-09)
2
18
  - rename to Network Resiliency
3
19
  - fix sample variance
data/Gemfile.lock CHANGED
@@ -1,67 +1,90 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- network_resiliency (0.0.2)
5
- faraday
4
+ network_resiliency (0.1.0)
6
5
 
7
6
  GEM
8
7
  remote: https://rubygems.org/
9
8
  specs:
10
9
  byebug (11.1.3)
11
- codecov (0.5.2)
12
- simplecov (>= 0.15, < 0.22)
13
- connection_pool (2.3.0)
14
- diff-lcs (1.4.4)
10
+ ddtrace (1.14.0)
11
+ debase-ruby_core_source (= 3.2.1)
12
+ libdatadog (~> 3.0.0.1.0)
13
+ libddwaf (~> 1.9.0.0.0)
14
+ msgpack
15
+ debase-ruby_core_source (3.2.1)
16
+ diff-lcs (1.5.0)
15
17
  docile (1.4.0)
16
- faraday (2.7.4)
17
- faraday-net_http (>= 2.0, < 3.1)
18
+ dogstatsd-ruby (4.8.3)
19
+ faraday (1.10.3)
20
+ faraday-em_http (~> 1.0)
21
+ faraday-em_synchrony (~> 1.0)
22
+ faraday-excon (~> 1.1)
23
+ faraday-httpclient (~> 1.0)
24
+ faraday-multipart (~> 1.0)
25
+ faraday-net_http (~> 1.0)
26
+ faraday-net_http_persistent (~> 1.0)
27
+ faraday-patron (~> 1.0)
28
+ faraday-rack (~> 1.0)
29
+ faraday-retry (~> 1.0)
18
30
  ruby2_keywords (>= 0.0.4)
19
- faraday-net_http (3.0.2)
31
+ faraday-em_http (1.0.0)
32
+ faraday-em_synchrony (1.0.0)
33
+ faraday-excon (1.1.0)
34
+ faraday-httpclient (1.0.1)
35
+ faraday-multipart (1.0.4)
36
+ multipart-post (~> 2)
37
+ faraday-net_http (1.0.1)
38
+ faraday-net_http_persistent (1.2.0)
39
+ faraday-patron (1.0.0)
20
40
  faraday-rack (1.0.0)
21
- rack (3.0.2)
22
- rack-test (2.0.2)
41
+ faraday-retry (1.0.3)
42
+ ffi (1.15.5)
43
+ libdatadog (3.0.0.1.0)
44
+ libddwaf (1.9.0.0.1)
45
+ ffi (~> 1.0)
46
+ msgpack (1.7.2)
47
+ multipart-post (2.3.0)
48
+ rack (3.0.8)
49
+ rack-test (2.1.0)
23
50
  rack (>= 1.3)
24
- redis (5.0.5)
25
- redis-client (>= 0.9.0)
26
- redis-client (0.11.2)
27
- connection_pool
28
- rspec (3.10.0)
29
- rspec-core (~> 3.10.0)
30
- rspec-expectations (~> 3.10.0)
31
- rspec-mocks (~> 3.10.0)
32
- rspec-core (3.10.1)
33
- rspec-support (~> 3.10.0)
34
- rspec-expectations (3.10.1)
51
+ redis (4.8.1)
52
+ rspec (3.12.0)
53
+ rspec-core (~> 3.12.0)
54
+ rspec-expectations (~> 3.12.0)
55
+ rspec-mocks (~> 3.12.0)
56
+ rspec-core (3.12.2)
57
+ rspec-support (~> 3.12.0)
58
+ rspec-expectations (3.12.3)
35
59
  diff-lcs (>= 1.2.0, < 2.0)
36
- rspec-support (~> 3.10.0)
37
- rspec-mocks (3.10.2)
60
+ rspec-support (~> 3.12.0)
61
+ rspec-mocks (3.12.6)
38
62
  diff-lcs (>= 1.2.0, < 2.0)
39
- rspec-support (~> 3.10.0)
40
- rspec-support (3.10.2)
63
+ rspec-support (~> 3.12.0)
64
+ rspec-support (3.12.1)
41
65
  ruby2_keywords (0.0.5)
42
- simplecov (0.21.2)
66
+ simplecov (0.22.0)
43
67
  docile (~> 1.1)
44
68
  simplecov-html (~> 0.11)
45
69
  simplecov_json_formatter (~> 0.1)
46
70
  simplecov-html (0.12.3)
47
- simplecov_json_formatter (0.1.3)
71
+ simplecov_json_formatter (0.1.4)
48
72
 
49
73
  PLATFORMS
50
- x86_64-darwin-19
51
- x86_64-darwin-20
52
- x86_64-darwin-21
74
+ ruby
53
75
 
54
76
  DEPENDENCIES
55
77
  byebug
56
- codecov
78
+ ddtrace (>= 1)
79
+ dogstatsd-ruby (<= 4.8.3)
80
+ faraday (~> 1)
57
81
  faraday-rack
58
82
  network_resiliency!
59
83
  rack
60
84
  rack-test
61
- redis
62
- redis-client (>= 0.10)
85
+ redis (~> 4)
63
86
  rspec
64
87
  simplecov
65
88
 
66
89
  BUNDLED WITH
67
- 2.2.20
90
+ 2.4.19
data/README.md CHANGED
@@ -1,6 +1,11 @@
1
- ApiAvenger
1
+ NetworkResiliency
2
2
  ======
3
- ...
3
+ ![Gem](https://img.shields.io/gem/dt/network_resiliency?style=plastic)
4
+ [![codecov](https://codecov.io/gh/dpep/network_resiliency_rb/branch/main/graph/badge.svg)](https://codecov.io/gh/dpep/network_resiliency_rb)
5
+
6
+ Making networks more resilient to errors.
7
+
8
+ Resiliency: the ability to recover from adversity or adjust to change.
4
9
 
5
10
 
6
11
  ```ruby
@@ -21,6 +26,10 @@ Yes please :)
21
26
  1. Create a Pull Request
22
27
 
23
28
 
29
+
24
30
  ----
25
- ![Gem](https://img.shields.io/gem/dt/network_resiliency?style=plastic)
26
- [![codecov](https://codecov.io/gh/dpep/network_resiliency_rb/branch/main/graph/badge.svg)](https://codecov.io/gh/dpep/network_resiliency_rb)
31
+ ### Inspired by
32
+
33
+ https://github.com/lostisland/faraday-retry/blob/main/lib/faraday/retry/middleware.rb
34
+
35
+ https://github.com/ankane/the-ultimate-guide-to-ruby-timeouts
@@ -2,58 +2,16 @@ require "faraday"
2
2
 
3
3
  module NetworkResiliency
4
4
  module Adapter
5
- class Faraday < ::Faraday::Middleware
6
- def call(env)
7
- puts "NetworkResiliency called: #{env.url}"
8
- # env.options.timeout = 0.001
9
- # open_timeout
10
-
11
- # url => id
12
- # predict time
13
- # get dynamic timeout
14
-
15
- if NetworkResiliency.enabled?
16
- # temp update timeout
17
- # with_timeout(...) { super }
18
- else
19
- super
5
+ class Faraday < ::Faraday::Adapter::NetHttp
6
+ def build_connection(env)
7
+ super.tap do |conn|
8
+ NetworkResiliency::Adapter::HTTP.patch(conn)
20
9
  end
21
- rescue ::Faraday::Error => e
22
- # note exception for ensure block
23
- ensure
24
- # record time taken
25
-
26
- # reraise if applicable
27
- raise e if e
28
- end
29
-
30
- def normalized_id(env)
31
- env.url
32
- end
33
-
34
- def with_timeout(env, timeout)
35
- old_timeouts = [
36
- env.options.timeout,
37
- env.options.open_timeout,
38
- env.options.read_timeout,
39
- env.options.write_timeout,
40
- ]
41
-
42
- env.options.timeout = [
43
- env.options.timeout,
44
- timeout,
45
- ].compact.min
46
-
47
- # env.options.open_timeout = [ env.options.open_timeout, timeout ].compact.min
48
- # ...
49
- ensure
50
- env.options.timeout = old_timeouts[0]
51
- # ...
52
10
  end
53
11
  end
54
12
  end
55
13
  end
56
14
 
57
- Faraday::Request.register_middleware(
15
+ Faraday::Adapter.register_middleware(
58
16
  network_resiliency: NetworkResiliency::Adapter::Faraday,
59
17
  )
@@ -0,0 +1,44 @@
1
+ require "net/http"
2
+
3
+ module NetworkResiliency
4
+ module Adapter
5
+ module HTTP
6
+ extend self
7
+
8
+ def patch(instance = nil)
9
+ (instance&.singleton_class || Net::HTTP).prepend(Instrumentation)
10
+ end
11
+
12
+ def patched?(instance = nil)
13
+ (instance&.singleton_class || Net::HTTP).ancestors.include?(Instrumentation)
14
+ end
15
+
16
+ module Instrumentation
17
+ def connect
18
+ return super unless NetworkResiliency.enabled?(:http)
19
+
20
+ begin
21
+ ts = -NetworkResiliency.timestamp
22
+
23
+ super
24
+ rescue Net::OpenTimeout => e
25
+ # capture error
26
+ raise
27
+ ensure
28
+ ts += NetworkResiliency.timestamp
29
+
30
+ NetworkResiliency.statsd&.distribution(
31
+ "network_resiliency.connect",
32
+ ts,
33
+ tags: {
34
+ adapter: "http",
35
+ destination: address,
36
+ error: e&.class,
37
+ }.compact,
38
+ )
39
+ end
40
+ end
41
+ end
42
+ end
43
+ end
44
+ end
@@ -59,5 +59,5 @@ module NetworkResiliency
59
59
  end
60
60
  end
61
61
 
62
- # RedisClient.register(RedisAvenger)
63
- # Redis.new(middlewares: [RedisAvenger])
62
+ # RedisClient.register(NetworkResiliency::Adapter::Redis)
63
+ # Redis.new(middlewares: [NetworkResiliency::Adapter::Redis])
@@ -1,3 +1,3 @@
1
1
  module NetworkResiliency
2
- VERSION = "0.0.2"
2
+ VERSION = "0.1.0"
3
3
  end
@@ -1,123 +1,54 @@
1
- require "network_resiliency/stats"
2
1
  require "network_resiliency/version"
3
2
 
4
3
  module NetworkResiliency
5
- extend self
6
-
7
- def enabled?
8
- true
4
+ module Adapter
5
+ autoload :HTTP, "network_resiliency/adapter/http"
6
+ autoload :Faraday, "network_resiliency/adapter/faraday"
7
+ autoload :Redis, "network_resiliency/adapter/redis"
9
8
  end
10
9
 
11
- def sample?
12
- enabled? || rand < sample_rate
13
- end
10
+ extend self
14
11
 
15
- # def mode=(mode)
16
- # unless [ :avg, :x10, :sig1, :sig2, :sig3 ]
17
- # end
12
+ attr_accessor :statsd
18
13
 
19
- def timeout(adapter, key)
20
- stats = self.stats(adapter, key)
14
+ def enabled?(adapter)
15
+ return true if @enabled.nil?
21
16
 
22
- stats.avg * 10 if stats.n >= 100
17
+ @enabled.is_a?(Proc) ? @enabled.call(adapter) : @enabled
23
18
  end
24
19
 
25
- def stats(adapter, key)
26
- store.get(
27
- [
28
- adapter.class.to_s.split("::")[-1],
29
- key,
30
- ].join(":"),
31
- )
32
- end
33
-
34
- def record(adapter, key, milliseconds)
35
- compound_key = [
36
- adapter.class.to_s.split("::")[-1],
37
- key,
38
- ].join(":")
39
-
40
- # normalize timestamp
41
- milliseconds = [ milliseconds.round, 1 ].max
42
-
43
- store.record(compound_key, milliseconds)
44
- end
20
+ def enabled=(enabled)
21
+ unless [ true, false ].include?(enabled) || enabled.is_a?(Proc)
22
+ raise ArgumentError
23
+ end
45
24
 
46
- def timestamp
47
- Process.clock_gettime(Process::CLOCK_MONOTONIC) * 1_000
25
+ @enabled = enabled
48
26
  end
49
27
 
50
- def time
51
- # if block_given?
52
- ts = -timestamp
53
- yield
28
+ def enable!
29
+ original = @enabled
30
+ @enabled = true
54
31
 
55
- ts += timestamp
32
+ yield if block_given?
33
+ ensure
34
+ @enabled = original if block_given?
56
35
  end
57
36
 
58
- def store
59
- @store ||= MemoryStore.new
60
- end
37
+ def disable!
38
+ original = @enabled
39
+ @enabled = false
61
40
 
62
- class Store
63
- def get(key)
64
- raise NotImplemented
65
- end
66
-
67
- def record(key, time)
68
- raise NotImplemented
69
- end
70
-
71
- def flush
72
- raise NotImplemented
73
- end
41
+ yield if block_given?
42
+ ensure
43
+ @enabled = original if block_given?
74
44
  end
75
45
 
76
- class MemoryStore < Store
77
- def initialize(substore = nil)
78
- @substore = substore
79
- @data = {}
80
- end
81
-
82
- def get(key)
83
- @data[key] ||= @substore&.get(key) || Stats.new
84
- end
85
-
86
- def record(key, time)
87
- get(key) << time
88
- @substore&.record(key, time)
89
-
90
- self
91
- end
92
-
93
- def flush
94
- @substore&.flush
95
- end
46
+ def timestamp
47
+ # milliseconds
48
+ Process.clock_gettime(Process::CLOCK_MONOTONIC) * 1_000
96
49
  end
97
50
 
98
- class RedisStore < Store
99
- def initialize(redis)
100
- @redis = redis
101
- end
102
-
103
- def cachekey(key)
104
- [ NetworkResiliency, key ].join(":")
105
- end
51
+ def reset
52
+ @enabled = nil
106
53
  end
107
54
  end
108
-
109
-
110
- require "network_resiliency/adapter/faraday"
111
- require "network_resiliency/adapter/redis"
112
-
113
- # ms granularity, round up, floor(1)
114
- #
115
-
116
- # storage
117
- # get(id) / record(id, time) / flush
118
-
119
- # local storage
120
- # - get(id) / save(id, time)
121
- # remote storage
122
- # - get(id) - sync
123
- # - save(id, time) - buffer and async flush
@@ -11,15 +11,16 @@ Gem::Specification.new do |s|
11
11
  s.summary = package.to_s
12
12
  s.version = package.const_get "VERSION"
13
13
 
14
- s.add_dependency "faraday"
14
+ s.required_ruby_version = ">= 3"
15
15
 
16
16
  s.add_development_dependency "byebug"
17
- s.add_development_dependency "codecov"
17
+ s.add_development_dependency "ddtrace", ">= 1"
18
+ s.add_development_dependency "dogstatsd-ruby", "<= 4.8.3"
19
+ s.add_development_dependency "faraday", "~> 1"
18
20
  s.add_development_dependency "faraday-rack"
19
21
  s.add_development_dependency "rack"
20
22
  s.add_development_dependency "rack-test"
21
- s.add_development_dependency "redis"
22
- s.add_development_dependency "redis-client", ">= 0.10"
23
+ s.add_development_dependency "redis", "~> 4"
23
24
  s.add_development_dependency "rspec"
24
25
  s.add_development_dependency "simplecov"
25
26
  end
metadata CHANGED
@@ -1,23 +1,23 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: network_resiliency
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.2
4
+ version: 0.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Daniel Pepper
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2023-05-09 00:00:00.000000000 Z
11
+ date: 2023-09-27 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
- name: faraday
14
+ name: byebug
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
17
  - - ">="
18
18
  - !ruby/object:Gem::Version
19
19
  version: '0'
20
- type: :runtime
20
+ type: :development
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
@@ -25,49 +25,49 @@ dependencies:
25
25
  - !ruby/object:Gem::Version
26
26
  version: '0'
27
27
  - !ruby/object:Gem::Dependency
28
- name: byebug
28
+ name: ddtrace
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
31
  - - ">="
32
32
  - !ruby/object:Gem::Version
33
- version: '0'
33
+ version: '1'
34
34
  type: :development
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
38
  - - ">="
39
39
  - !ruby/object:Gem::Version
40
- version: '0'
40
+ version: '1'
41
41
  - !ruby/object:Gem::Dependency
42
- name: codecov
42
+ name: dogstatsd-ruby
43
43
  requirement: !ruby/object:Gem::Requirement
44
44
  requirements:
45
- - - ">="
45
+ - - "<="
46
46
  - !ruby/object:Gem::Version
47
- version: '0'
47
+ version: 4.8.3
48
48
  type: :development
49
49
  prerelease: false
50
50
  version_requirements: !ruby/object:Gem::Requirement
51
51
  requirements:
52
- - - ">="
52
+ - - "<="
53
53
  - !ruby/object:Gem::Version
54
- version: '0'
54
+ version: 4.8.3
55
55
  - !ruby/object:Gem::Dependency
56
- name: faraday-rack
56
+ name: faraday
57
57
  requirement: !ruby/object:Gem::Requirement
58
58
  requirements:
59
- - - ">="
59
+ - - "~>"
60
60
  - !ruby/object:Gem::Version
61
- version: '0'
61
+ version: '1'
62
62
  type: :development
63
63
  prerelease: false
64
64
  version_requirements: !ruby/object:Gem::Requirement
65
65
  requirements:
66
- - - ">="
66
+ - - "~>"
67
67
  - !ruby/object:Gem::Version
68
- version: '0'
68
+ version: '1'
69
69
  - !ruby/object:Gem::Dependency
70
- name: rack
70
+ name: faraday-rack
71
71
  requirement: !ruby/object:Gem::Requirement
72
72
  requirements:
73
73
  - - ">="
@@ -81,7 +81,7 @@ dependencies:
81
81
  - !ruby/object:Gem::Version
82
82
  version: '0'
83
83
  - !ruby/object:Gem::Dependency
84
- name: rack-test
84
+ name: rack
85
85
  requirement: !ruby/object:Gem::Requirement
86
86
  requirements:
87
87
  - - ">="
@@ -95,7 +95,7 @@ dependencies:
95
95
  - !ruby/object:Gem::Version
96
96
  version: '0'
97
97
  - !ruby/object:Gem::Dependency
98
- name: redis
98
+ name: rack-test
99
99
  requirement: !ruby/object:Gem::Requirement
100
100
  requirements:
101
101
  - - ">="
@@ -109,19 +109,19 @@ dependencies:
109
109
  - !ruby/object:Gem::Version
110
110
  version: '0'
111
111
  - !ruby/object:Gem::Dependency
112
- name: redis-client
112
+ name: redis
113
113
  requirement: !ruby/object:Gem::Requirement
114
114
  requirements:
115
- - - ">="
115
+ - - "~>"
116
116
  - !ruby/object:Gem::Version
117
- version: '0.10'
117
+ version: '4'
118
118
  type: :development
119
119
  prerelease: false
120
120
  version_requirements: !ruby/object:Gem::Requirement
121
121
  requirements:
122
- - - ">="
122
+ - - "~>"
123
123
  - !ruby/object:Gem::Version
124
- version: '0.10'
124
+ version: '4'
125
125
  - !ruby/object:Gem::Dependency
126
126
  name: rspec
127
127
  requirement: !ruby/object:Gem::Requirement
@@ -163,6 +163,7 @@ files:
163
163
  - README.md
164
164
  - lib/network_resiliency.rb
165
165
  - lib/network_resiliency/adapter/faraday.rb
166
+ - lib/network_resiliency/adapter/http.rb
166
167
  - lib/network_resiliency/adapter/redis.rb
167
168
  - lib/network_resiliency/stats.rb
168
169
  - lib/network_resiliency/version.rb
@@ -179,7 +180,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
179
180
  requirements:
180
181
  - - ">="
181
182
  - !ruby/object:Gem::Version
182
- version: '0'
183
+ version: '3'
183
184
  required_rubygems_version: !ruby/object:Gem::Requirement
184
185
  requirements:
185
186
  - - ">="