archfiend 0.1.0
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/.github/PULL_REQUEST_TEMPLATE.md +18 -0
- data/.gitignore +12 -0
- data/.rspec +4 -0
- data/.rubocop.yml +323 -0
- data/.travis.yml +11 -0
- data/CHANGES.md +12 -0
- data/CODE_OF_CONDUCT.md +74 -0
- data/Gemfile +7 -0
- data/Gemfile.lock +122 -0
- data/LICENSE.txt +21 -0
- data/README.md +114 -0
- data/ROADMAP.md +11 -0
- data/Rakefile +6 -0
- data/archfiend.gemspec +35 -0
- data/bin/console +14 -0
- data/bin/setup +8 -0
- data/exe/archfiend +4 -0
- data/lib/archfiend.rb +18 -0
- data/lib/archfiend/application.rb +132 -0
- data/lib/archfiend/cli.rb +9 -0
- data/lib/archfiend/generators/daemon.rb +144 -0
- data/lib/archfiend/generators/daemon/templates/.rspec +4 -0
- data/lib/archfiend/generators/daemon/templates/.rubocop.yml +323 -0
- data/lib/archfiend/generators/daemon/templates/Gemfile.tt +32 -0
- data/lib/archfiend/generators/daemon/templates/README.md.tt +23 -0
- data/lib/archfiend/generators/daemon/templates/Rakefile.tt +13 -0
- data/lib/archfiend/generators/daemon/templates/app/clockwork/clockwork.rb.tt +14 -0
- data/lib/archfiend/generators/daemon/templates/app/models/application_record.rb +3 -0
- data/lib/archfiend/generators/daemon/templates/app/subprocess_loops/foo_subprocess_loop.rb +13 -0
- data/lib/archfiend/generators/daemon/templates/app/thread_loops/bar_thread_loop.rb +8 -0
- data/lib/archfiend/generators/daemon/templates/bin/console +3 -0
- data/lib/archfiend/generators/daemon/templates/bin/start.tt +6 -0
- data/lib/archfiend/generators/daemon/templates/config/application.rb.tt +27 -0
- data/lib/archfiend/generators/daemon/templates/config/boot.rb.tt +3 -0
- data/lib/archfiend/generators/daemon/templates/config/daemon.rb.tt +18 -0
- data/lib/archfiend/generators/daemon/templates/config/database.yml.example.tt +26 -0
- data/lib/archfiend/generators/daemon/templates/config/environment.rb.tt +4 -0
- data/lib/archfiend/generators/daemon/templates/config/settings.yml.tt +8 -0
- data/lib/archfiend/generators/daemon/templates/config/settings/development.yml.tt +2 -0
- data/lib/archfiend/generators/daemon/templates/config/settings/production.yml.tt +2 -0
- data/lib/archfiend/generators/daemon/templates/config/settings/staging.yml.tt +5 -0
- data/lib/archfiend/generators/daemon/templates/config/settings/test.yml.tt +0 -0
- data/lib/archfiend/generators/daemon/templates/db/migrate/.gitkeep +0 -0
- data/lib/archfiend/generators/daemon/templates/lib/tasks/.gitkeep +0 -0
- data/lib/archfiend/generators/daemon/templates/log/.gitkeep +0 -0
- data/lib/archfiend/generators/daemon/templates/spec/factories/.gitkeep +0 -0
- data/lib/archfiend/generators/daemon/templates/spec/models/.gitkeep +0 -0
- data/lib/archfiend/generators/daemon/templates/spec/spec_helper.rb +43 -0
- data/lib/archfiend/generators/daemon/templates/spec/subprocess_loops/foo_subprocess_loop_spec.rb +5 -0
- data/lib/archfiend/generators/daemon/templates/spec/support/factory_bot.rb +9 -0
- data/lib/archfiend/generators/daemon/templates/spec/support/timecop.rb +9 -0
- data/lib/archfiend/generators/daemon/templates/spec/thread_loops/bar_thread_loop_spec.rb +5 -0
- data/lib/archfiend/generators/daemon/templates/tmp/.gitkeep +0 -0
- data/lib/archfiend/generators/extensions.rb +119 -0
- data/lib/archfiend/generators/options.rb +51 -0
- data/lib/archfiend/generators/utils.rb +37 -0
- data/lib/archfiend/logging.rb +38 -0
- data/lib/archfiend/logging/base_formatter.rb +35 -0
- data/lib/archfiend/logging/default_formatter.rb +12 -0
- data/lib/archfiend/logging/json_formatter.rb +21 -0
- data/lib/archfiend/logging/multi_logger.rb +31 -0
- data/lib/archfiend/shared_loop/runnable.rb +26 -0
- data/lib/archfiend/subprocess_loop.rb +46 -0
- data/lib/archfiend/thread_loop.rb +35 -0
- data/lib/archfiend/version.rb +3 -0
- data/scripts/travis/install +13 -0
- data/scripts/travis/script +43 -0
- metadata +280 -0
data/Gemfile
ADDED
data/Gemfile.lock
ADDED
@@ -0,0 +1,122 @@
|
|
1
|
+
PATH
|
2
|
+
remote: .
|
3
|
+
specs:
|
4
|
+
archfiend (0.1.0)
|
5
|
+
activesupport
|
6
|
+
oj
|
7
|
+
pry
|
8
|
+
thor
|
9
|
+
|
10
|
+
GEM
|
11
|
+
remote: https://rubygems.org/
|
12
|
+
specs:
|
13
|
+
activemodel (5.2.1)
|
14
|
+
activesupport (= 5.2.1)
|
15
|
+
activerecord (5.2.1)
|
16
|
+
activemodel (= 5.2.1)
|
17
|
+
activesupport (= 5.2.1)
|
18
|
+
arel (>= 9.0)
|
19
|
+
activesupport (5.2.1)
|
20
|
+
concurrent-ruby (~> 1.0, >= 1.0.2)
|
21
|
+
i18n (>= 0.7, < 2)
|
22
|
+
minitest (~> 5.1)
|
23
|
+
tzinfo (~> 1.1)
|
24
|
+
arel (9.0.0)
|
25
|
+
ast (2.4.0)
|
26
|
+
coderay (1.1.2)
|
27
|
+
concurrent-ruby (1.0.5)
|
28
|
+
config (1.7.0)
|
29
|
+
activesupport (>= 3.0)
|
30
|
+
deep_merge (~> 1.2.1)
|
31
|
+
dry-validation (>= 0.10.4)
|
32
|
+
deep_merge (1.2.1)
|
33
|
+
diff-lcs (1.3)
|
34
|
+
dry-configurable (0.7.0)
|
35
|
+
concurrent-ruby (~> 1.0)
|
36
|
+
dry-container (0.6.0)
|
37
|
+
concurrent-ruby (~> 1.0)
|
38
|
+
dry-configurable (~> 0.1, >= 0.1.3)
|
39
|
+
dry-core (0.4.7)
|
40
|
+
concurrent-ruby (~> 1.0)
|
41
|
+
dry-equalizer (0.2.1)
|
42
|
+
dry-inflector (0.1.2)
|
43
|
+
dry-logic (0.4.2)
|
44
|
+
dry-container (~> 0.2, >= 0.2.6)
|
45
|
+
dry-core (~> 0.2)
|
46
|
+
dry-equalizer (~> 0.2)
|
47
|
+
dry-types (0.13.2)
|
48
|
+
concurrent-ruby (~> 1.0)
|
49
|
+
dry-container (~> 0.3)
|
50
|
+
dry-core (~> 0.4, >= 0.4.4)
|
51
|
+
dry-equalizer (~> 0.2)
|
52
|
+
dry-inflector (~> 0.1, >= 0.1.2)
|
53
|
+
dry-logic (~> 0.4, >= 0.4.2)
|
54
|
+
dry-validation (0.12.2)
|
55
|
+
concurrent-ruby (~> 1.0)
|
56
|
+
dry-configurable (~> 0.1, >= 0.1.3)
|
57
|
+
dry-core (~> 0.2, >= 0.2.1)
|
58
|
+
dry-equalizer (~> 0.2)
|
59
|
+
dry-logic (~> 0.4, >= 0.4.0)
|
60
|
+
dry-types (~> 0.13.1)
|
61
|
+
i18n (1.1.0)
|
62
|
+
concurrent-ruby (~> 1.0)
|
63
|
+
jaro_winkler (1.5.1)
|
64
|
+
method_source (0.9.0)
|
65
|
+
minitest (5.11.3)
|
66
|
+
oj (3.6.7)
|
67
|
+
parallel (1.12.1)
|
68
|
+
parser (2.5.1.2)
|
69
|
+
ast (~> 2.4.0)
|
70
|
+
pg (0.21.0)
|
71
|
+
powerpack (0.1.2)
|
72
|
+
pry (0.11.3)
|
73
|
+
coderay (~> 1.1.0)
|
74
|
+
method_source (~> 0.9.0)
|
75
|
+
rainbow (3.0.0)
|
76
|
+
rake (10.5.0)
|
77
|
+
rspec (3.8.0)
|
78
|
+
rspec-core (~> 3.8.0)
|
79
|
+
rspec-expectations (~> 3.8.0)
|
80
|
+
rspec-mocks (~> 3.8.0)
|
81
|
+
rspec-core (3.8.0)
|
82
|
+
rspec-support (~> 3.8.0)
|
83
|
+
rspec-expectations (3.8.1)
|
84
|
+
diff-lcs (>= 1.2.0, < 2.0)
|
85
|
+
rspec-support (~> 3.8.0)
|
86
|
+
rspec-mocks (3.8.0)
|
87
|
+
diff-lcs (>= 1.2.0, < 2.0)
|
88
|
+
rspec-support (~> 3.8.0)
|
89
|
+
rspec-support (3.8.0)
|
90
|
+
rubocop (0.58.2)
|
91
|
+
jaro_winkler (~> 1.5.1)
|
92
|
+
parallel (~> 1.10)
|
93
|
+
parser (>= 2.5, != 2.5.1.1)
|
94
|
+
powerpack (~> 0.1)
|
95
|
+
rainbow (>= 2.2.2, < 4.0)
|
96
|
+
ruby-progressbar (~> 1.7)
|
97
|
+
unicode-display_width (~> 1.0, >= 1.0.1)
|
98
|
+
rubocop-rspec (1.29.1)
|
99
|
+
rubocop (>= 0.58.0)
|
100
|
+
ruby-progressbar (1.10.0)
|
101
|
+
thor (0.20.0)
|
102
|
+
thread_safe (0.3.6)
|
103
|
+
tzinfo (1.2.5)
|
104
|
+
thread_safe (~> 0.1)
|
105
|
+
unicode-display_width (1.4.0)
|
106
|
+
|
107
|
+
PLATFORMS
|
108
|
+
ruby
|
109
|
+
|
110
|
+
DEPENDENCIES
|
111
|
+
activerecord
|
112
|
+
archfiend!
|
113
|
+
bundler (~> 1.15)
|
114
|
+
config
|
115
|
+
pg (~> 0.21)
|
116
|
+
rake (~> 10.0)
|
117
|
+
rspec (~> 3.0)
|
118
|
+
rubocop
|
119
|
+
rubocop-rspec
|
120
|
+
|
121
|
+
BUNDLED WITH
|
122
|
+
1.16.4
|
data/LICENSE.txt
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
The MIT License (MIT)
|
2
|
+
|
3
|
+
Copyright (c) 2018 Toptal, Maciek Dubiński
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
7
|
+
in the Software without restriction, including without limitation the rights
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
10
|
+
furnished to do so, subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in
|
13
|
+
all copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
21
|
+
THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,114 @@
|
|
1
|
+
# Archfiend
|
2
|
+
|
3
|
+
Archfiend (/ˈɑrtʃˈfind/) - a basic daemon generator. It features boilerplate for common development tools (ActiveRecord, RSpec, FactoryBot, RuboCop),
|
4
|
+
handles daemonizing, configuration, logging and more. It provides a way to structure backend applications in an organized manner.
|
5
|
+
|
6
|
+
[](https://travis-ci.com/toptal/archfiend)
|
7
|
+
|
8
|
+
## Contents
|
9
|
+
* [Getting started](#getting-started)
|
10
|
+
* [Primitives](#primitives)
|
11
|
+
* [Featured gems](#featured-gems)
|
12
|
+
* [Changelog](#changelog)
|
13
|
+
* [Contributing](#contributing)
|
14
|
+
* [License](#license)
|
15
|
+
* [Code of Conduct](#code-of-conduct)
|
16
|
+
|
17
|
+
## Getting started
|
18
|
+
|
19
|
+
Archfiend provides the `archfiend` executable, which features a daemon generator.
|
20
|
+
|
21
|
+
```bash
|
22
|
+
$ bundle exec archfiend new my_new_daemon # Creates the new daemon
|
23
|
+
$ cd my_new_daemon
|
24
|
+
$ cp config/database.yml{.example,} # Currently, it ships with ActiveRecord, database configuration is required
|
25
|
+
$ bin/start # Start without daemonization
|
26
|
+
2018-10-09T13:59:55.874Z 88087 TID-ovtqe0m53 INFO: Starting up
|
27
|
+
2018-10-09T13:59:56.301Z 88087 TID-ovtqu0g3f INFO: Starting thread BarThreadLoop
|
28
|
+
2018-10-09T13:59:56.303Z 88431 TID-ovtqe0m53 INFO: Starting subprocess FooSubprocessLoop
|
29
|
+
```
|
30
|
+
|
31
|
+
## Primitives
|
32
|
+
|
33
|
+
Daemons generated with Archfiend are structured around `ThreadLoops` and `SubprocessLoops`.
|
34
|
+
They provide entry points for any user code. There is no limit on the number of each, you should
|
35
|
+
use your judgement on how many your target environment can realistically handle.
|
36
|
+
|
37
|
+
### ThreadLoops
|
38
|
+
|
39
|
+
When started, Archfiend instantiates each [ThreadLoop](lib/archfiend/thread_loop.rb) subclass in a separate thread and calls its `#run` method.
|
40
|
+
By default, `#run` wraps looped execution of `#iterate` with `StandardError` handling.
|
41
|
+
You are supposed to either provide the `#iterate` method or shadow the `#run` method to fully take over
|
42
|
+
the control of the thread.
|
43
|
+
Bear in mind that any unhandled exception will terminate the whole process. If your code deals with
|
44
|
+
exceptions that are not subclasses of `StandardError`, make sure you handle it on your own.
|
45
|
+
|
46
|
+
With MRI, parallel threads execution happens only when one of threads waits for IO. This should be
|
47
|
+
fairly often in network communicating daemons.
|
48
|
+
|
49
|
+
### SubprocessLoops
|
50
|
+
|
51
|
+
When started, archfiend instantiates each [SubprocessLoop](lib/archfiend/subprocess_loop.rb) subclass in a separate fork and calls its `#run` method.
|
52
|
+
By default, `#run` wraps looped execution of `#iterate` with `StandardError` handling.
|
53
|
+
You are supposed to either provide the `#iterate` method or shadow the `#run` method to fully take over
|
54
|
+
the control of the process.
|
55
|
+
Subprocesses are killed when the main daemon process exits. If a subprocess gets terminated, it does not kill the main
|
56
|
+
process. The main process doesn't restart its subprocesses by default.
|
57
|
+
|
58
|
+
## Featured gems
|
59
|
+
|
60
|
+
### ActiveRecord
|
61
|
+
|
62
|
+
ActiveRecord is available and configured using the `config/database.yml`, you can create regular AR model files
|
63
|
+
inside `app/models`.
|
64
|
+
When creating multi-threaded daemons, make sure connection pool is handled correctly (that connections are
|
65
|
+
released to the pool after a thread finishes) and that the pool has enough open connections (default is 5).
|
66
|
+
|
67
|
+
Migrations are provided by the [ActiveRecord::Migrations](https://github.com/ioquatix/activerecord-migrations) gem, you can use following rake tasks
|
68
|
+
```bash
|
69
|
+
rake db:migrate # Migrate the database (options: VERSION=x, VERBOSE=false, SCOPE=blog)
|
70
|
+
rake db:rollback # Rolls the schema back to the previous version (specify steps w/ STEP=n)
|
71
|
+
rake db:migrations:new[name,options] # Creates a new migration file with the specified name
|
72
|
+
```
|
73
|
+
|
74
|
+
Please see `bundle exec rake -T` for more options.
|
75
|
+
|
76
|
+
### Clockwork
|
77
|
+
|
78
|
+
Archfiend provides the [Clockwork](https://github.com/Rykian/clockwork) integration, so daemons can schedule recurring tasks.
|
79
|
+
Uncomment the contents of the `clockwork/clockwork.rb` file to enable it. If the daemon doesn't use clockwork, feel free
|
80
|
+
to remove the file, the directory and the Gemfile entry.
|
81
|
+
|
82
|
+
### Settings
|
83
|
+
|
84
|
+
The [config](https://github.com/railsconfig/config) gem is used to handle multi-environment settings.
|
85
|
+
|
86
|
+
### rbtrace
|
87
|
+
|
88
|
+
For debugging, daemons generated with Archfiend include [rbtrace](http://github.com/tmm1/rbtrace).
|
89
|
+
By default, it is enabled in the development environment.
|
90
|
+
|
91
|
+
### RSpec / RuboCop
|
92
|
+
|
93
|
+
Newly generated daemons come with integrations for RSpec and RuboCop.
|
94
|
+
|
95
|
+
## Changelog
|
96
|
+
|
97
|
+
See [CHANGES.md](CHANGES.md) for the list of changes.
|
98
|
+
|
99
|
+
## Roadmap
|
100
|
+
|
101
|
+
See [ROADMAP.md](ROADMAP.md) for the uncommitted list of ideas for future.
|
102
|
+
|
103
|
+
## Contributing
|
104
|
+
|
105
|
+
Bug reports and pull requests are welcome on GitHub at https://github.com/toptal/archfiend.
|
106
|
+
This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [Contributor Covenant](http://contributor-covenant.org) code of conduct.
|
107
|
+
|
108
|
+
## License
|
109
|
+
|
110
|
+
The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
|
111
|
+
|
112
|
+
## Code of Conduct
|
113
|
+
|
114
|
+
Everyone interacting in the Archfiend project’s codebases, issue trackers, chat rooms and mailing lists is expected to follow the [code of conduct](https://github.com/toptal/archfiend/blob/master/CODE_OF_CONDUCT.md).
|
data/ROADMAP.md
ADDED
@@ -0,0 +1,11 @@
|
|
1
|
+
# Archfiend Roadmap
|
2
|
+
|
3
|
+
The general goal of this project is to have a low-dependency, solid, pluggable Ruby daemon generator.
|
4
|
+
|
5
|
+
Ideas include
|
6
|
+
* exhaustive documentation for running (`bin/start`, `bin/console`) and development of generated daemons
|
7
|
+
* method to opt-out from any integrated gem
|
8
|
+
* removal of `daemons` dependency
|
9
|
+
* removal of `config` dependency
|
10
|
+
* removal of `clockwork` dependency
|
11
|
+
* stand-alone generator option, to generate daemons with no external run time dependencies (with Archfiend base classes baked in)
|
data/Rakefile
ADDED
data/archfiend.gemspec
ADDED
@@ -0,0 +1,35 @@
|
|
1
|
+
lib = File.expand_path('lib', __dir__)
|
2
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
3
|
+
require 'archfiend/version'
|
4
|
+
|
5
|
+
Gem::Specification.new do |spec|
|
6
|
+
spec.name = 'archfiend'
|
7
|
+
spec.version = Archfiend::VERSION
|
8
|
+
spec.authors = ['Maciek Dubiński']
|
9
|
+
spec.email = ['maciek@dubinski.net']
|
10
|
+
|
11
|
+
spec.summary = 'A tool to simplify creation and development of Ruby daemons'
|
12
|
+
spec.description = 'A tool to simplify creation and development of Ruby daemons.'
|
13
|
+
spec.homepage = 'https://github.com/toptal/archfiend'
|
14
|
+
spec.license = 'MIT'
|
15
|
+
|
16
|
+
spec.files = `git ls-files -z`.split("\x0").reject do |f|
|
17
|
+
f.match(%r{^(test|spec|features)/})
|
18
|
+
end
|
19
|
+
spec.bindir = 'exe'
|
20
|
+
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
21
|
+
spec.require_paths = ['lib']
|
22
|
+
|
23
|
+
spec.add_dependency 'activesupport' # CLI
|
24
|
+
spec.add_development_dependency 'activerecord'
|
25
|
+
spec.add_development_dependency 'bundler', '~> 1.15'
|
26
|
+
spec.add_development_dependency 'config'
|
27
|
+
spec.add_dependency 'oj'
|
28
|
+
spec.add_development_dependency 'pg', '~> 0.21'
|
29
|
+
spec.add_dependency 'pry'
|
30
|
+
spec.add_development_dependency 'rake', '~> 10.0'
|
31
|
+
spec.add_development_dependency 'rspec', '~> 3.0'
|
32
|
+
spec.add_development_dependency 'rubocop'
|
33
|
+
spec.add_development_dependency 'rubocop-rspec'
|
34
|
+
spec.add_dependency 'thor' # CLI
|
35
|
+
end
|
data/bin/console
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require 'bundler/setup'
|
4
|
+
require 'archfiend'
|
5
|
+
|
6
|
+
# You can add fixtures and/or initialization code here to make experimenting
|
7
|
+
# with your gem easier. You can also use a different console, if you like.
|
8
|
+
|
9
|
+
# (If you use this, don't forget to add pry to your Gemfile!)
|
10
|
+
# require "pry"
|
11
|
+
# Pry.start
|
12
|
+
|
13
|
+
require 'irb'
|
14
|
+
IRB.start(__FILE__)
|
data/bin/setup
ADDED
data/exe/archfiend
ADDED
data/lib/archfiend.rb
ADDED
@@ -0,0 +1,18 @@
|
|
1
|
+
require 'archfiend/version'
|
2
|
+
require 'archfiend/application'
|
3
|
+
require 'archfiend/logging'
|
4
|
+
require 'archfiend/logging/base_formatter'
|
5
|
+
require 'archfiend/logging/default_formatter'
|
6
|
+
require 'archfiend/logging/json_formatter'
|
7
|
+
require 'archfiend/logging/multi_logger'
|
8
|
+
require 'archfiend/shared_loop/runnable'
|
9
|
+
require 'archfiend/thread_loop'
|
10
|
+
require 'archfiend/subprocess_loop'
|
11
|
+
require 'archfiend/generators/daemon'
|
12
|
+
require 'archfiend/generators/options'
|
13
|
+
require 'archfiend/generators/extensions'
|
14
|
+
require 'archfiend/generators/utils'
|
15
|
+
require 'archfiend/cli'
|
16
|
+
|
17
|
+
module Archfiend
|
18
|
+
end
|
@@ -0,0 +1,132 @@
|
|
1
|
+
module Archfiend
|
2
|
+
class Application
|
3
|
+
extend Forwardable
|
4
|
+
|
5
|
+
def_delegators :utils, :logger, :env, :name
|
6
|
+
|
7
|
+
# The main application entry point, it starts up all the subthreads, all the subprocesses,
|
8
|
+
# registers the exit handler and then it blocks the execution.
|
9
|
+
def run
|
10
|
+
logger.info 'Starting up'
|
11
|
+
|
12
|
+
setup
|
13
|
+
|
14
|
+
ThreadLoop.start_all(self)
|
15
|
+
SubprocessLoop.start_all(self)
|
16
|
+
|
17
|
+
run_clockwork
|
18
|
+
|
19
|
+
# Setup after subprocesses are created, so the handler is not copied to them
|
20
|
+
setup_cleanup
|
21
|
+
loop { sleep 1 }
|
22
|
+
end
|
23
|
+
|
24
|
+
def setup
|
25
|
+
return if @already_setup
|
26
|
+
|
27
|
+
setup_timezone
|
28
|
+
setup_settings
|
29
|
+
setup_logger
|
30
|
+
setup_activerecord
|
31
|
+
setup_debug
|
32
|
+
|
33
|
+
run_initializers
|
34
|
+
require_app_classes
|
35
|
+
|
36
|
+
@already_setup = true
|
37
|
+
end
|
38
|
+
|
39
|
+
private
|
40
|
+
|
41
|
+
def run_initializers
|
42
|
+
Dir[utils.root.join('config', 'initializers', '**', '*.rb')].sort.each do |ruby_file|
|
43
|
+
load ruby_file
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
def require_app_classes
|
48
|
+
rb_pattern = utils.root.join('app', '**', '*.rb')
|
49
|
+
Dir[rb_pattern].each { |file_name| require file_name }
|
50
|
+
end
|
51
|
+
|
52
|
+
def setup_activerecord
|
53
|
+
# TODO: ensure connection timezone is correct
|
54
|
+
|
55
|
+
yaml_text = ERB.new(IO.read(utils.root.join('config', 'database.yml'))).result
|
56
|
+
::ActiveRecord::Base.configurations = YAML.load(yaml_text) # rubocop:disable Security/YAMLLoad
|
57
|
+
::ActiveRecord::Base.establish_connection(env.to_sym)
|
58
|
+
::ActiveRecord::Base.logger = utils.logger if %w[development test].include?(env)
|
59
|
+
end
|
60
|
+
|
61
|
+
def setup_timezone
|
62
|
+
Time.zone_default = ActiveSupport::TimeZone['UTC']
|
63
|
+
end
|
64
|
+
|
65
|
+
def setup_settings
|
66
|
+
::Config.load_and_set_settings(::Config.setting_files(utils.root.join('config'), env))
|
67
|
+
end
|
68
|
+
|
69
|
+
# Starts a new thread that runs tasks defined in the Clockwork module.
|
70
|
+
def run_clockwork
|
71
|
+
return unless self.class.const_defined?('Clockwork')
|
72
|
+
|
73
|
+
th = Thread.new do
|
74
|
+
::Clockwork.run
|
75
|
+
end
|
76
|
+
th[:name] = 'Clockwork'
|
77
|
+
end
|
78
|
+
|
79
|
+
POSSIBLE_LOGGER_LEVELS = %i[debug info warn error fatal unknown].freeze
|
80
|
+
def setup_logger
|
81
|
+
logger_level = Settings.logger&.level
|
82
|
+
fail "Please set logger.level setting (#{POSSIBLE_LOGGER_LEVELS.inspect})" unless POSSIBLE_LOGGER_LEVELS.include?(logger_level)
|
83
|
+
utils.logger.level = logger_level
|
84
|
+
utils.logger.progname = name
|
85
|
+
end
|
86
|
+
|
87
|
+
# Registers actions to be performed when the ruby vm exits
|
88
|
+
def setup_cleanup
|
89
|
+
at_exit do
|
90
|
+
utils.logger.info 'Exiting'
|
91
|
+
SubprocessLoop.kill_all
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
def setup_debug
|
96
|
+
return unless Settings.debug&.rbtrace
|
97
|
+
|
98
|
+
require 'rbtrace'
|
99
|
+
rescue LoadError => e
|
100
|
+
puts 'Settings.debug.rbtrace is true but cannot load the "rbtrace" gem, make sure it is present in Gemfile'
|
101
|
+
puts "(#{e})"
|
102
|
+
exit 1
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
106
|
+
module Utilities
|
107
|
+
def logger
|
108
|
+
@logger ||= Archfiend::Logging.create(env, root.join('log'))
|
109
|
+
end
|
110
|
+
|
111
|
+
def app
|
112
|
+
@app ||= const_get('Application').new
|
113
|
+
end
|
114
|
+
|
115
|
+
def env
|
116
|
+
ENV['APP_ENV'] || ENV['RAILS_ENV'] || 'development'
|
117
|
+
end
|
118
|
+
|
119
|
+
# Returns all dependency groups for loading based on:
|
120
|
+
# * The App environment;
|
121
|
+
# * The environment variable APP_GROUPS;
|
122
|
+
# @return [Array<string>] All gem groups that needs to be included for current env
|
123
|
+
def groups(*groups)
|
124
|
+
groups.unshift(:default, env.to_sym)
|
125
|
+
env_groups = ENV['APP_GROUPS'] || ENV['RAILS_GROUPS']
|
126
|
+
groups.concat env_groups.to_s.split(',')
|
127
|
+
groups.compact!
|
128
|
+
groups.uniq!
|
129
|
+
groups
|
130
|
+
end
|
131
|
+
end
|
132
|
+
end
|