triglav-agent 1.0.0.pre1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +11 -0
- data/.rspec +2 -0
- data/.travis.yml +6 -0
- data/.yardopts +6 -0
- data/CHANGELOG.md +3 -0
- data/CODE_OF_CONDUCT.md +49 -0
- data/Gemfile +5 -0
- data/LICENSE.txt +21 -0
- data/README.md +59 -0
- data/Rakefile +11 -0
- data/bin/console +14 -0
- data/bin/setup +8 -0
- data/docs/Triglav/Agent/ApiClient/AuthenticationError.html +150 -0
- data/docs/Triglav/Agent/ApiClient/ConnectionError.html +150 -0
- data/docs/Triglav/Agent/ApiClient/Error.html +296 -0
- data/docs/Triglav/Agent/ApiClient.html +545 -0
- data/docs/Triglav/Agent/Base/CLI.html +498 -0
- data/docs/Triglav/Agent/Base/Connection.html +258 -0
- data/docs/Triglav/Agent/Base/Monitor.html +370 -0
- data/docs/Triglav/Agent/Base/Processor.html +623 -0
- data/docs/Triglav/Agent/Base/Setting.html +1081 -0
- data/docs/Triglav/Agent/Base/Worker.html +635 -0
- data/docs/Triglav/Agent/Base.html +121 -0
- data/docs/Triglav/Agent/Configuration.html +967 -0
- data/docs/Triglav/Agent/Error.html +130 -0
- data/docs/Triglav/Agent/HashUtil.html +351 -0
- data/docs/Triglav/Agent/LogFormatter.html +271 -0
- data/docs/Triglav/Agent/Logger.html +287 -0
- data/docs/Triglav/Agent/StorageFile.html +1130 -0
- data/docs/Triglav/Agent/Timer.html +424 -0
- data/docs/Triglav/Agent/TooManyError.html +134 -0
- data/docs/Triglav/Agent.html +131 -0
- data/docs/Triglav.html +119 -0
- data/docs/_index.html +335 -0
- data/docs/class_list.html +51 -0
- data/docs/css/common.css +1 -0
- data/docs/css/full_list.css +58 -0
- data/docs/css/style.css +481 -0
- data/docs/file.LICENSE.html +72 -0
- data/docs/file.README.html +137 -0
- data/docs/file_list.html +61 -0
- data/docs/frames.html +17 -0
- data/docs/index.html +137 -0
- data/docs/js/app.js +243 -0
- data/docs/js/full_list.js +216 -0
- data/docs/js/jquery.js +4 -0
- data/docs/method_list.html +659 -0
- data/docs/top-level-namespace.html +112 -0
- data/example/config.yml +40 -0
- data/lib/triglav/agent/api_client.rb +199 -0
- data/lib/triglav/agent/base/cli.rb +98 -0
- data/lib/triglav/agent/base/connection.rb +30 -0
- data/lib/triglav/agent/base/monitor.rb +32 -0
- data/lib/triglav/agent/base/processor.rb +136 -0
- data/lib/triglav/agent/base/setting.rb +112 -0
- data/lib/triglav/agent/base/worker.rb +95 -0
- data/lib/triglav/agent/configuration.rb +79 -0
- data/lib/triglav/agent/error.rb +4 -0
- data/lib/triglav/agent/hash_util.rb +36 -0
- data/lib/triglav/agent/logger.rb +50 -0
- data/lib/triglav/agent/storage_file.rb +144 -0
- data/lib/triglav/agent/timer.rb +80 -0
- data/lib/triglav/agent/version.rb +5 -0
- data/lib/triglav/agent.rb +20 -0
- data/lib/triglav-agent.rb +1 -0
- data/triglav-agent.gemspec +33 -0
- metadata +250 -0
@@ -0,0 +1,112 @@
|
|
1
|
+
require 'triglav/agent/hash_util'
|
2
|
+
require 'triglav/agent/logger'
|
3
|
+
require 'yaml'
|
4
|
+
require 'erb'
|
5
|
+
|
6
|
+
module Triglav::Agent
|
7
|
+
module Base
|
8
|
+
# A base class represents settings coming from config.yml and cli options
|
9
|
+
#
|
10
|
+
# This base class usually should be enough for agent plugins, but
|
11
|
+
# you can override this class and configure with Configuration#setting_class=
|
12
|
+
class Setting
|
13
|
+
attr_reader :cli_options
|
14
|
+
|
15
|
+
DEFAULT_LOG = 'STDOUT'.freeze
|
16
|
+
DEFAULT_LOG_LEVEL = 'info'.freeze
|
17
|
+
DEFAULT_APP_ENV = 'development'.freeze
|
18
|
+
|
19
|
+
def initialize(cli_options = {})
|
20
|
+
@cli_options = cli_options
|
21
|
+
if dotenv?
|
22
|
+
require 'dotenv'
|
23
|
+
Dotenv.load
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
def reload
|
28
|
+
Dotenv.overload if dotenv?
|
29
|
+
@config = nil
|
30
|
+
@logger.close rescue nil
|
31
|
+
@logger = nil
|
32
|
+
end
|
33
|
+
|
34
|
+
def app_env
|
35
|
+
@app_env ||= ENV['APP_ENV'] || DEFAULT_APP_ENV
|
36
|
+
end
|
37
|
+
|
38
|
+
def config_file
|
39
|
+
@cli_options[:config]
|
40
|
+
end
|
41
|
+
|
42
|
+
def status_file
|
43
|
+
@status_file ||= @cli_options[:status] || config.dig(:triglav, :status_file) || 'status.yml'
|
44
|
+
end
|
45
|
+
|
46
|
+
def token_file
|
47
|
+
@token_file ||= @cli_options[:token] || config.dig(:triglav, :token_file) || 'token.yml'
|
48
|
+
end
|
49
|
+
|
50
|
+
def dotenv?
|
51
|
+
@cli_options[:dotenv]
|
52
|
+
end
|
53
|
+
|
54
|
+
def debug?
|
55
|
+
@cli_options[:debug]
|
56
|
+
end
|
57
|
+
|
58
|
+
def logger
|
59
|
+
@logger ||= Logger.new(log, serverengine_logger_options)
|
60
|
+
end
|
61
|
+
|
62
|
+
def log_level
|
63
|
+
@cli_options[:log_level] || config.dig(:serverengine, :log_level) || DEFAULT_LOG_LEVEL
|
64
|
+
end
|
65
|
+
|
66
|
+
def log
|
67
|
+
@cli_options[:log] || config.dig(:serverengine, :log) || DEFAULT_LOG
|
68
|
+
end
|
69
|
+
|
70
|
+
def serverengine_options
|
71
|
+
serverengine_options = config[:serverengine].dup || {}
|
72
|
+
# serverengine_options[:workers] = 1 # default
|
73
|
+
# serverengine_options[:worker_type] = 'embedded' # default
|
74
|
+
serverengine_options.keys.each do |k|
|
75
|
+
serverengine_options.delete(k) if k.to_s.start_with?('log')
|
76
|
+
end
|
77
|
+
serverengine_options.merge!({
|
78
|
+
logger: logger,
|
79
|
+
log_level: log_level,
|
80
|
+
setting: self,
|
81
|
+
})
|
82
|
+
end
|
83
|
+
|
84
|
+
def [](key)
|
85
|
+
config[key]
|
86
|
+
end
|
87
|
+
|
88
|
+
def dig(*args)
|
89
|
+
config.dig(*args)
|
90
|
+
end
|
91
|
+
|
92
|
+
private
|
93
|
+
|
94
|
+
def config
|
95
|
+
@config ||=
|
96
|
+
begin
|
97
|
+
raw = File.read(config_file)
|
98
|
+
erb = ERB.new(raw, nil, "-").tap {|_| _.filename = config_file }
|
99
|
+
all = HashUtil.deep_symbolize_keys(YAML.load(erb.result(binding)))
|
100
|
+
all[app_env.to_sym]
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
def serverengine_logger_options
|
105
|
+
{
|
106
|
+
log: log,
|
107
|
+
log_level: log_level,
|
108
|
+
}
|
109
|
+
end
|
110
|
+
end
|
111
|
+
end
|
112
|
+
end
|
@@ -0,0 +1,95 @@
|
|
1
|
+
require 'triglav/agent/timer'
|
2
|
+
|
3
|
+
module Triglav::Agent
|
4
|
+
module Base
|
5
|
+
# Triglav agent worker module for Serverengine.
|
6
|
+
#
|
7
|
+
# You usually do not need to customize this module, but if you want to
|
8
|
+
# implement your original, configure
|
9
|
+
#
|
10
|
+
# Triglav::Agent::Configuration.worker_module
|
11
|
+
module Worker
|
12
|
+
# serverengine interface
|
13
|
+
def initialize
|
14
|
+
@timer = Timer.new
|
15
|
+
end
|
16
|
+
|
17
|
+
# serverengine interface
|
18
|
+
def reload
|
19
|
+
$logger.info { "Worker#reload worker_id:#{worker_id}" }
|
20
|
+
$setting.reload
|
21
|
+
end
|
22
|
+
|
23
|
+
# serverengine interface
|
24
|
+
def run
|
25
|
+
$logger.info { "Worker#run worker_id:#{worker_id}" }
|
26
|
+
start
|
27
|
+
until @stop
|
28
|
+
@timer.wait(monitor_interval) { process }
|
29
|
+
end
|
30
|
+
rescue => e
|
31
|
+
# ServerEngine.dump_uncaught_error does not tell me e.class
|
32
|
+
log_error(e)
|
33
|
+
raise e
|
34
|
+
end
|
35
|
+
|
36
|
+
def process
|
37
|
+
started = Time.now
|
38
|
+
$logger.info { "Start Worker#process worker_id:#{worker_id}" }
|
39
|
+
|
40
|
+
total_count = 0
|
41
|
+
total_success_count = 0
|
42
|
+
resource_uri_prefixes.each do |resource_uri_prefix|
|
43
|
+
break if stopped?
|
44
|
+
processor = processor_class.new(self, resource_uri_prefix)
|
45
|
+
total_count += processor.total_count
|
46
|
+
total_success_count += processor.process
|
47
|
+
end
|
48
|
+
|
49
|
+
elapsed = Time.now - started
|
50
|
+
$logger.info {
|
51
|
+
"Finish Worker#process worker_id:#{worker_id} " \
|
52
|
+
"success_count/total_count:#{total_success_count}/#{total_count} elapsed:#{elapsed.to_f}sec"
|
53
|
+
}
|
54
|
+
end
|
55
|
+
|
56
|
+
def start
|
57
|
+
@timer.start
|
58
|
+
@stop = false
|
59
|
+
end
|
60
|
+
|
61
|
+
# serverengine interface
|
62
|
+
def stop
|
63
|
+
$logger.info { "Worker#stop worker_id:#{worker_id}" }
|
64
|
+
@stop = true
|
65
|
+
@timer.stop
|
66
|
+
end
|
67
|
+
|
68
|
+
def stopped?
|
69
|
+
@stop
|
70
|
+
end
|
71
|
+
|
72
|
+
private
|
73
|
+
|
74
|
+
def processor_class
|
75
|
+
Configuration.processor_class
|
76
|
+
end
|
77
|
+
|
78
|
+
def name
|
79
|
+
Configuration.name
|
80
|
+
end
|
81
|
+
|
82
|
+
def log_error(e)
|
83
|
+
$logger.error { "#{e.class} #{e.message} #{e.backtrace.join("\\n")}" } # one line
|
84
|
+
end
|
85
|
+
|
86
|
+
def monitor_interval
|
87
|
+
$setting.dig(name, :monitor_interval) || 60
|
88
|
+
end
|
89
|
+
|
90
|
+
def resource_uri_prefixes
|
91
|
+
$setting.dig(name, :connection_info).keys
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|
95
|
+
end
|
@@ -0,0 +1,79 @@
|
|
1
|
+
module Triglav
|
2
|
+
module Agent
|
3
|
+
# Configure Triglav::Agent framework
|
4
|
+
#
|
5
|
+
# require 'triglav/agent/configuration'
|
6
|
+
# require 'triglav/agent/vertica/worker'
|
7
|
+
# Triglav::Agent::Configuration.configure do |config|
|
8
|
+
# config.name = :vertica # default: :agent
|
9
|
+
# config.cli_class = Triglav::Agent::Vertica::CLI
|
10
|
+
# config.setting_class = Triglav::Agent::Vertica::Setting
|
11
|
+
# config.worker_module = Triglav::Agent::Vertica::Worker
|
12
|
+
# config.processor_class = Triglav::Agent::Vertica::Processor
|
13
|
+
# config.monitor_class = Triglav::Agent::Vertica::Monitor
|
14
|
+
# config.connection_class = Triglav::Agent::Vertica::Connection
|
15
|
+
# end
|
16
|
+
# Triglav::Agent::Configuration.cli_class.new.run
|
17
|
+
class Configuration
|
18
|
+
def self.configure(&block)
|
19
|
+
yield(Triglav::Agent::Configuration)
|
20
|
+
end
|
21
|
+
|
22
|
+
def self.worker_module
|
23
|
+
@worker_module ||= Triglav::Agent::Base::Worker
|
24
|
+
end
|
25
|
+
|
26
|
+
def self.processor_class
|
27
|
+
@processor_class ||= Triglav::Agent::Base::Processor
|
28
|
+
end
|
29
|
+
|
30
|
+
def self.monitor_class
|
31
|
+
@monitor_class ||= Triglav::Agent::Base::Monitor
|
32
|
+
end
|
33
|
+
|
34
|
+
def self.connection_class
|
35
|
+
@connection_class ||= Triglav::Agent::Base::Connection
|
36
|
+
end
|
37
|
+
|
38
|
+
def self.setting_class
|
39
|
+
@setting_class ||= Triglav::Agent::Base::Setting
|
40
|
+
end
|
41
|
+
|
42
|
+
def self.cli_class
|
43
|
+
@cli_class ||= Triglav::Agent::Base::CLI
|
44
|
+
end
|
45
|
+
|
46
|
+
def self.name
|
47
|
+
@name ||= :agent
|
48
|
+
end
|
49
|
+
|
50
|
+
def self.worker_module=(worker_module)
|
51
|
+
@worker_module = worker_module
|
52
|
+
end
|
53
|
+
|
54
|
+
def self.processor_class=(processor_class)
|
55
|
+
@processor_class = processor_class
|
56
|
+
end
|
57
|
+
|
58
|
+
def self.monitor_class=(monitor_class)
|
59
|
+
@monitor_class = monitor_class
|
60
|
+
end
|
61
|
+
|
62
|
+
def self.connection_class=(connection_class)
|
63
|
+
@connection_class = connection_class
|
64
|
+
end
|
65
|
+
|
66
|
+
def self.setting_class=(setting_class)
|
67
|
+
@setting_class = setting_class
|
68
|
+
end
|
69
|
+
|
70
|
+
def self.cli_class=(cli_class)
|
71
|
+
@cli_class = cli_class
|
72
|
+
end
|
73
|
+
|
74
|
+
def self.name=(name)
|
75
|
+
@name = name
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
module Triglav::Agent
|
2
|
+
class HashUtil
|
3
|
+
def self.deep_symbolize_keys(obj)
|
4
|
+
case obj
|
5
|
+
when Hash
|
6
|
+
obj.map {|k, v| [k.to_sym, deep_symbolize_keys(v)] }.to_h
|
7
|
+
when Array
|
8
|
+
obj.map {|v| deep_symbolize_keys(v) }
|
9
|
+
else
|
10
|
+
obj
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
def self.deep_stringify_keys(obj)
|
15
|
+
case obj
|
16
|
+
when Hash
|
17
|
+
obj.map {|k, v| [k.to_s, deep_stringify_keys(v)] }.to_h
|
18
|
+
when Array
|
19
|
+
obj.map {|v| deep_stringify_keys(v) }
|
20
|
+
else
|
21
|
+
obj
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
# HashUtil.setdig(hash, ['a', 'b'], 'bar') # like hash['a']['b'] = 'bar'
|
26
|
+
def self.setdig(hash, key, val)
|
27
|
+
keys = Array(key)
|
28
|
+
sub_hash = hash
|
29
|
+
keys[0...-1].each do |k|
|
30
|
+
sub_hash = (sub_hash[k] ||= {})
|
31
|
+
end
|
32
|
+
sub_hash[keys.last] = val
|
33
|
+
hash
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,50 @@
|
|
1
|
+
require 'serverengine/daemon_logger'
|
2
|
+
|
3
|
+
module Triglav::Agent
|
4
|
+
# Logger class
|
5
|
+
#
|
6
|
+
# require 'triglav/agent/logger'
|
7
|
+
# logger = Logger.new('STDOUT', opts = {})
|
8
|
+
class Logger < ::ServerEngine::DaemonLogger
|
9
|
+
def initialize(logdev, *args)
|
10
|
+
logdev = STDOUT if logdev == 'STDOUT'
|
11
|
+
logdev = STDERR if logdev == 'STDERR'
|
12
|
+
super(logdev, *args)
|
13
|
+
@formatter = LogFormatter.new
|
14
|
+
end
|
15
|
+
|
16
|
+
def write(msg)
|
17
|
+
@logdev.write msg
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
class LogFormatter
|
22
|
+
FORMAT = "%s [%s] %s %s\n"
|
23
|
+
|
24
|
+
def initialize(opts={})
|
25
|
+
end
|
26
|
+
|
27
|
+
def call(severity, time, progname, msg)
|
28
|
+
FORMAT % [format_datetime(time), severity, format_pid, format_message(msg)]
|
29
|
+
end
|
30
|
+
|
31
|
+
private
|
32
|
+
def format_datetime(time)
|
33
|
+
time.strftime("%Y-%m-%dT%H:%M:%S.%6N%:z")
|
34
|
+
end
|
35
|
+
|
36
|
+
def format_pid
|
37
|
+
"PID-#{::Process.pid} TID-#{Thread.current.object_id}"
|
38
|
+
end
|
39
|
+
|
40
|
+
def format_message(message)
|
41
|
+
case message
|
42
|
+
when ::Exception
|
43
|
+
e = message
|
44
|
+
"#{e.class} (#{e.message})\\n #{e.backtrace.join("\\n ")}"
|
45
|
+
else
|
46
|
+
message.to_s.gsub(/\n/, "\\n")
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
@@ -0,0 +1,144 @@
|
|
1
|
+
require 'triglav/agent/hash_util'
|
2
|
+
require 'yaml'
|
3
|
+
|
4
|
+
module Triglav::Agent
|
5
|
+
# Thread and inter-process safe YAML file storage
|
6
|
+
#
|
7
|
+
# StorageFile.open($setting.status_file) do |fp|
|
8
|
+
# status = fp.load
|
9
|
+
# status['foo'] = 'bar'
|
10
|
+
# fp.dump(status)
|
11
|
+
# end
|
12
|
+
class StorageFile
|
13
|
+
attr_reader :fp
|
14
|
+
|
15
|
+
private def initialize(fp)
|
16
|
+
@fp = fp
|
17
|
+
end
|
18
|
+
|
19
|
+
# Load storage file
|
20
|
+
#
|
21
|
+
# StorageFile.load($setting.status_file)
|
22
|
+
#
|
23
|
+
# @param [String] path
|
24
|
+
# @return [Hash]
|
25
|
+
def self.load(path)
|
26
|
+
open(path) {|fp| fp.load }
|
27
|
+
end
|
28
|
+
|
29
|
+
# Open storage file
|
30
|
+
#
|
31
|
+
# StorageFile.open($setting.status_file) do |fp|
|
32
|
+
# status = fp.load
|
33
|
+
# status['foo'] = 'bar'
|
34
|
+
# fp.dump(status)
|
35
|
+
# end
|
36
|
+
#
|
37
|
+
# @param [String] path
|
38
|
+
# @param [Block] block
|
39
|
+
def self.open(path, &block)
|
40
|
+
fp = File.open(path, (File::RDONLY | File::CREAT))
|
41
|
+
until fp.flock(File::LOCK_EX | File::LOCK_NB)
|
42
|
+
$logger.info { "Somebody else is locking the storage file #{path.inspect}" }
|
43
|
+
sleep 0.5
|
44
|
+
end
|
45
|
+
begin
|
46
|
+
return yield(StorageFile.new(fp))
|
47
|
+
ensure
|
48
|
+
fp.flock(File::LOCK_UN)
|
49
|
+
fp.close rescue nil
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
# Set storage file with given key, value
|
54
|
+
#
|
55
|
+
# StorageFile.set($setting.status_file, 'foo', 'bar') # like h['foo'] = 'bar'
|
56
|
+
# StorageFile.set($setting.status_file, ['a','b'], 'bar') # like h['a']['b'] = 'bar'
|
57
|
+
#
|
58
|
+
# @param [String] path
|
59
|
+
# @param [Object] key
|
60
|
+
# @param [Object] val
|
61
|
+
def self.set(path, key, val)
|
62
|
+
keys = Array(key)
|
63
|
+
open(path) do |fp|
|
64
|
+
params = fp.load
|
65
|
+
HashUtil.setdig(params, keys, val)
|
66
|
+
fp.dump(params)
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
# Set key to hold val if key does not exist
|
71
|
+
#
|
72
|
+
# StorageFile.setnx($setting.status_file, 'foo', 'bar') # like h['foo'] = 'bar'
|
73
|
+
# StorageFile.setnx($setting.status_file, ['a','b'], 'bar') # like h['a']['b'] = 'bar'
|
74
|
+
#
|
75
|
+
# @param [String] path
|
76
|
+
# @param [Object] key
|
77
|
+
# @param [Object] val
|
78
|
+
# @return [Boolean] true if set (not exist), false if not set (exists)
|
79
|
+
def self.setnx(path, key, val)
|
80
|
+
keys = Array(key)
|
81
|
+
open(path) do |fp|
|
82
|
+
params = fp.load
|
83
|
+
return false if params.dig(*keys)
|
84
|
+
HashUtil.setdig(params, keys, val)
|
85
|
+
fp.dump(params)
|
86
|
+
return true
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
# Set key to hold val if key does not exist and returns the holded value
|
91
|
+
#
|
92
|
+
# This is a kind of atomic short hand of
|
93
|
+
#
|
94
|
+
# StorageFile.setnx($setting.status_file, 'foo', 'bar')
|
95
|
+
# StorageFile.get($setting.status_file, 'foo')
|
96
|
+
#
|
97
|
+
# @param [String] path
|
98
|
+
# @param [Object] key
|
99
|
+
# @param [Object] val
|
100
|
+
# @return [Object] holded value
|
101
|
+
def self.getsetnx(path, key, val)
|
102
|
+
keys = Array(key)
|
103
|
+
open(path) do |fp|
|
104
|
+
params = fp.load
|
105
|
+
if curr = params.dig(*keys)
|
106
|
+
return curr
|
107
|
+
end
|
108
|
+
HashUtil.setdig(params, keys, val)
|
109
|
+
fp.dump(params)
|
110
|
+
return val
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
114
|
+
# Get value of the given key from storage file
|
115
|
+
#
|
116
|
+
# StorageFile.get($setting.status_file, 'foo') # like h['foo'] = 'bar'
|
117
|
+
# StorageFile.get($setting.status_file, ['a','b']) # like hash['a']['b']
|
118
|
+
#
|
119
|
+
# @param [String] path
|
120
|
+
# @param [Object] key
|
121
|
+
def self.get(path, key)
|
122
|
+
keys = Array(key)
|
123
|
+
open(path) {|fp| fp.load.dig(*keys) }
|
124
|
+
end
|
125
|
+
|
126
|
+
# Load storage file
|
127
|
+
#
|
128
|
+
# @return [Hash]
|
129
|
+
def load
|
130
|
+
if !(content = @fp.read).empty?
|
131
|
+
YAML.load(content) # all keys must be symbols
|
132
|
+
else
|
133
|
+
{}
|
134
|
+
end
|
135
|
+
end
|
136
|
+
|
137
|
+
# Dump to storage file
|
138
|
+
#
|
139
|
+
# @param [Hash] hash
|
140
|
+
def dump(hash)
|
141
|
+
File.write(@fp.path, YAML.dump(hash))
|
142
|
+
end
|
143
|
+
end
|
144
|
+
end
|
@@ -0,0 +1,80 @@
|
|
1
|
+
module Triglav::Agent
|
2
|
+
# A timer utility to run serverengine worker in a time interval
|
3
|
+
#
|
4
|
+
# module Triglav::Agent
|
5
|
+
# module Worker
|
6
|
+
# def initialize
|
7
|
+
# @interval = 60.0 # sec
|
8
|
+
# end
|
9
|
+
#
|
10
|
+
# def run
|
11
|
+
# @timer = Timer.new
|
12
|
+
# @stop = false
|
13
|
+
# until @stop
|
14
|
+
# @timer.wait(@interval) { process }
|
15
|
+
# end
|
16
|
+
# end
|
17
|
+
#
|
18
|
+
# def stop
|
19
|
+
# @stop = true
|
20
|
+
# @timer.stop
|
21
|
+
# end
|
22
|
+
# end
|
23
|
+
# end
|
24
|
+
class Timer
|
25
|
+
def initialize
|
26
|
+
@r, @w = IO.pipe
|
27
|
+
start
|
28
|
+
end
|
29
|
+
|
30
|
+
def wait(sec, &block)
|
31
|
+
return if @stop
|
32
|
+
started = Time.now
|
33
|
+
yield
|
34
|
+
elapsed = Time.now - started
|
35
|
+
if (timeout = (sec - elapsed).to_f) > 0
|
36
|
+
begin
|
37
|
+
IO.select([@r], [], [], timeout)
|
38
|
+
rescue IOError, Errno::EBADF
|
39
|
+
# these error may occur if @r is closed during IO.select. Ignore it
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
def start
|
45
|
+
@stop = false
|
46
|
+
end
|
47
|
+
|
48
|
+
def stop
|
49
|
+
@stop = true
|
50
|
+
signal
|
51
|
+
end
|
52
|
+
|
53
|
+
private
|
54
|
+
|
55
|
+
def signal
|
56
|
+
@w.puts ' '
|
57
|
+
end
|
58
|
+
|
59
|
+
# # Hmm, Ctrl-C breaks condvar.wait before calling #stop unexpectedly
|
60
|
+
# attr_reader :condvar, :mutex
|
61
|
+
#
|
62
|
+
# def initialize
|
63
|
+
# @condvar = ConditionVariable.new
|
64
|
+
# @mutex = Mutex.new
|
65
|
+
# end
|
66
|
+
#
|
67
|
+
# def wait(sec, &block)
|
68
|
+
# started = Time.now
|
69
|
+
# @mutex.synchronize do
|
70
|
+
# yield
|
71
|
+
# elapsed = (Time.now - started).to_f
|
72
|
+
# @condvar.wait(@mutex, sec - elapsed)
|
73
|
+
# end
|
74
|
+
# end
|
75
|
+
#
|
76
|
+
# def signal
|
77
|
+
# @condvar.signal
|
78
|
+
# end
|
79
|
+
end
|
80
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
module Triglav
|
2
|
+
module Agent
|
3
|
+
end
|
4
|
+
end
|
5
|
+
|
6
|
+
require 'triglav/agent/api_client'
|
7
|
+
require 'triglav/agent/configuration'
|
8
|
+
require 'triglav/agent/error'
|
9
|
+
require 'triglav/agent/hash_util'
|
10
|
+
require 'triglav/agent/logger'
|
11
|
+
require 'triglav/agent/storage_file'
|
12
|
+
require 'triglav/agent/timer'
|
13
|
+
require 'triglav/agent/version'
|
14
|
+
|
15
|
+
require 'triglav/agent/base/cli'
|
16
|
+
require 'triglav/agent/base/setting'
|
17
|
+
require 'triglav/agent/base/worker'
|
18
|
+
require 'triglav/agent/base/processor'
|
19
|
+
require 'triglav/agent/base/connection' # just a skelton
|
20
|
+
require 'triglav/agent/base/monitor' # just a skelton
|
@@ -0,0 +1 @@
|
|
1
|
+
require 'triglav/agent'
|
@@ -0,0 +1,33 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'triglav/agent/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "triglav-agent"
|
8
|
+
spec.version = Triglav::Agent::VERSION
|
9
|
+
spec.authors = ["Triglav Team"]
|
10
|
+
spec.email = ["triglav_admin_my@dena.jp"]
|
11
|
+
|
12
|
+
spec.summary = %q{Framework of Triglav Agent in Ruby.}
|
13
|
+
spec.description = %q{Framework of Triglav Agent in Ruby.}
|
14
|
+
spec.homepage = "https://github.com/triglav-dataflow/triglav-agent-framework-ruby"
|
15
|
+
spec.license = "MIT"
|
16
|
+
|
17
|
+
spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
|
18
|
+
spec.bindir = "exe"
|
19
|
+
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
20
|
+
spec.require_paths = ["lib"]
|
21
|
+
|
22
|
+
spec.add_dependency "serverengine"
|
23
|
+
spec.add_dependency "dotenv"
|
24
|
+
spec.add_dependency "triglav_client"
|
25
|
+
spec.add_dependency "parallel"
|
26
|
+
spec.add_dependency "connection_pool"
|
27
|
+
|
28
|
+
spec.add_development_dependency "bundler", "~> 1.11"
|
29
|
+
spec.add_development_dependency "rake", "~> 10.0"
|
30
|
+
spec.add_development_dependency "test-unit"
|
31
|
+
spec.add_development_dependency "test-unit-rr"
|
32
|
+
spec.add_development_dependency "yard"
|
33
|
+
end
|