cantemo-portal-agent 1.0.9 → 1.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (31) hide show
  1. checksums.yaml +4 -4
  2. data/exe/cantemo-portal-agent +8 -6
  3. data/lib/cantemo/portal/agent/WatchFolderUtility/foreman.rb +59 -0
  4. data/lib/cantemo/portal/agent/cli/commands/watch_folders-working.rb +237 -0
  5. data/lib/cantemo/portal/agent/cli/commands/watch_folders.rb +63 -0
  6. data/lib/cantemo/portal/agent/version.rb +1 -1
  7. data/lib/envoi/aspera/watch_service/client.rb +397 -0
  8. data/lib/envoi/aspera/watch_service/snapshot.rb +11 -0
  9. data/lib/envoi/aspera/watch_service/subscription.rb +0 -0
  10. data/lib/envoi/aspera/watch_service/watch_folder.rb +322 -0
  11. data/lib/envoi/mam/agent/cli/commands/cantemo-agent.rb +62 -0
  12. data/lib/envoi/mam/agent/cli/commands/cantemo-watch_folders.rb +41 -0
  13. data/lib/envoi/mam/agent/cli/commands/cantemo.rb +5 -0
  14. data/lib/envoi/mam/agent/cli/commands/iconik.rb +21 -11
  15. data/lib/envoi/mam/agent/cli/commands/mediasilo.rb +1 -1
  16. data/lib/envoi/mam/agent/cli/commands/vidispine.rb +7 -4
  17. data/lib/envoi/mam/agent/cli/commands/wiredrive.rb +15 -2
  18. data/lib/envoi/mam/agent/cli/commands.rb +4 -4
  19. data/lib/envoi/mam/agent/cli.rb +3 -3
  20. data/lib/envoi/mam/agent/transfer_client/aspera.rb +145 -7
  21. data/lib/envoi/mam/agent/version.rb +1 -1
  22. data/lib/envoi/mam/agent/watch_folder_utility/foreman.rb +76 -0
  23. data/lib/envoi/mam/agent.rb +6 -1
  24. data/lib/envoi/mam/cantemo/agent/watch_folder_handler-working.rb +111 -0
  25. data/lib/envoi/mam/cantemo/agent/watch_folder_handler.rb +176 -0
  26. data/lib/envoi/mam/cantemo/agent/watch_folder_handler_aspera.rb +112 -0
  27. data/lib/envoi/mam/cantemo/agent.rb +288 -0
  28. data/lib/envoi/mam/iconik/agent.rb +15 -3
  29. data/lib/envoi/mam/vidispine/agent.rb +6 -1
  30. data/lib/envoi/watch_folder_utility/watch_folder/handler/listen.rb +189 -0
  31. metadata +48 -4
@@ -1,4 +1,59 @@
1
1
  require 'envoi/mam/agent/transfer_client'
2
+ require 'asperalm/fasp/local'
3
+
4
+
5
+
6
+ module Asperalm
7
+ module Fasp
8
+ module InstallationExtensions
9
+
10
+ PRODUCTS = {
11
+ unix: {
12
+ :aspera_cli_local => {
13
+ :expected=>'Aspera CLI',
14
+ :exe_ext=>'',
15
+ :app_root=>File.join(Dir.home,'.aspera','cli'),
16
+ :run_root=>File.join(Dir.home,'.aspera','cli'),
17
+ :sub_bin=>'bin',
18
+ :sub_keys=>'etc',
19
+ :dsa=>'asperaweb_id_dsa.openssh'
20
+ }
21
+ }
22
+ }
23
+
24
+ def find_missing_products(os_type, common_places)
25
+ missing_products = []
26
+ case os_type
27
+ when :unix
28
+ extended_products = PRODUCTS[os_type] || { }
29
+ extended_products.each do |product_name, product|
30
+ product_found = common_places.find do |cp|
31
+ cp[:expected] == product[:expected] && cp[:app_root] == product[:app_root]
32
+ end
33
+ missing_products.push product unless product_found
34
+ end
35
+ end
36
+ missing_products
37
+ end
38
+
39
+ def add_missing_products(os_type, common_places)
40
+ missing_products = find_missing_products(os_type, common_places)
41
+ common_places.concat missing_products unless missing_products.empty?
42
+ end
43
+
44
+ def product_locations
45
+ common_places = super
46
+ add_missing_products(OpenApplication.current_os_type, common_places)
47
+ common_places
48
+ end
49
+
50
+ end
51
+
52
+ class Installation
53
+ include InstallationExtensions
54
+ end
55
+ end
56
+ end
2
57
 
