triglav-agent 1.0.0.pre1
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 +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
|