process_settings 0.16.0 → 0.19.0

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
2
  SHA256:
3
- metadata.gz: fe4e35a75d3c8a06396dbc7094874cf5e2509847f66c442ff5297e9c8011cebd
4
- data.tar.gz: a7b18e595bde05fd56037570a80008bf3f0cc5d679810dce724a63977fec9a02
3
+ metadata.gz: 14973d0d1a4eb5ad4641db115a9eb439740761bbc4ae0bfd20a103a455c9eb82
4
+ data.tar.gz: 4d662530770cd4afba5792ec603c67f86681300d8aef0c4ed8d9b9e0d8975bca
5
5
  SHA512:
6
- metadata.gz: 3f972dcfa9f6e7f988866ac290e71231f0a005842105a284e6a688123e74f9e970ec60749675d0855b47d13d344462169f29cd70b7251b799ae6a6ef4f82b6a6
7
- data.tar.gz: e30ad37d7c7508c70471c75322ffcf98c981fb54bdf0e339e6ab512d95c04a8bcd2dad5917381c0a2fbd3ce468e1f04cc18bc0c7919bc9848be3f8b934155853
6
+ metadata.gz: 010056e43ab73c0a6838732c25fc4f23fcb598056cac740e81d27f5d9765b12740a1db2f587286d716613597393d49e9781150ff7bd186363c22fd0bc8b420c2
7
+ data.tar.gz: 4784757b38d3e80c41ec366ecccc0425069820a712e995927a82fffd02f177e3053cf274886259310d472cc314cdf526b8198531f965b15b24b89b520e14c612
data/README.md CHANGED
@@ -167,6 +167,32 @@ 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
+
183
+ ### Start Watchdog
184
+ When using `ProcessSettings` you can start a watchdog thread using `start_watchdog_thread` on a particular file path. The watchdog will poll once a minute to double-check if any changes have been missed due to a bug in the `listen` gem or the supporting OS drivers like `inotify`.
185
+ You may not start the watchdog thread it has already been started.
186
+ ```ruby
187
+ ProcessSettings.instance.start_watchdog_thread(file_path)
188
+ ```
189
+
190
+ ### Stop Watchdog
191
+ When using `ProcessSettings` you can stop a watchdog thread using `stop_watchdog_thread`. Once stopped you may start a new watchdog thread.
192
+ ```ruby
193
+ ProcessSettings.instance.stop_watchdog_thread
194
+ ```
195
+
170
196
  ### Testing
171
197
  For testing, it is often necessary to set a specific override hash for the process_settings values to use in
172
198
  that use case. The `ProcessSettings::Testing::RSpec::Helpers` and `ProcessSettings::Testing::Minitest::Helpers` modules are provided for this purpose.
@@ -114,7 +114,11 @@ module ProcessSettings
114
114
  # find last value from matching targets
115
115
  if target_and_settings.target.target_key_matches?(full_context)
116
116
  if (value = target_and_settings.settings.json_doc.mine(*path, not_found_value: :not_found)) != :not_found
117
- latest_result = value
117
+ latest_result = if latest_result.is_a?(Hash) && value.is_a?(Hash)
118
+ latest_result.deep_merge(value)
119
+ else
120
+ value
121
+ end
118
122
  end
119
123
  end
120
124
  latest_result
@@ -8,6 +8,7 @@ require 'active_support/deprecation'
8
8
  require 'process_settings/abstract_monitor'
9
9
  require 'process_settings/targeted_settings'
10
10
  require 'process_settings/hash_path'
11
+ require 'process_settings/helpers/watchdog'
11
12
 
12
13
  module ProcessSettings
13
14
  class FileMonitor < AbstractMonitor
@@ -24,10 +25,32 @@ module ProcessSettings
24
25
  start_internal(enable_listen_thread?(environment))
25
26
  end
26
27
 
28
+ def start_watchdog_thread(file_path)
29
+ @watchdog_thread and raise ArgumentError, "watchdog thread already running!"
30
+ @watchdog_thread = Thread.new do
31
+ watchdog = Watchdog.new(file_path)
32
+ loop do
33
+ sleep(1.minute)
34
+ watchdog.check
35
+ rescue => ex
36
+ logger.error("ProcessSettings::Watchdog thread: #{ex.class.name}: #{ex.message}")
37
+ end
38
+ end
39
+ end
40
+
41
+ def stop_watchdog_thread
42
+ @watchdog_thread&.kill
43
+ @watchdog_thread = nil
44
+ end
45
+
27
46
  def start
28
47
  start_internal(enable_listen_thread?)
29
48
  end
30
- deprecate :start, deprecator: ActiveSupport::Deprecation.new('1.0', 'ProcessSettings') # will become private
49
+ deprecate start: :restart_after_fork, deprecator: ActiveSupport::Deprecation.new('1.0', 'ProcessSettings')
50
+
51
+ def restart_after_fork
52
+ start_internal(enable_listen_thread?)
53
+ end
31
54
 
32
55
  def listen_thread_running?
33
56
  !@listener.nil?
@@ -0,0 +1,37 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'active_support/core_ext/numeric/time'
4
+
5
+ module ProcessSettings
6
+ class Watchdog
7
+ class OutOfSync < StandardError; end
8
+
9
+ MAX_MTIME_DIFFERENCE = 2.minutes
10
+
11
+ def initialize(process_settings_file_path)
12
+ @process_settings_file_path = process_settings_file_path or raise ArgumentError, "process_settings_file_path must be passed"
13
+ end
14
+
15
+ def check
16
+ if version_from_memory != version_from_disk && (Time.now - mtime_from_disk) > MAX_MTIME_DIFFERENCE
17
+ raise ProcessSettings::OutOfSync.new("ProcessSettings versions are out of sync!\n Version from Disk: #{version_from_disk}\n Version from Memory: #{version_from_memory}\n mtime of file: #{mtime_from_disk}")
18
+ end
19
+ end
20
+
21
+ private
22
+
23
+ attr_reader :process_settings_file_path
24
+
25
+ def version_from_memory
26
+ ProcessSettings.instance.untargeted_settings.version
27
+ end
28
+
29
+ def version_from_disk
30
+ ProcessSettings::TargetedSettings.from_file(process_settings_file_path, only_meta: true).version
31
+ end
32
+
33
+ def mtime_from_disk
34
+ File.mtime(process_settings_file_path)
35
+ end
36
+ end
37
+ end
@@ -46,7 +46,7 @@ module ProcessSettings
46
46
  def logger=(new_logger)
47
47
  ActiveSupport::Deprecation.warn("ProcessSettings::Monitor.logger is deprecated and will be removed in v1.0.")
48
48
  @logger = new_logger
49
- Listen.logger ||= new_logger
49
+ Listen.logger = new_logger unless Listen.instance_variable_get(:@logger)
50
50
  end
51
51
 
52
52
  deprecate :logger, :logger=, :file_path, :file_path=, deprecator: ActiveSupport::Deprecation.new('1.0', 'ProcessSettings')
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module ProcessSettings
4
- VERSION = '0.16.0'
4
+ VERSION = '0.19.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.16.0
4
+ version: 0.19.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Invoca
@@ -94,6 +94,7 @@ files:
94
94
  - lib/process_settings/file_monitor.rb
95
95
  - lib/process_settings/hash_path.rb
96
96
  - lib/process_settings/hash_with_hash_path.rb
97
+ - lib/process_settings/helpers/watchdog.rb
97
98
  - lib/process_settings/monitor.rb
98
99
  - lib/process_settings/replace_versioned_file.rb
99
100
  - lib/process_settings/settings.rb