3
58
  module Envoi
4
59
  module Mam
@@ -32,10 +87,68 @@ module Envoi
32
87
  File.executable?(@ascp_path)
33
88
  end
34
89
 
90
+ def build_asperala_transfer_args(config, mode, source_path, target_path)
91
+
92
+ aspera_host_address = config['host_address'] || config['host']
93
+ aspera_username = config['username']
94
+ aspera_password = config['password']
95
+ aspera_ssh_port = config['ssh_port']
96
+
97
+ aspera_url = config['url'] || config['uri']
98
+ if aspera_url
99
+ aspera_uri = URI(aspera_url)
100
+ aspera_host_address ||= aspera_uri.host if aspera_uri
101
+ un, pw = (aspera_uri.userinfo || '').split(':')
102
+ aspera_username ||= un if un
103
+ aspera_password ||= pw if pw
104
+ aspera_ssh_port = aspera_uri.port
105
+ end
106
+
107
+ aspera_token = config['aspera_transfer_token'] || config['aspera_token'] || config['token'] || config['transfer_token']
108
+
109
+ # @ascp_path = config['ascp_path'] || default_ascp_path
110
+ # @ascp_path = File.expand_path(@ascp_path)
111
+ # aspera_ascp_path = @ascp_path
112
+
113
+ env_vars = { }
114
+ env_vars['ASPERA_SCP_PASS'] = aspera_password if aspera_password
115
+
116
+ ascp_args = config['ascp_args'] || default_ascp_args || agent.default_ascp_args
117
+
118
+ tags = config['tags'] || { }
119
+ aspera_tags = tags['aspera'] || { }
120
+ aspera_tags['xfer_id'] ||= SecureRandom.uuid
121
+
122
+ cmdline_args = [
123
+ '--mode', mode,
124
+ '--host', aspera_host_address,
125
+ '--user', aspera_username,
126
+ '--tags64', Base64.strict_encode64(JSON.generate(tags)),
127
+ ]
128
+ cmdline_args.concat [ '-P', aspera_ssh_port ] if aspera_ssh_port
129
+ cmdline_args.concat ascp_args.is_a?(Array) ? ascp_args : ascp_args.split(' ') if ascp_args && !ascp_args.empty?
130
+ cmdline_args.concat [ '-W', aspera_token ] if aspera_token && !aspera_token.empty?
131
+ cmdline_args.concat [ source_path.gsub('"', '\"'), target_path.gsub('"', '\"') ]
132
+
133
+ { env: env_vars, args: cmdline_args, ascp_version: :ascp }
134
+ end
135
+
35
136
  def build_ascp_command(config, mode, source_path, target_path)
36
137
  aspera_host_address = config['host_address'] || config['host']
37
138
  aspera_username = config['username']
38
139
  aspera_password = config['password']
140
+ aspera_ssh_port = config['ssh_port']
141
+
142
+ aspera_url = config['url'] || config['uri']
143
+ if aspera_url
144
+ aspera_uri = URI(aspera_url)
145
+ aspera_host_address ||= aspera_uri.host if aspera_uri
146
+ un, pw = (aspera_uri.userinfo || '').split(':')
147
+ aspera_username ||= un if un
148
+ aspera_password ||= pw if pw
149
+ aspera_ssh_port ||= aspera_uri.port
150
+ end
151
+
39
152
  aspera_token = config['aspera_transfer_token'] || config['aspera_token'] || config['token'] || config['transfer_token']
40
153
 
41
154
  @ascp_path = config['ascp_path'] || default_ascp_path
@@ -43,11 +156,19 @@ module Envoi
43
156
 
44
157
  aspera_ascp_path = @ascp_path
45
158
 
159
+ tags = config['tags'] || { }
160
+ aspera_tags = tags['aspera'] || { }
161
+ aspera_tags['xfer_id'] ||= SecureRandom.uuid
162
+
163
+
46
164
  ascp_args = config['ascp_args'] || default_ascp_args || agent.default_ascp_args
165
+
47
166
  # command = %(export ASPERA_SCP_PASS="#{aspera_password}"; "#{aspera_ascp_path}" #{ascp_args} --host="#{aspera_host_address}" --user=#{aspera_username} --mode=#{mode} "#{source_path}" "#{target_path}" )
48
167
  command = ''
49
168
  command << %(export ASPERA_SCP_PASS="#{aspera_password}"; ) if aspera_password
50
169
  command << %("#{aspera_ascp_path}" --mode=#{mode} --host="#{aspera_host_address}" --user="#{aspera_username}")
170
+ command << %( -P #{aspera_ssh_port}) if aspera_ssh_port
171
+ command << %(--tags64 #{Base64.strict_encode64(JSON.generate(tags))}) if tags && !tags.empty?
51
172
  command << %( #{ascp_args}) if ascp_args && !ascp_args.empty?
52
173
  command << %( -W "#{aspera_token}") if aspera_token && !aspera_token.empty?
53
174
  command << %( "#{source_path.gsub('"', '\"')}" "#{target_path.gsub('"', '\"')}")
@@ -56,20 +177,37 @@ module Envoi
56
177
  def download(config, path, destination_path = DEFAULT_DESTINATION_PATH)
57
178
  aspera_base_path = config['base_path'] || ''
58
179
  source_path = File.join(aspera_base_path, path)
59
- command = build_ascp_command(config, 'recv', source_path, destination_path)
60
180
 
61
- unless ascp_path_exists?
62
- warn "ASCP not found. '#{ascp_path}'"
63
- return false
64
- end
65
- agent.shell_execute(command)
181
+ mode = 'recv'
182
+ transfer(config, mode, source_path, destination_path)
66
183
  end
67
184
 
68
185
  def upload(config, path, destination_path = DEFAULT_DESTINATION_PATH)
69
186
  aspera_base_path = config['base_path'] || ''
70
187
  source_path = path
71
188
  destination_path = aspera_base_path.empty? ? destination_path : File.join(aspera_base_path, destination_path)
72
- command = build_ascp_command(config, 'send', source_path, destination_path)
189
+
190
+ mode = 'send'
191
+ transfer(config, mode, source_path, destination_path)
192
+ end
193
+
194
+ def transfer(config, mode, source_path, destination_path)
195
+ if false
196
+ transfer_using_asperala(config, mode, source_path, destination_path)
197
+ else
198
+ transfer_using_shell_execute(config, mode, source_path, destination_path)
199
+ end
200
+ end
201
+
202
+ def transfer_using_asperala(config, mode, source_path, destination_path)
203
+ args_out = build_asperala_transfer_args(config, mode, source_path, destination_path)
204
+ fasp = Asperalm::Fasp::Local.instance
205
+ Asperalm::Log.instance.level = :debug
206
+ fasp.start_transfer_with_args_env(args_out, {})
207
+ end
208
+
209
+ def transfer_using_shell_execute(config, mode, source_path, destination_path)
210
+ command = build_ascp_command(config, mode, source_path, destination_path)
73
211
 
74
212
  unless ascp_path_exists?
75
213
  warn "ASCP not found. '#{ascp_path}'"
@@ -1,7 +1,7 @@
1
1
  module Envoi
2
2
  module Mam
3
3
  class Agent
4
- VERSION = '1.0.2'.freeze
4
+ VERSION = '1.1.0'.freeze
5
5
  end
6
6
  end
7
7
  end
@@ -0,0 +1,76 @@
1
+ module Envoi
2
+ module Mam
3
+ class Agent
4
+ class WatchFolderUtility
5
+ class Foreman
6
+
7
+ AWF = Envoi::Aspera::WatchService::WatchFolder
8
+ LWF = Envoi::WatchFolderUtility::WatchFolder::Listen
9
+
10
+ attr_accessor :logger, :agent, :config, :watch_folders
11
+
12
+ def initialize(args = { })
13
+ initialize_logger(args)
14
+
15
+ @agent = Envoi::Mam::Cantemo::Agent.load_from_config_file(args)
16
+ @config = agent.config
17
+ cantemo_config = config[:cantemo] || config['cantemo']
18
+ watch_folder_defs = cantemo_config[:watch_folders] || cantemo_config['watch_folders']
19
+
20
+ @ignored_file_paths_by_watch_folder = Hash.new { |h, k| h[k] = [] }
21
+
22
+
23
+
24
+ @watch_folders = AWF.process_watch_folder_defs(watch_folder_defs)
25
+ end
26
+
27
+ def self.initialize_watch_folder(watch_folder_def)
28
+ case (watch_folder_def['handler'] || '').downcase.gsub(/[-_ ]/, '')
29
+ when 'asperawatch'
30
+ wf_class = Envoi::Aspera::WatchService::WatchFolder
31
+ end
32
+ wf_class.new(watch_folder_def)
33
+ end
34
+
35
+ def self.process_watch_folder_def(watch_folder_def)
36
+ initialize_watch_folder(watch_folder_def)
37
+ end
38
+
39
+ def self.process_watch_folder_defs(watch_folder_defs)
40
+ if watch_folder_defs.is_a?(Array)
41
+ watch_folder_defs.map { |watch_folder_def| process_watch_folder_def(watch_folder_def) }
42
+ elsif watch_folder_defs.is_a?(Hash)
43
+ watch_folder_defs.map do |name, watch_folder_def|
44
+ watch_folder_def['path'] ||= name; process_watch_folder_def(watch_folder_def)
45
+ end
46
+ else
47
+ raise "Unhandled format: #{watch_folder_defs.class.name}"
48
+ end
49
+ end
50
+
51
+ def self.poll_watch_folder(watch_folder, &block)
52
+ watch_folder.poll(&block)
53
+ end
54
+
55
+ def self.poll_watch_folders(watch_folders, &block)
56
+ watch_folders.each { |watch_folder| poll_watch_folder(watch_folder, &block) }
57
+ end
58
+
59
+ def self.run_once(watch_folders, &block)
60
+ poll_watch_folders(watch_folders, &block)
61
+ end
62
+
63
+ # Foreman
64
+ end
65
+
66
+ # WatchFolderUtility
67
+ end
68
+
69
+ # Agent
70
+ end
71
+
72
+ # Mam
73
+ end
74
+
75
+ # Envoi
76
+ end
@@ -55,6 +55,7 @@ module Envoi
55
55
  end
56
56
  logger.debug { "Executing Command: '#{command}'" }
57
57
 
58
+ success = false
58
59
  Open3.popen3(command) do |stdin, stdout, stderr, thread|
59
60
  # stdin.sync = true
60
61
  # stdout.sync = true
@@ -65,11 +66,15 @@ module Envoi
65
66
  output << stdout.read #rescue nil
66
67
  output << stderr.read # rescue nil
67
68
  unless output.empty?
68
- print output
69
+ logger.debug { output }
69
70
  output.clear
70
71
  end
71
72
  end
73
+
74
+ success = thread.value == 0 ? true : false
72
75
  end
76
+
77
+ success
73
78
  end
74
79
 
75
80
  def self.load_from_config_file(args)
@@ -0,0 +1,111 @@
1
+ require 'envoi/mam/cantemo/agent'
2
+ require 'envoi/aspera/watch_service/watch_folder'
3
+
4
+ module Envoi::Mam::Cantemo
5
+
6
+ class Agent
7
+
8
+ class WatchFolderHandler
9
+
10
+ AWF = Envoi::Aspera::WatchService::WatchFolder
11
+
12
+ attr_accessor :logger, :agent, :config, :watch_folders
13
+
14
+ def initialize(args = { })
15
+ initialize_logger(args)
16
+
17
+ @agent = Envoi::Mam::Cantemo::Agent.load_from_config_file(args)
18
+ @config = agent.config
19
+ cantemo_config = config[:cantemo] || config['cantemo']
20
+ watch_folder_defs = cantemo_config[:watch_folders] || cantemo_config['watch_folders']
21
+
22
+ @ignored_file_paths_by_watch_folder = Hash.new { |h, k| h[k] = [] }
23
+
24
+ @watch_folders = AWF.process_watch_folder_defs(watch_folder_defs)
25
+ end
26
+
27
+ def initialize_logger(args = { })
28
+ @logger = args[:logger] ||= Logger.new(args[:log_to] || STDOUT)
29
+ log_level = args[:log_level]
30
+ if log_level
31
+ @logger.level = log_level
32
+ args[:logger] = @logger
33
+ end
34
+ @logger
35
+ end
36
+
37
+ def add_to_ignore(wf, file)
38
+ @ignored_file_paths_by_watch_folder[wf] << file.path
39
+ end
40
+
41
+ def process_file(watch_folder, file, storage_id = nil, quarantine_directory_path = nil)
42
+ full_file_path = File.join(watch_folder.path, file.path)
43
+ if storage_id && agent.upload(file_path: full_file_path, storage_id: storage_id)
44
+ FileUtils.rm full_file_path
45
+ else
46
+ if Dir.exist?(quarantine_directory_path)
47
+ FileUtils.mv full_file_path, quarantine_directory_path
48
+ else
49
+ add_to_ignore(watch_folder, file)
50
+ end
51
+ end
52
+ end
53
+
54
+ def process_watch_folder(wf)
55
+ storage_id = wf.definition['upload_to_storage_id'] || wf.definition['storage_id']
56
+ quarantine_directory_path = wf.definition['quarantine_path']
57
+ exclude = wf.definition['exclude']
58
+ min_stable_poll_count = wf.definition['stable_poll_count'] || 3
59
+
60
+ maps = wf.state.details[:maps]
61
+ stable_paths = maps[:stable]
62
+ ignored_files = @ignored_file_paths_by_watch_folder[wf]
63
+ stable_paths.each do |fp, file|
64
+ if exclude
65
+ next if ignored_files.include?(file.path)
66
+ if [*exclude].find { |ep| File.fnmatch(ep, file.path) }
67
+ logger.debug { "Adding File to Ignore Cache: '#{file.path}'"}
68
+ ignored_files << file.path
69
+ next
70
+ end
71
+ end
72
+
73
+ # full_file_path = File.join(wf.path, file.path)
74
+
75
+ # pp file
76
+ # puts file_path
77
+ stable_poll_count = file[:stable_poll_count]
78
+
79
+ if stable_poll_count && stable_poll_count > min_stable_poll_count
80
+ process_file(wf, file, storage_id, quarantine_directory_path)
81
+ end
82
+ end
83
+
84
+ # process_watch_folder
85
+ end
86
+
87
+ def run
88
+ # AWF.run_once(watch_folders) { |wf| pp wf }
89
+ AWF.run(watch_folders) { |wf| process_watch_folder(wf) }
90
+ end
91
+
92
+ def run_once
93
+ AWF.run_once(watch_folders) { |wf| process_watch_folder(wf) }
94
+ end
95
+
96
+ def self.run(args)
97
+ w = self.new(args)
98
+ w.run
99
+ end
100
+
101
+ def self.run_as_daemon(args)
102
+ # ARGV.unshift 'run' unless %w(start stop restart run zap killall status).include? ARGV.first
103
+ require 'daemons'
104
+ Daemons.run_proc('cantemo-portal-watch-folders') { self.run(args) }
105
+ end
106
+
107
+ end
108
+
109
+ end
110
+
111
+ end
@@ -0,0 +1,176 @@
1
+ require 'envoi/mam/cantemo/agent'
2
+ require 'envoi/aspera/watch_service/watch_folder'
3
+ require 'envoi/watch_folder_utility/watch_folder/handler/listen'
4
+
5
+ module Envoi::Mam::Cantemo
6
+
7
+ class Agent
8
+
9
+ class WatchFolderHandler
10
+
11
+ AWF = Envoi::Aspera::WatchService::WatchFolder
12
+ LWF = Envoi::WatchFolderUtility::WatchFolder::Handler::Listen
13
+
14
+ attr_accessor :logger, :agent, :config, :watch_folder_defs, :watch_folders
15
+
16
+ def initialize(args = { })
17
+ initialize_logger(args)
18
+
19
+ @agent = Envoi::Mam::Cantemo::Agent.load_from_config_file(args)
20
+ @config = agent.config
21
+ cantemo_config = config[:cantemo] || config['cantemo']
22
+ @watch_folder_defs = cantemo_config[:watch_folders] || cantemo_config['watch_folders']
23
+
24
+ @ignored_file_paths_by_watch_folder = Hash.new { |h, k| h[k] = [] }
25
+ process_watch_folder_defs
26
+ end
27
+
28
+ def process_watch_folder_def(watch_folder_def)
29
+ name = watch_folder_def['name']
30
+
31
+ path = watch_folder_def['path']
32
+ path ||= name
33
+ (watch_folder_def['paths'] ||= []).concat [*path]
34
+ watch_folder_def['paths'].uniq!
35
+ paths = watch_folder_def['paths']
36
+ watch_folder_def['path'] ||= paths.first if path.length == 1
37
+
38
+ exclude = watch_folder_def['exclude']
39
+ exclude ||= '**/.*'
40
+ (watch_folder_def['excludes'] ||= []).concat [*exclude]
41
+ watch_folder_def['excludes'].uniq!
42
+
43
+ args_out = { }
44
+ logging = watch_folder_def['logging'] || watch_folder_def
45
+ log_to = logging['log_to']
46
+ log_level = logging['log_level']
47
+ args_out[:log_to] ||= log_to if log_to && !log_to.empty?
48
+ args_out[:log_level] ||= log_level if log_level && !log_level.empty?
49
+ args_out[:logger] ||= logger.dup unless log_to
50
+ args_out[:definition] = watch_folder_def
51
+
52
+ LWF.new(args_out)
53
+ end
54
+
55
+ def process_watch_folder_defs
56
+ if watch_folder_defs.is_a?(Array)
57
+ @watch_folders = watch_folder_defs.map { |watch_folder_def| process_watch_folder_def(watch_folder_def) }
58
+ elsif watch_folder_defs.is_a?(Hash)
59
+ @watch_folders = watch_folder_defs.map do |name, watch_folder_def|
60
+ watch_folder_def['name'] ||= name
61
+
62
+ process_watch_folder_def(watch_folder_def)
63
+ end
64
+ else
65
+ raise "Unhandled format: #{watch_folder_defs.class.name}"
66
+ end
67
+ end
68
+
69
+ def initialize_logger(args = { })
70
+ @logger = args[:logger] ||= Logger.new(args[:log_to] || STDOUT)
71
+ log_level = args[:log_level]
72
+ if log_level
73
+ @logger.level = log_level
74
+ args[:logger] = @logger
75
+ end
76
+ @logger
77
+ end
78
+
79
+ def add_to_ignore(watch_folder, file)
80
+ logger.debug { "Adding File to Ignore Cache: '#{file.path}'"}
81
+ @ignored_file_paths_by_watch_folder[watch_folder] << file.path
82
+ end
83
+
84
+ def process_file(watch_folder, file, storage_id = nil, quarantine_directory_path = nil)
85
+ # full_file_path = File.join(watch_folder.path, file.path)
86
+ full_file_path = file.path
87
+ if storage_id && agent.upload(file_path: full_file_path, storage_id: storage_id)
88
+ FileUtils.rm full_file_path
89
+ else
90
+ if Dir.exist?(quarantine_directory_path)
91
+ FileUtils.mv full_file_path, quarantine_directory_path
92
+ else
93
+ add_to_ignore(watch_folder, file)
94
+ end
95
+ end
96
+ end
97
+
98
+ def process_watch_folder_stable_files(wf, stable_files)
99
+ storage_id = wf.definition['upload_to_storage_id'] || wf.definition['storage_id']
100
+ quarantine_directory_path = wf.definition['quarantine_path']
101
+ exclude = wf.definition['excludes']
102
+
103
+ ignored_file_paths = @ignored_file_paths_by_watch_folder[wf]
104
+ stable_files.each do |file|
105
+ next if ignored_file_paths.include?(file.path)
106
+
107
+ if exclude && [*exclude].find do |ep|
108
+ excluded = (r = Regexp.try_convert(ep) ? r.match(ep) : File.fnmatch(ep, file.path))
109
+ logger.debug { "#{ep} #{excluded ? 'matched' : "didn't match"} #{file.path}" }
110
+ excluded
111
+ end
112
+ add_to_ignore(wf, file)
113
+ next
114
+ end
115
+
116
+ process_file(wf, file, storage_id, quarantine_directory_path)
117
+ end
118
+
119
+ end
120
+
121
+ def poll
122
+ stable_files_by_watch_folder = {} # Hash.new { |h, k| h[k] = [] }
123
+ watch_folders.each do |watch_folder|
124
+ if !watch_folder.last_poll_time || (Time.now - watch_folder.last_poll_time) >= watch_folder.poll_interval
125
+ stable_files = watch_folder.poll
126
+ stable_files_by_watch_folder[watch_folder] = stable_files
127
+ end
128
+ end
129
+ stable_files_by_watch_folder.each do |watch_folder, stable_files|
130
+ process_watch_folder_stable_files(watch_folder, stable_files)
131
+ end
132
+ end
133
+
134
+ def run
135
+ # AWF.run_once(watch_folders) { |wf| pp wf }
136
+ # AWF.run(watch_folders) { |wf| process_watch_folder(wf) }
137
+
138
+ logger.info { 'Running...' }
139
+ watch_folders.map { |wf| wf.run }
140
+ loop do
141
+ begin
142
+ poll
143
+ sleep 1
144
+ rescue SystemExit, Interrupt
145
+ break
146
+ end
147
+ end
148
+ logger.info { 'Exiting...' }
149
+ rescue => e
150
+ logger.error { "An error occurred.\n#{e.message}\n#{e.backtrace.join("\n")}\n#{e.message}" }
151
+ raise e
152
+ end
153
+
154
+ def run_once
155
+ # AWF.run_once(watch_folders) { |wf| process_watch_folder(wf) }
156
+ end
157
+
158
+ def self.run(args)
159
+ w = self.new(args)
160
+ w.run
161
+ rescue => e
162
+ abort("An error occurred.\n#{e.message}\n#{e.message}")
163
+ end
164
+
165
+ def self.run_as_daemon(args)
166
+ # ARGV.unshift 'run' unless %w(start stop restart run zap killall status).include? ARGV.first
167
+ require 'daemons'
168
+ # Daemons.run_proc('cantemo-portal-watch-folders', { force: true }) { self.run(args) }
169
+ Daemons.run_proc('cantemo-portal-watch-folders') { self.run(args) }
170
+ end
171
+
172
+ end
173
+
174
+ end
175
+
176
+ end