process_settings 0.14.0.pre.1 → 0.17.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: 0f741a9ba0e6370251e742c613fe5dba63b4c53c7dfdec8c352d00f9d2938489
4
- data.tar.gz: 69b58c50ff369b61d95814cba575fad95d8eb3404443acfb2f5d4154aea392c4
3
+ metadata.gz: 93741a97801bc4783109ff2423f1d1254f764ccad969f8810e242cb32a48ca18
4
+ data.tar.gz: 8e8a865c9f03fa41dc9dd61b5aaa2d59ef86fb66753ca891898942677c9c518e
5
5
  SHA512:
6
- metadata.gz: d00a43c0beffc30ab1af86edebc98adb7dc99dcc21d334dc7ba13cb146b5595e04bb905c6ce346a057ea29f2483fa729e52cdaaacb45eb743f0740fb062fdcf9
7
- data.tar.gz: 97ebec348ff8d4220668b55148cb26aa5c3934317e91d114ecbeb5e2e2c7cc081bfa695595b09ee8b9ac984b1c58955346697eda2ef78b36e6ea7bab1a8e6491
6
+ metadata.gz: f42cb27c7d884a6be0e4543fe148f2e7cc68d2f8e41883789a5ee5a32db9ee4cec5de349f0f576dcb551f07f60e1b9d749a8d4b122ba43aa7346c4cb13f91014
7
+ data.tar.gz: 981330f869266006284477f9146f6686724d0240745ec4112b1b62ba090e4d28f5a211f3a515a3dba1a70f538e87a8191c6d81958c71f628711879031e8e1d11
data/README.md CHANGED
@@ -167,6 +167,19 @@ This will be applied in any process that has (`service_name == "frontend"` OR `s
167
167
  ### Precedence
168
168
  The settings YAML files are always combined in alphabetical order by file path. Later settings take precedence over the earlier ones.
169
169
 
170
+ ### Forked Processes
171
+ When using `ProcessSettings` within an environment that is forking threads (like `unicorn` web servers), you can restart the `FileMonitor`
172
+ after the fork with `restart_after_fork`.
173
+ ```ruby
174
+ # unicorn.rb
175
+
176
+ preload_app true
177
+
178
+ after_fork do
179
+ ProcessSettings.instance.restart_after_fork
180
+ end
181
+ ```
182
+
170
183
  ### Testing
171
184
  For testing, it is often necessary to set a specific override hash for the process_settings values to use in
172
185
  that use case. The `ProcessSettings::Testing::RSpec::Helpers` and `ProcessSettings::Testing::Minitest::Helpers` modules are provided for this purpose.
@@ -181,7 +194,7 @@ require 'process_settings/testing/helpers'
181
194
  RSpec.configure do |config|
182
195
  # ...
183
196
 
184
- include ProcessSettings::Testing::RSpec::Helpers
197
+ config.include ProcessSettings::Testing::RSpec::Helpers
185
198
 
186
199
  # Note: the include above will automatically register a global after block that will reset process_settings to their initial values.
187
200
  # ...
@@ -92,6 +92,26 @@ def warn_if_old_libyaml_version
92
92
  end
93
93
  end
94
94
 
95
+ def settings_files_match?(filename_1, filename_2)
96
+ filename_1 && filename_2 &&
97
+ File.exist?(filename_1) && File.exist?(filename_2) &&
98
+ diff_process_settings(filename_1, filename_2)
99
+ end
100
+
101
+ def diff_process_settings(filename_1, filename_2)
102
+ system(<<~EOS)
103
+ bundle exec diff_process_settings --silent "#{filename_1}" "#{filename_2}"
104
+ EOS
105
+ status_code = $?.exitstatus
106
+ case status_code
107
+ when 0
108
+ true
109
+ when 1
110
+ false
111
+ else
112
+ raise "diff_process_settings failed with code #{status_code}"
113
+ end
114
+ end
95
115
 
96
116
  #
97
117
  # main
@@ -115,14 +135,17 @@ tmp_output_filename = "#{output_filename}.tmp"
115
135
  system("rm -f #{tmp_output_filename}")
116
136
  File.write(tmp_output_filename, yaml_with_warning_comment)
117
137
 
118
- system(<<~EOS)
119
- if bundle exec diff_process_settings --silent #{tmp_output_filename} #{output_filename} ; then
120
- #{"echo #{options.root_folder}: unchanged;" if options.verbose}
121
- rm -f #{tmp_output_filename};
138
+ if settings_files_match?(options.initial_filename, tmp_output_filename)
139
+ if settings_files_match?(output_filename, tmp_output_filename)
140
+ puts "#{options.root_folder}: unchanged" if options.verbose
141
+ FileUtils.rm_f(tmp_output_filename)
122
142
  else
123
- #{"echo #{options.root_folder}: UPDATING;" if options.verbose}
124
- mv #{tmp_output_filename} #{output_filename};
125
- fi
126
- EOS
143
+ puts "#{options.root_folder}: UPDATING (changed now)" if options.verbose
144
+ FileUtils.mv(tmp_output_filename, output_filename)
145
+ end
146
+ else
147
+ puts "#{options.root_folder}: UPDATING (unchanged now, but changed from initial)" if options.verbose
148
+ FileUtils.mv(tmp_output_filename, output_filename)
149
+ end
127
150
 
128
151
  exit(0)
@@ -34,10 +34,7 @@ input_files =
34
34
  if path == '-'
35
35
  ''
36
36
  else
37
- unless File.exists?(path)
38
- warn "#{path} not found--must be a path to combined_process_settings.yml"
39
- exit 1
40
- end
37
+ File.exist?(path) or path = '/dev/null'
41
38
  "< #{path}"
42
39
  end
43
40
  end
@@ -11,14 +11,16 @@ module ProcessSettings
11
11
  OnChangeDeprecation = ActiveSupport::Deprecation.new('1.0', 'ProcessSettings::Monitor')
12
12
 
13
13
  class AbstractMonitor
14
+
14
15
  attr_reader :min_polling_seconds, :logger
15
- attr_reader :static_context, :statically_targeted_settings
16
+ attr_reader :static_context, :statically_targeted_settings, :full_context_cache
16
17
 
17
18
  def initialize(logger:)
18
19
  @logger = logger or raise ArgumentError, "logger must be not be nil"
19
20
  @on_change_callbacks = []
20
21
  @when_updated_blocks = Set.new
21
22
  @static_context = {}
23
+ @full_context_cache = {}
22
24
  end
23
25
 
24
26
  # This is the main entry point for looking up settings on the Monitor instance.
@@ -94,10 +96,20 @@ module ProcessSettings
94
96
  def targeted_value(*path, dynamic_context:, required: true)
95
97
  # Merging the static context in is necessary to make sure that the static context isn't shifting
96
98
  # this can be rather costly to do every time if the dynamic context is not changing
97
- # TODO: Warn in the case where dynamic context was attempting to change a static value
98
- # TODO: Cache the last used dynamic context as a potential optimization to avoid unnecessary deep merges
99
- # TECH-4402 was created to address these todos
100
- full_context = dynamic_context.deep_merge(static_context)
99
+
100
+ # Warn in the case where dynamic context was attempting to change a static value
101
+ changes = dynamic_context.each_with_object({}) do |(key, dynamic_value), result|
102
+ if static_context.has_key?(key)
103
+ static_value = static_context[key]
104
+ if static_value != dynamic_value
105
+ result[key] = [static_value, dynamic_value]
106
+ end
107
+ end
108
+ end
109
+
110
+ changes.empty? or warn("WARNING: static context overwritten by dynamic!\n#{changes.inspect}")
111
+
112
+ full_context = full_context_from_cache(dynamic_context)
101
113
  result = statically_targeted_settings.reduce(:not_found) do |latest_result, target_and_settings|
102
114
  # find last value from matching targets
103
115
  if target_and_settings.target.target_key_matches?(full_context)
@@ -119,6 +131,18 @@ module ProcessSettings
119
131
  end
120
132
  end
121
133
 
134
+ def full_context_from_cache(dynamic_context)
135
+ if (full_context = full_context_cache[dynamic_context])
136
+ full_context
137
+ else
138
+ dynamic_context.deep_merge(static_context).tap do |full_context|
139
+ if full_context_cache.size <= 1000
140
+ full_context_cache[dynamic_context] = full_context
141
+ end
142
+ end
143
+ end
144
+ end
145
+
122
146
  private
123
147
 
124
148
  class << self
@@ -27,7 +27,11 @@ module ProcessSettings
27
27
  def start
28
28
  start_internal(enable_listen_thread?)
29
29
  end
30
- deprecate :start, deprecator: ActiveSupport::Deprecation.new('1.0', 'ProcessSettings') # will become private
30
+ deprecate start: :restart_after_fork, deprecator: ActiveSupport::Deprecation.new('1.0', 'ProcessSettings')
31
+
32
+ def restart_after_fork
33
+ start_internal(enable_listen_thread?)
34
+ end
31
35
 
32
36
  def listen_thread_running?
33
37
  !@listener.nil?
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module ProcessSettings
4
- VERSION = '0.14.0.pre.1'
4
+ VERSION = '0.17.0'
5
5
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: process_settings
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.14.0.pre.1
4
+ version: 0.17.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Invoca
@@ -122,9 +122,9 @@ required_ruby_version: !ruby/object:Gem::Requirement
122
122
  version: '0'
123
123
  required_rubygems_version: !ruby/object:Gem::Requirement
124
124
  requirements:
125
- - - ">"
125
+ - - ">="
126
126
  - !ruby/object:Gem::Version
127
- version: 1.3.1
127
+ version: '0'
128
128
  requirements: []
129
129
  rubygems_version: 3.0.3
130
130
  signing_key: