fiksu-af 1.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +24 -0
- data/.rspec +2 -0
- data/.travis.yml +14 -0
- data/Gemfile +22 -0
- data/LICENSE +30 -0
- data/README.md +175 -0
- data/Rakefile +42 -0
- data/examples/af_script_with_options.rb +73 -0
- data/examples/af_side_component.rb +16 -0
- data/examples/my_application.rb +8 -0
- data/fiksu-af.gemspec +27 -0
- data/lib/fiksu-af/application/component.rb +95 -0
- data/lib/fiksu-af/application.rb +361 -0
- data/lib/fiksu-af/deprecated.rb +15 -0
- data/lib/fiksu-af/get_options.rb +68 -0
- data/lib/fiksu-af/logging/configurator.rb +152 -0
- data/lib/fiksu-af/logging.rb +13 -0
- data/lib/fiksu-af/option_parser/columnizer.rb +36 -0
- data/lib/fiksu-af/option_parser/dsl.rb +290 -0
- data/lib/fiksu-af/option_parser/get_options.rb +65 -0
- data/lib/fiksu-af/option_parser/helper.rb +80 -0
- data/lib/fiksu-af/option_parser/instance_variable_setter.rb +117 -0
- data/lib/fiksu-af/option_parser/interface.rb +63 -0
- data/lib/fiksu-af/option_parser/option.rb +40 -0
- data/lib/fiksu-af/option_parser/option_check.rb +66 -0
- data/lib/fiksu-af/option_parser/option_finder.rb +82 -0
- data/lib/fiksu-af/option_parser/option_group.rb +37 -0
- data/lib/fiksu-af/option_parser/option_select.rb +68 -0
- data/lib/fiksu-af/option_parser/option_store.rb +89 -0
- data/lib/fiksu-af/option_parser/option_type.rb +59 -0
- data/lib/fiksu-af/option_parser.rb +145 -0
- data/lib/fiksu-af/q_thread/base.rb +20 -0
- data/lib/fiksu-af/q_thread/interface.rb +23 -0
- data/lib/fiksu-af/q_thread/message.rb +14 -0
- data/lib/fiksu-af/q_thread/message_handler.rb +30 -0
- data/lib/fiksu-af/tcp_command/client.rb +49 -0
- data/lib/fiksu-af/tcp_command/server.rb +119 -0
- data/lib/fiksu-af/thread_pool.rb +102 -0
- data/lib/fiksu-af/version.rb +4 -0
- data/lib/fiksu-af.rb +12 -0
- data/logging/af.yml +32 -0
- data/spec/dummy/.rspec +1 -0
- data/spec/dummy/README.rdoc +261 -0
- data/spec/dummy/Rakefile +7 -0
- data/spec/dummy/app/assets/javascripts/application.js +15 -0
- data/spec/dummy/app/assets/stylesheets/application.css +13 -0
- data/spec/dummy/app/controllers/application_controller.rb +3 -0
- data/spec/dummy/app/helpers/application_helper.rb +2 -0
- data/spec/dummy/app/views/layouts/application.html.erb +14 -0
- data/spec/dummy/config/application.rb +59 -0
- data/spec/dummy/config/boot.rb +10 -0
- data/spec/dummy/config/database-sample.yml +32 -0
- data/spec/dummy/config/environment.rb +5 -0
- data/spec/dummy/config/environments/development.rb +31 -0
- data/spec/dummy/config/environments/production.rb +67 -0
- data/spec/dummy/config/environments/test.rb +35 -0
- data/spec/dummy/config/initializers/backtrace_silencers.rb +7 -0
- data/spec/dummy/config/initializers/inflections.rb +15 -0
- data/spec/dummy/config/initializers/mime_types.rb +5 -0
- data/spec/dummy/config/initializers/secret_token.rb +7 -0
- data/spec/dummy/config/initializers/session_store.rb +8 -0
- data/spec/dummy/config/initializers/wrap_parameters.rb +14 -0
- data/spec/dummy/config/locales/en.yml +5 -0
- data/spec/dummy/config/routes.rb +58 -0
- data/spec/dummy/config.ru +4 -0
- data/spec/dummy/public/404.html +26 -0
- data/spec/dummy/public/422.html +26 -0
- data/spec/dummy/public/500.html +25 -0
- data/spec/dummy/public/favicon.ico +0 -0
- data/spec/dummy/script/rails +6 -0
- data/spec/dummy/spec/spec_helper.rb +32 -0
- data/spec/lib/af/application_spec.rb +60 -0
- data/spec/lib/af/get_options_spec.rb +24 -0
- data/spec/lib/af/option_parser/option_check_spec.rb +50 -0
- data/spec/lib/af/option_parser/option_select_spec.rb +51 -0
- data/spec/spec_helper.rb +33 -0
- metadata +288 -0
data/.gitignore
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
# See http://help.github.com/ignore-files/ for more about ignoring files.
|
2
|
+
#
|
3
|
+
# If you find yourself ignoring temporary files generated by your text editor
|
4
|
+
# or operating system, you probably want to add a global ignore instead:
|
5
|
+
# git config --global core.excludesfile ~/.gitignore_global
|
6
|
+
|
7
|
+
# Ignore bundler config
|
8
|
+
/.bundle
|
9
|
+
|
10
|
+
# Ignore the default SQLite database.
|
11
|
+
/db/*.sqlite3
|
12
|
+
|
13
|
+
# Ignore all logfiles and tempfiles.
|
14
|
+
/log/*.log
|
15
|
+
/tmp
|
16
|
+
.idea/*
|
17
|
+
database.yml
|
18
|
+
/log/*.pid
|
19
|
+
spec/dummy/db/*.sqlite3
|
20
|
+
spec/dummy/log/*.log
|
21
|
+
spec/dummy/tmp/
|
22
|
+
spec/dummy/.sass-cache
|
23
|
+
spec/dummy/config/database.yml
|
24
|
+
spec/dummy/db/schema.rb
|
data/.rspec
ADDED
data/.travis.yml
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
language: ruby
|
2
|
+
rvm:
|
3
|
+
- 1.9.3
|
4
|
+
bundler_args: --without staging development deploy
|
5
|
+
before_install:
|
6
|
+
before_script: cp spec/dummy/config/database-sample.yml spec/dummy/config/database.yml; cd spec/dummy; bundle exec rake db:create;
|
7
|
+
script: rspec spec
|
8
|
+
branches:
|
9
|
+
only:
|
10
|
+
- master
|
11
|
+
notifications:
|
12
|
+
hipchat: 5d580c1746812c946d9cb0b58f7a66@FMA
|
13
|
+
email:
|
14
|
+
- dev-fma@fiksu.com
|
data/Gemfile
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
source "http://rubygems.org"
|
2
|
+
|
3
|
+
# Declare your gem's dependencies in partitioned.gemspec.
|
4
|
+
# Bundler will treat runtime dependencies like base dependencies, and
|
5
|
+
# development dependencies will be added by default to the :development group.
|
6
|
+
gemspec
|
7
|
+
|
8
|
+
gem 'pg_application_name', '>= 1.0.0'
|
9
|
+
gem 'pg_advisory_locker', '>= 0.9.0'
|
10
|
+
gem 'log4r', '1.1.10'
|
11
|
+
gem 'reasonable_log4r', '>= 0.9.0'
|
12
|
+
gem 'uuid', '2.3.5'
|
13
|
+
|
14
|
+
gem 'awesome_print'
|
15
|
+
|
16
|
+
# Declare any dependencies that are still in development here instead of in
|
17
|
+
# your gemspec. These might include edge Rails or gems from your path or
|
18
|
+
# Git. Remember to move these dependencies to your gemspec before releasing
|
19
|
+
# your gem to rubygems.org.
|
20
|
+
|
21
|
+
# To use debugger
|
22
|
+
# gem 'ruby-debug'
|
data/LICENSE
ADDED
@@ -0,0 +1,30 @@
|
|
1
|
+
Copyright (c) 2010-2013, Fiksu, Inc.
|
2
|
+
All rights reserved.
|
3
|
+
|
4
|
+
Redistribution and use in source and binary forms, with or without
|
5
|
+
modification, are permitted provided that the following conditions are
|
6
|
+
met:
|
7
|
+
|
8
|
+
o Redistributions of source code must retain the above copyright
|
9
|
+
notice, this list of conditions and the following disclaimer.
|
10
|
+
|
11
|
+
o Redistributions in binary form must reproduce the above copyright
|
12
|
+
notice, this list of conditions and the following disclaimer in the
|
13
|
+
documentation and/or other materials provided with the
|
14
|
+
distribution.
|
15
|
+
|
16
|
+
o Fiksu, Inc. nor the names of its contributors may be used to
|
17
|
+
endorse or promote products derived from this software without
|
18
|
+
specific prior written permission.
|
19
|
+
|
20
|
+
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
21
|
+
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
22
|
+
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
23
|
+
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
24
|
+
HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
25
|
+
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
26
|
+
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
27
|
+
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
28
|
+
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
29
|
+
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
30
|
+
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
data/README.md
ADDED
@@ -0,0 +1,175 @@
|
|
1
|
+
# Af - an application framework
|
2
|
+
|
3
|
+
gem 'fiksu-af'
|
4
|
+
|
5
|
+
This application framework supports:
|
6
|
+
|
7
|
+
* an Application class with supporting infrastruction
|
8
|
+
* command line options integrated into instance (and class) variables
|
9
|
+
* logging via log4r with support for papertrail
|
10
|
+
* postgres advisory locking via pg_advisor_locker gem
|
11
|
+
* postgres database connection updates via pg_application_name gem
|
12
|
+
* threads and message passing
|
13
|
+
* application components adding loggers and command line options
|
14
|
+
|
15
|
+
## Application class
|
16
|
+
|
17
|
+
The class ::Af::Application provides a basic interface to the start-up
|
18
|
+
and management of Ruby on Rails scripts.
|
19
|
+
|
20
|
+
A simple example of an application which logs its startup and exits
|
21
|
+
is:
|
22
|
+
|
23
|
+
```
|
24
|
+
class MyApplication < ::Af::Application
|
25
|
+
opt :word, "the word", :short => :w, :default => "bird"
|
26
|
+
|
27
|
+
def work
|
28
|
+
logger.info "Started up: #{@word} is the word"
|
29
|
+
exit 0
|
30
|
+
end
|
31
|
+
end
|
32
|
+
```
|
33
|
+
|
34
|
+
Class-method "opt" specifies command line parameter(s) whose arguments
|
35
|
+
are stored in instance variables. MyApplication specifies a single
|
36
|
+
parameter "--word" with a short alias "-w" that accepts a string
|
37
|
+
argument (whose default is "bird", so we know it should be a string).
|
38
|
+
The parameters value will be stored in class instance variable: @word.
|
39
|
+
More information on command line option glue is provided in the
|
40
|
+
Command Line Options section.
|
41
|
+
|
42
|
+
The method "logger" is available to ::Af::Application to create and
|
43
|
+
fetch log4r loggers. In this case, we use the basic application
|
44
|
+
logger (named "MyApplication") and logs an INFO level message. More
|
45
|
+
information on the glue ::Af::Application provides with Log4r is
|
46
|
+
in the logging section below.
|
47
|
+
|
48
|
+
This application would be run from the command line as:
|
49
|
+
|
50
|
+
```
|
51
|
+
$ script/rails runner MyApplication.run --word grease
|
52
|
+
```
|
53
|
+
|
54
|
+
The class method #run provides start-up glue for applications, parsing
|
55
|
+
command line options, environment variables and configuration files.
|
56
|
+
The instance method #work is where application codes start their work.
|
57
|
+
|
58
|
+
## Command Line Options
|
59
|
+
|
60
|
+
a more interesting example of options from multiple classes
|
61
|
+
|
62
|
+
```
|
63
|
+
class AfSideComponent
|
64
|
+
include Af::Application::Component
|
65
|
+
|
66
|
+
opt_group :side_component_stuff, "options associated with this side component" do
|
67
|
+
opt :a_side_component_option, :default => "foo"
|
68
|
+
end
|
69
|
+
|
70
|
+
opt :basic_option_from_component, "this is a switch from the side component, in the basic (default) group"
|
71
|
+
|
72
|
+
create_proxy_logger :foo
|
73
|
+
|
74
|
+
def do_something
|
75
|
+
foo_logger.info "doing something @@a_side_component_option='#{@@a_side_component_option}'"
|
76
|
+
foo_logger.info "did something @@basic_option_from_component=#{@@basic_option_from_component.inspect}"
|
77
|
+
end
|
78
|
+
end
|
79
|
+
```
|
80
|
+
|
81
|
+
```
|
82
|
+
class AfScriptWithOptions < ::Af::Application
|
83
|
+
opt_group :singles, "parameters whose types are a single value" do
|
84
|
+
opt :a_switch, "a switch"
|
85
|
+
opt :an_int, "an integer of some sort", :default => 1
|
86
|
+
opt :a_float, "a float of some sort whose default is PI", :default => 3.14
|
87
|
+
opt :a_string, "a string of some sort", :type => :string
|
88
|
+
opt :a_uri, "some uri", :type => :uri
|
89
|
+
opt :a_date, "a date", :type => :date
|
90
|
+
opt :a_time, "a time", :type => :time
|
91
|
+
opt :a_datetime, "a datetime", :type => :datetime
|
92
|
+
opt :a_choice, "a choice", :argument_note => "COLOR", :choices => [:red, :blue, :green, :yellow, :white, :black, :orange]
|
93
|
+
end
|
94
|
+
|
95
|
+
# there is already an advanced option group -- it is set to hidden by default
|
96
|
+
opt_group :advanced, "advanced parameters", :hidden => false do
|
97
|
+
opt :a_small_integer, "another integer", :default => 10, :argument_note => "[1 >= INTEGER <= 10]" do |argument,option|
|
98
|
+
argument = argument.to_i
|
99
|
+
if (argument < 1 || argument > 10)
|
100
|
+
opt_error "ERROR: #{option.long_name}: value must be between 1 and 10 (inclusive)"
|
101
|
+
end
|
102
|
+
argument
|
103
|
+
end
|
104
|
+
opt :a_constrained_number, "a number which is not an integer", :requirement => :required, :argument_note => "NON-INTEGER" do |argument,option|
|
105
|
+
i_argument = argument.to_i
|
106
|
+
f_argument = argument.to_f
|
107
|
+
if (i_argument == f_argument)
|
108
|
+
opt_error "ERROR: #{option.long_name}: value must not be an integer"
|
109
|
+
end
|
110
|
+
f_argument
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
114
|
+
opt_group :collections, "parameters whose types are collections" do
|
115
|
+
opt :a_hash, "a key value pair", :type => :hash
|
116
|
+
opt :some_ints, "a list of integer", :type => :ints
|
117
|
+
opt :some_integers, "a list of integer", :type => :integers
|
118
|
+
opt :some_floats, "a list of floats", :type => :floats
|
119
|
+
opt :some_numbers, "a list of numbers", :type => :numbers
|
120
|
+
opt :some_strings, "a list of strings", :type => :strings
|
121
|
+
opt :some_uris, "a list of uris", :type => :uris
|
122
|
+
opt :some_dates, "a list of dates", :type => :dates
|
123
|
+
opt :some_times, "a list of times", :type => :times
|
124
|
+
opt :some_datetimes, "a list of datetimes", :type => :datetimes
|
125
|
+
opt :some_choices, "a list of choices", :choices => [:foo, :bar, :baz, :beltch]
|
126
|
+
end
|
127
|
+
|
128
|
+
opt_group :blank, "a blank group that won't be seen"
|
129
|
+
|
130
|
+
opt :word, "the word to print", :default => :foo, :choices => [:foo, :bar, :baz, :beltch]
|
131
|
+
opt :words, "the words to print", :default => [:foo], :choices => [:foo, :bar, :baz, :beltch]
|
132
|
+
opt :numbers, "the number lists", :default => [1,2,3]
|
133
|
+
opt :switcher, "this is a switch"
|
134
|
+
|
135
|
+
def af_opt_class_path
|
136
|
+
[AfSideComponent] + super
|
137
|
+
end
|
138
|
+
|
139
|
+
def logger
|
140
|
+
super('Process::T')
|
141
|
+
end
|
142
|
+
|
143
|
+
def work
|
144
|
+
logger.info "switcher: #{switcher.inspect}"
|
145
|
+
logger.info "WORK STARTED: #{@word}"
|
146
|
+
logger.info @words.inspect
|
147
|
+
logger.info "NUMBERS: #{@numbers.inspect}"
|
148
|
+
|
149
|
+
AfSideComponent.new.do_something
|
150
|
+
|
151
|
+
logger.info "WORK COMPLETED: #{@word}"
|
152
|
+
end
|
153
|
+
end
|
154
|
+
|
155
|
+
```
|
156
|
+
|
157
|
+
## Logging with Log4r
|
158
|
+
|
159
|
+
Some changes to Log4r:
|
160
|
+
|
161
|
+
* root loggers are no longer null loggers -- you can add outputters to them
|
162
|
+
* the global logger is used to set a global log level (root is no longer used for this)
|
163
|
+
* yaml configurator has been updated to handle new root logger semantics
|
164
|
+
* yaml configurator has been updated to accept a set of files AND sections (default section: log4r_config)
|
165
|
+
|
166
|
+
What this really means is that you can set up one outputter in the root
|
167
|
+
logger to manage the default logging behavior.
|
168
|
+
|
169
|
+
## Thread Pool
|
170
|
+
|
171
|
+
*TODO*
|
172
|
+
|
173
|
+
## TCP Message Passing
|
174
|
+
|
175
|
+
*TODO*
|
data/Rakefile
ADDED
@@ -0,0 +1,42 @@
|
|
1
|
+
#!/usr/bin/env rake
|
2
|
+
begin
|
3
|
+
require 'bundler/setup'
|
4
|
+
rescue LoadError
|
5
|
+
puts 'You must `gem install bundler` and `bundle install` to run rake tasks'
|
6
|
+
end
|
7
|
+
|
8
|
+
begin
|
9
|
+
require 'rdoc/task'
|
10
|
+
rescue LoadError
|
11
|
+
require 'rdoc/rdoc'
|
12
|
+
require 'rake/rdoctask'
|
13
|
+
RDoc::Task = Rake::RDocTask
|
14
|
+
end
|
15
|
+
|
16
|
+
RDoc::Task.new(:rdoc) do |rdoc|
|
17
|
+
rdoc.rdoc_dir = 'rdoc'
|
18
|
+
rdoc.title = 'Af'
|
19
|
+
rdoc.options << '--line-numbers'
|
20
|
+
rdoc.rdoc_files.include('README')
|
21
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
22
|
+
end
|
23
|
+
|
24
|
+
# Eventually we will want a test application to use this Engine
|
25
|
+
# to see if it works!
|
26
|
+
|
27
|
+
APP_RAKEFILE = File.expand_path("../spec/dummy/Rakefile", __FILE__)
|
28
|
+
|
29
|
+
load 'rails/tasks/engine.rake'
|
30
|
+
|
31
|
+
Bundler::GemHelper.install_tasks
|
32
|
+
|
33
|
+
require 'rake'
|
34
|
+
require 'rspec/core'
|
35
|
+
require 'rspec/core/rake_task'
|
36
|
+
|
37
|
+
RSpec::Core::RakeTask.new(:spec) do |spec|
|
38
|
+
spec.pattern = FileList['spec/**/*_spec.rb']
|
39
|
+
end
|
40
|
+
|
41
|
+
desc 'Default: Run all specs.'
|
42
|
+
task :default => :spec
|
@@ -0,0 +1,73 @@
|
|
1
|
+
class AfScriptWithOptions < ::Af::Application
|
2
|
+
opt_group :singles, "parameters whose types are a single value" do
|
3
|
+
opt :a_switch, "a switch"
|
4
|
+
opt :an_int, "an integer of some sort", :default => 1
|
5
|
+
opt :a_float, "a float of some sort whose default is PI", :default => 3.14
|
6
|
+
opt :a_string, "a string of some sort", :type => :string
|
7
|
+
opt :a_uri, "some uri", :type => :uri
|
8
|
+
opt :a_date, "a date", :type => :date
|
9
|
+
opt :a_time, "a time", :type => :time
|
10
|
+
opt :a_datetime, "a datetime", :type => :datetime
|
11
|
+
opt :a_choice, "a choice", :argument_note => "COLOR", :choices => [:red, :blue, :green, :yellow, :white, :black, :orange]
|
12
|
+
end
|
13
|
+
|
14
|
+
# there is already an advanced option group -- it is set to hidden by default
|
15
|
+
opt_group :advanced, "advanced parameters", :hidden => false do
|
16
|
+
opt :a_small_integer, "another integer", :default => 10, :argument_note => "[1 >= INTEGER <= 10]" do |argument,option|
|
17
|
+
argument = argument.to_i
|
18
|
+
if (argument < 1 || argument > 10)
|
19
|
+
opt_error "ERROR: #{option.long_name}: value must be between 1 and 10 (inclusive)"
|
20
|
+
end
|
21
|
+
argument
|
22
|
+
end
|
23
|
+
opt :a_constrained_number, "a number which is not an integer", :requirement => :required, :argument_note => "NON-INTEGER" do |argument,option|
|
24
|
+
i_argument = argument.to_i
|
25
|
+
f_argument = argument.to_f
|
26
|
+
if (i_argument == f_argument)
|
27
|
+
opt_error "ERROR: #{option.long_name}: value must not be an integer"
|
28
|
+
end
|
29
|
+
f_argument
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
opt_group :collections, "parameters whose types are collections" do
|
34
|
+
opt :a_hash, "a key value pair", :type => :hash
|
35
|
+
opt :some_ints, "a list of integer", :type => :ints
|
36
|
+
opt :some_integers, "a list of integer", :type => :integers
|
37
|
+
opt :some_floats, "a list of floats", :type => :floats
|
38
|
+
opt :some_numbers, "a list of numbers", :type => :numbers
|
39
|
+
opt :some_strings, "a list of strings", :type => :strings
|
40
|
+
opt :some_uris, "a list of uris", :type => :uris
|
41
|
+
opt :some_dates, "a list of dates", :type => :dates
|
42
|
+
opt :some_times, "a list of times", :type => :times
|
43
|
+
opt :some_datetimes, "a list of datetimes", :type => :datetimes
|
44
|
+
opt :some_choices, "a list of choices", :choices => [:foo, :bar, :baz, :beltch]
|
45
|
+
end
|
46
|
+
|
47
|
+
opt_group :blank, "a blank group that won't be seen"
|
48
|
+
|
49
|
+
opt :word, "the word to print", :default => :foo, :choices => [:foo, :bar, :baz, :beltch]
|
50
|
+
opt :words, "the words to print", :default => [:foo], :choices => [:foo, :bar, :baz, :beltch]
|
51
|
+
opt :numbers, "the number lists", :default => [1,2,3]
|
52
|
+
opt :switcher, "this is a switch"
|
53
|
+
|
54
|
+
def af_opt_class_path
|
55
|
+
[AfSideComponent] + super
|
56
|
+
end
|
57
|
+
|
58
|
+
def logger
|
59
|
+
super('Process::T')
|
60
|
+
end
|
61
|
+
|
62
|
+
def work
|
63
|
+
logger.info "switcher: #{switcher.inspect}"
|
64
|
+
logger.info "WORK STARTED: #{@word}"
|
65
|
+
logger.info @words.inspect
|
66
|
+
logger.info "NUMBERS: #{@numbers.inspect}"
|
67
|
+
|
68
|
+
AfSideComponent.new.do_something
|
69
|
+
|
70
|
+
logger.info "WORK COMPLETED: #{@word}"
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
@@ -0,0 +1,16 @@
|
|
1
|
+
class AfSideComponent
|
2
|
+
include Af::Application::Component
|
3
|
+
|
4
|
+
opt_group :side_component_stuff, "options associated with this side component" do
|
5
|
+
opt :a_side_component_option, :default => "foo"
|
6
|
+
end
|
7
|
+
|
8
|
+
opt :basic_option_from_component, "this is a switch from the side component, in the basic (default) group"
|
9
|
+
|
10
|
+
create_proxy_logger :foo
|
11
|
+
|
12
|
+
def do_something
|
13
|
+
foo_logger.info "doing something @@a_side_component_option='#{@@a_side_component_option}'"
|
14
|
+
foo_logger.info "did something @@basic_option_from_component=#{@@basic_option_from_component.inspect}"
|
15
|
+
end
|
16
|
+
end
|
data/fiksu-af.gemspec
ADDED
@@ -0,0 +1,27 @@
|
|
1
|
+
$LOAD_PATH.push File.expand_path("../lib", __FILE__)
|
2
|
+
|
3
|
+
# Maintain your gem's version:
|
4
|
+
require "fiksu-af/version"
|
5
|
+
|
6
|
+
Gem::Specification.new do |s|
|
7
|
+
s.name = 'fiksu-af'
|
8
|
+
s.version = Af::VERSION
|
9
|
+
s.license = 'New BSD License'
|
10
|
+
s.date = '2013-10-11'
|
11
|
+
s.summary = "An application framework for ruby on rails based scripts."
|
12
|
+
s.description = "Af groups together gems and provides some glue and helper classes to easily creating applications in a ruby on rails environment."
|
13
|
+
s.authors = ["Keith Gabryelski", "Leonardo Meira"]
|
14
|
+
s.email = ['keith@fiksu.com', 'lmeira@fiksu.com']
|
15
|
+
s.files = `git ls-files`.split("\n")
|
16
|
+
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
17
|
+
s.require_path = 'lib'
|
18
|
+
s.homepage = 'http://github.com/fiksu/af'
|
19
|
+
s.add_dependency 'pg_application_name', '>= 1.0.0'
|
20
|
+
s.add_dependency 'pg_advisory_locker', '>= 0.9.0'
|
21
|
+
s.add_dependency 'log4r', '1.1.10'
|
22
|
+
s.add_dependency "log4r_remote_syslog_outputter", "0.0.1"
|
23
|
+
s.add_dependency 'reasonable_log4r', '>= 0.9.0'
|
24
|
+
s.add_dependency 'uuid'
|
25
|
+
s.add_dependency "rails", '>= 3.0.0'
|
26
|
+
s.add_dependency 'rspec-rails', '>=2.12.0'
|
27
|
+
end
|
@@ -0,0 +1,95 @@
|
|
1
|
+
module Af
|
2
|
+
class Application
|
3
|
+
# Proxy's are used by dependant classes to interact with the Application framework
|
4
|
+
#
|
5
|
+
# consider a model that wishes to use the logging functionality of Af:
|
6
|
+
#
|
7
|
+
# class Foo < ActiveRecord::Base
|
8
|
+
# include ::Af::Application::Component
|
9
|
+
#
|
10
|
+
# after_create :do_something_after_create
|
11
|
+
#
|
12
|
+
# create_proxy_logger :foo
|
13
|
+
#
|
14
|
+
# private
|
15
|
+
# def do_something_after_create
|
16
|
+
# foo_logger.info "created: #{self.inspect}"
|
17
|
+
# end
|
18
|
+
# end
|
19
|
+
#
|
20
|
+
module Component
|
21
|
+
def self.included(base)
|
22
|
+
base.extend(ClassMethods)
|
23
|
+
base.send(:include, ::Af::Logging)
|
24
|
+
end
|
25
|
+
|
26
|
+
module ClassMethods
|
27
|
+
def create_proxy_logger(prefix = "", logger_name = self.name, create_class_method = false)
|
28
|
+
prefix = prefix.to_s
|
29
|
+
if !prefix.blank? && prefix[-1] != '_'
|
30
|
+
prefix = "#{prefix}_"
|
31
|
+
end
|
32
|
+
|
33
|
+
method_name = "#{prefix}logger"
|
34
|
+
class_eval <<-CLASS_EVAL
|
35
|
+
def #{create_class_method ? 'self.' : ''}#{method_name}
|
36
|
+
return Log4r::Logger['#{logger_name}'] || Log4r::Logger.new('#{logger_name}')
|
37
|
+
end
|
38
|
+
CLASS_EVAL
|
39
|
+
end
|
40
|
+
|
41
|
+
def create_class_proxy_logger(prefix = "", logger_name = self.name)
|
42
|
+
create_proxy_logger(prefix, logger_name, true)
|
43
|
+
end
|
44
|
+
|
45
|
+
def opt(long_name, *extra_stuff, &b)
|
46
|
+
add_target_container(extra_stuff)
|
47
|
+
return ::Af::Application.opt(long_name, *extra_stuff, &b)
|
48
|
+
end
|
49
|
+
|
50
|
+
def opt_group(group_name, *extra_stuff, &b)
|
51
|
+
add_target_container(extra_stuff)
|
52
|
+
return ::Af::Application.opt_group(group_name, *extra_stuff, &b)
|
53
|
+
end
|
54
|
+
|
55
|
+
def opt_check(var_name, *extra_stuff, &b)
|
56
|
+
add_target_container(extra_stuff)
|
57
|
+
return ::Af::Application.opt_check(var_name, *extra_stuff, &b)
|
58
|
+
end
|
59
|
+
|
60
|
+
def opt_select(var_name, *extra_stuff, &b)
|
61
|
+
add_target_container(extra_stuff)
|
62
|
+
return ::Af::Application.opt_select(var_name, *extra_stuff, &b)
|
63
|
+
end
|
64
|
+
|
65
|
+
def add_target_container(extra_stuff)
|
66
|
+
extra_hash = {}
|
67
|
+
if extra_stuff[-1].is_a? Hash
|
68
|
+
extra_hash = extra_stuff.pop
|
69
|
+
end
|
70
|
+
extra_stuff.push extra_hash.merge({ target_container: self })
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
def af_logger(logger_name = (af_name || "Unknown"))
|
75
|
+
return ::Af::Application.singleton.logger(logger_name)
|
76
|
+
end
|
77
|
+
|
78
|
+
def af_name
|
79
|
+
return ::Af::Application.singleton.try(:af_name)
|
80
|
+
end
|
81
|
+
|
82
|
+
def periodic_application_checkpoint
|
83
|
+
af_application.try(:periodic_application_checkpoint)
|
84
|
+
end
|
85
|
+
|
86
|
+
def protect_from_signals
|
87
|
+
af_application.try(:protect_from_signals)
|
88
|
+
end
|
89
|
+
|
90
|
+
def af_application
|
91
|
+
return ::Af::Application.singleton
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|
95
|
+
end
|