Class: AemLookout::Watcher
- Inherits:
-
Object
- Object
- AemLookout::Watcher
- Defined in:
- lib/aem_lookout/watcher.rb
Instance Attribute Summary collapse
-
#config ⇒ Object
Returns the value of attribute config.
-
#log ⇒ Object
Returns the value of attribute log.
-
#repo_path ⇒ Object
Returns the value of attribute repo_path.
Class Method Summary collapse
Instance Method Summary collapse
-
#command_configs ⇒ Object
Something like this [=> “java-core/src/main/java”, “pwd” => “java-core”, “command” => “mvn install -P author-localhost”].
-
#create_threaded_fsevent(watch_path, options, &action_block) ⇒ Object
Watch a given path with speified options and call action_block when a non-ignored path is modified.
-
#discover_jcr_path_from_file_in_vault_package(filesystem_path) ⇒ Object
Find the root of the package to determine the path used for the filter.
- #handle_sling_initial_content_change(paths, filesystem_path, jcr_path) ⇒ Object
- #hostnames ⇒ Object
-
#ignored?(file) ⇒ Boolean
Return true if file should not trigger a sync.
-
#initialize(repo_path, config, log = nil) ⇒ Watcher
constructor
A new instance of Watcher.
- #jcr_root_paths ⇒ Object
- #run ⇒ Object
- #sling_initial_content_paths ⇒ Object
- #sync_vault_package_paths(paths) ⇒ Object
-
#track_job_on_list(job, running_jobs) ⇒ Object
Adds to running job list and removes from list when thread completes.
-
#validate_command_config!(command_config) ⇒ Object
Ensures required keys are present.
- #validate_sling_initial_content_path!(path) ⇒ Object
- #wait_for(threads) ⇒ Object
- #watch_command_config(command_config) ⇒ Object
- #watch_sling_initial_content(path) ⇒ Object
- #watch_vault_package(jcr_root) ⇒ Object
Constructor Details
#initialize(repo_path, config, log = nil) ⇒ Watcher
Returns a new instance of Watcher.
11 12 13 14 15 |
# File 'lib/aem_lookout/watcher.rb', line 11 def initialize(repo_path, config, log = nil) @repo_path = repo_path @config = config @log = log || Logger.new(STDOUT) end |
Instance Attribute Details
#config ⇒ Object
Returns the value of attribute config.
9 10 11 |
# File 'lib/aem_lookout/watcher.rb', line 9 def config @config end |
#log ⇒ Object
Returns the value of attribute log.
9 10 11 |
# File 'lib/aem_lookout/watcher.rb', line 9 def log @log end |
#repo_path ⇒ Object
Returns the value of attribute repo_path.
9 10 11 |
# File 'lib/aem_lookout/watcher.rb', line 9 def repo_path @repo_path end |
Class Method Details
.run(repo_path, config) ⇒ Object
5 6 7 |
# File 'lib/aem_lookout/watcher.rb', line 5 def self.run(repo_path, config) self.new(repo_path, config).run end |
Instance Method Details
#command_configs ⇒ Object
Something like this [=> “java-core/src/main/java”, “pwd” => “java-core”, “command” => “mvn install -P author-localhost”]
181 182 183 184 185 186 |
# File 'lib/aem_lookout/watcher.rb', line 181 def command_configs config.fetch("commands", []).map do |command_config| validate_command_config!(command_config) command_config end end |
#create_threaded_fsevent(watch_path, options, &action_block) ⇒ Object
Watch a given path with speified options and call action_block when a non-ignored path is modified. This also ensures that only one action_block is running at a time, killing any other running blocks before starting a new one.
56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 |
# File 'lib/aem_lookout/watcher.rb', line 56 def create_threaded_fsevent(watch_path, , &action_block) fsevent = FSEvent.new running_jobs = Set.new fsevent.watch watch_path, do |paths| paths.delete_if {|path| ignored?(path) } log.warn "Detected change inside: #{paths.inspect}" unless paths.empty? if running_jobs.length > 0 log.warn "A job is currently running for this watcher, killing..." running_jobs.each {|thread| thread.kill } else log.warn "Phew, no running jobs: #{running_jobs}" end job = Thread.new do action_block.call(paths) Thread.exit end track_job_on_list(job, running_jobs) end fsevent end |
#discover_jcr_path_from_file_in_vault_package(filesystem_path) ⇒ Object
Find the root of the package to determine the path used for the filter
215 216 217 218 219 220 221 222 223 |
# File 'lib/aem_lookout/watcher.rb', line 215 def discover_jcr_path_from_file_in_vault_package(filesystem_path) possible_jcr_root = Pathname(filesystem_path).parent while !possible_jcr_root.root? break if possible_jcr_root.basename.to_s == "jcr_root" possible_jcr_root = possible_jcr_root.parent end filesystem_path.gsub(/^#{possible_jcr_root.to_s}/, "") end |
#handle_sling_initial_content_change(paths, filesystem_path, jcr_path) ⇒ Object
134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 |
# File 'lib/aem_lookout/watcher.rb', line 134 def handle_sling_initial_content_change(paths, filesystem_path, jcr_path) paths.each do |path| if !File.exist?(path) log.info "#{path} no longer exists, syncing parent instead" path = File.dirname(path) end relative_jcr_path = path.gsub(/^.+#{filesystem_path}\//, "") AemLookout::Sync.new( hostnames: hostnames, filesystem: path, jcr: (Pathname(jcr_path) + relative_jcr_path).to_s, log: log, sling_initial_content: true ).run end end |
#hostnames ⇒ Object
202 203 204 |
# File 'lib/aem_lookout/watcher.rb', line 202 def hostnames config.fetch("instances") end |
#ignored?(file) ⇒ Boolean
Return true if file should not trigger a sync
207 208 209 210 211 212 |
# File 'lib/aem_lookout/watcher.rb', line 207 def ignored?(file) return true if File.extname(file) == ".tmp" return true if file.match(/___$/) return true if File.basename(file) == ".DS_Store" return false end |
#jcr_root_paths ⇒ Object
169 170 171 |
# File 'lib/aem_lookout/watcher.rb', line 169 def jcr_root_paths config.fetch("jcrRootPaths", []).map {|jcr_root_path| Pathname(repo_path) + jcr_root_path }.map(&:to_s) end |
#run ⇒ Object
17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 |
# File 'lib/aem_lookout/watcher.rb', line 17 def run threads = jcr_root_paths.map do |jcr_root_paths| Thread.new { watch_vault_package(jcr_root_paths) } end threads += sling_initial_content_paths.map do |sling_initial_content_path| Thread.new { watch_sling_initial_content(sling_initial_content_path) } end threads += command_configs.map do |command_config| Thread.new { watch_command_config(command_config) } end wait_for(threads) end |
#sling_initial_content_paths ⇒ Object
173 174 175 176 177 178 |
# File 'lib/aem_lookout/watcher.rb', line 173 def sling_initial_content_paths config.fetch("slingInitialContentPaths", []).map do |sling_initial_content_path| validate_sling_initial_content_path!(sling_initial_content_path) sling_initial_content_path end end |
#sync_vault_package_paths(paths) ⇒ Object
94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 |
# File 'lib/aem_lookout/watcher.rb', line 94 def sync_vault_package_paths(paths) paths.each do |path| if !File.exist?(path) log.warn "#{path} no longer exists, syncing parent instead" path = File.dirname(path) end jcr_path = discover_jcr_path_from_file_in_vault_package(path) AemLookout::Sync.new( hostnames: hostnames, filesystem: path, jcr: jcr_path, log: log ).run end end |
#track_job_on_list(job, running_jobs) ⇒ Object
Adds to running job list and removes from list when thread completes.
83 84 85 86 87 88 89 90 91 92 |
# File 'lib/aem_lookout/watcher.rb', line 83 def track_job_on_list(job, running_jobs) Thread.new do running_jobs << job log.warn "Waiting for #{job} to finish" wait_for(job) log.warn "#{job} job finished" running_jobs.delete(job) Thread.exit end end |
#validate_command_config!(command_config) ⇒ Object
Ensures required keys are present. This is ugly.
189 190 191 192 193 194 |
# File 'lib/aem_lookout/watcher.rb', line 189 def validate_command_config!(command_config) required_keys = ["watch", "command"] unless command_config.has_key?(required_keys.first) and command_config.has_key?(required_keys.last) raise "commands entry is malformed (requires these keys: #{required_keys.join(", ")}): #{command_config.inspect}" end end |
#validate_sling_initial_content_path!(path) ⇒ Object
196 197 198 199 200 |
# File 'lib/aem_lookout/watcher.rb', line 196 def validate_sling_initial_content_path!(path) unless path.has_key?("filesystem") and path.has_key?("jcr") raise "slingInitialContentPaths entry is malformed (requires \"filesystem\" and \"jcr\" entry): #{path.inspect}" end end |
#wait_for(threads) ⇒ Object
33 34 35 |
# File 'lib/aem_lookout/watcher.rb', line 33 def wait_for(threads) sleep 1 until Array(threads).map {|thread| thread.join(1) }.all? {|result| result } end |
#watch_command_config(command_config) ⇒ Object
153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 |
# File 'lib/aem_lookout/watcher.rb', line 153 def watch_command_config(command_config) watch_path = command_config.fetch("watch") pwd = Pathname(repo_path) + command_config.fetch("pwd", "") command = command_config.fetch("command") = {:latency => 1, :file_events => true} fsevent = create_threaded_fsevent watch_path, do |paths| break if paths.empty? log.info "Running command" Terminal.new(log).execute_command("cd #{pwd} && #{command}") end log.info "Watching #{watch_path}, changes will run #{command.inspect}..." fsevent.run end |
#watch_sling_initial_content(path) ⇒ Object
112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 |
# File 'lib/aem_lookout/watcher.rb', line 112 def watch_sling_initial_content(path) filesystem_path = path.fetch("filesystem") jcr_path = path.fetch("jcr") if !File.exist?(filesystem_path) log.warn "Filesystem path for Sling-Initial-Content points to non-existing directory: #{filesystem_path}" return end = {:latency => 0.1, :file_events => true} fsevent = create_threaded_fsevent filesystem_path.to_s, do |paths| begin handle_sling_initial_content_change(paths, filesystem_path, jcr_path) rescue LookoutError => e log.error "An error occurred while handling sling initial content change: #{e.message}" end end log.info "Watching Sling-Initial-Content at #{filesystem_path} for changes..." fsevent.run end |
#watch_vault_package(jcr_root) ⇒ Object
37 38 39 40 41 42 43 44 45 46 47 48 49 50 |
# File 'lib/aem_lookout/watcher.rb', line 37 def watch_vault_package(jcr_root) if !File.exist?(jcr_root) log.warn "jcr_root points to non-existing directory: #{jcr_root}" return end = {:latency => 0.1, :file_events => true} fsevent = create_threaded_fsevent jcr_root.to_s, do |paths| sync_vault_package_paths(paths) end log.info "Watching jcr_root at #{jcr_root} for changes..." fsevent.run end |