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.
Files changed (69) hide show
  1. checksums.yaml +7 -0
  2. data/.github/PULL_REQUEST_TEMPLATE.md +18 -0
  3. data/.gitignore +12 -0
  4. data/.rspec +4 -0
  5. data/.rubocop.yml +323 -0
  6. data/.travis.yml +11 -0
  7. data/CHANGES.md +12 -0
  8. data/CODE_OF_CONDUCT.md +74 -0
  9. data/Gemfile +7 -0
  10. data/Gemfile.lock +122 -0
  11. data/LICENSE.txt +21 -0
  12. data/README.md +114 -0
  13. data/ROADMAP.md +11 -0
  14. data/Rakefile +6 -0
  15. data/archfiend.gemspec +35 -0
  16. data/bin/console +14 -0
  17. data/bin/setup +8 -0
  18. data/exe/archfiend +4 -0
  19. data/lib/archfiend.rb +18 -0
  20. data/lib/archfiend/application.rb +132 -0
  21. data/lib/archfiend/cli.rb +9 -0
  22. data/lib/archfiend/generators/daemon.rb +144 -0
  23. data/lib/archfiend/generators/daemon/templates/.rspec +4 -0
  24. data/lib/archfiend/generators/daemon/templates/.rubocop.yml +323 -0
  25. data/lib/archfiend/generators/daemon/templates/Gemfile.tt +32 -0
  26. data/lib/archfiend/generators/daemon/templates/README.md.tt +23 -0
  27. data/lib/archfiend/generators/daemon/templates/Rakefile.tt +13 -0
  28. data/lib/archfiend/generators/daemon/templates/app/clockwork/clockwork.rb.tt +14 -0
  29. data/lib/archfiend/generators/daemon/templates/app/models/application_record.rb +3 -0
  30. data/lib/archfiend/generators/daemon/templates/app/subprocess_loops/foo_subprocess_loop.rb +13 -0
  31. data/lib/archfiend/generators/daemon/templates/app/thread_loops/bar_thread_loop.rb +8 -0
  32. data/lib/archfiend/generators/daemon/templates/bin/console +3 -0
  33. data/lib/archfiend/generators/daemon/templates/bin/start.tt +6 -0
  34. data/lib/archfiend/generators/daemon/templates/config/application.rb.tt +27 -0
  35. data/lib/archfiend/generators/daemon/templates/config/boot.rb.tt +3 -0
  36. data/lib/archfiend/generators/daemon/templates/config/daemon.rb.tt +18 -0
  37. data/lib/archfiend/generators/daemon/templates/config/database.yml.example.tt +26 -0
  38. data/lib/archfiend/generators/daemon/templates/config/environment.rb.tt +4 -0
  39. data/lib/archfiend/generators/daemon/templates/config/settings.yml.tt +8 -0
  40. data/lib/archfiend/generators/daemon/templates/config/settings/development.yml.tt +2 -0
  41. data/lib/archfiend/generators/daemon/templates/config/settings/production.yml.tt +2 -0
  42. data/lib/archfiend/generators/daemon/templates/config/settings/staging.yml.tt +5 -0
  43. data/lib/archfiend/generators/daemon/templates/config/settings/test.yml.tt +0 -0
  44. data/lib/archfiend/generators/daemon/templates/db/migrate/.gitkeep +0 -0
  45. data/lib/archfiend/generators/daemon/templates/lib/tasks/.gitkeep +0 -0
  46. data/lib/archfiend/generators/daemon/templates/log/.gitkeep +0 -0
  47. data/lib/archfiend/generators/daemon/templates/spec/factories/.gitkeep +0 -0
  48. data/lib/archfiend/generators/daemon/templates/spec/models/.gitkeep +0 -0
  49. data/lib/archfiend/generators/daemon/templates/spec/spec_helper.rb +43 -0
  50. data/lib/archfiend/generators/daemon/templates/spec/subprocess_loops/foo_subprocess_loop_spec.rb +5 -0
  51. data/lib/archfiend/generators/daemon/templates/spec/support/factory_bot.rb +9 -0
  52. data/lib/archfiend/generators/daemon/templates/spec/support/timecop.rb +9 -0
  53. data/lib/archfiend/generators/daemon/templates/spec/thread_loops/bar_thread_loop_spec.rb +5 -0
  54. data/lib/archfiend/generators/daemon/templates/tmp/.gitkeep +0 -0
  55. data/lib/archfiend/generators/extensions.rb +119 -0
  56. data/lib/archfiend/generators/options.rb +51 -0
  57. data/lib/archfiend/generators/utils.rb +37 -0
  58. data/lib/archfiend/logging.rb +38 -0
  59. data/lib/archfiend/logging/base_formatter.rb +35 -0
  60. data/lib/archfiend/logging/default_formatter.rb +12 -0
  61. data/lib/archfiend/logging/json_formatter.rb +21 -0
  62. data/lib/archfiend/logging/multi_logger.rb +31 -0
  63. data/lib/archfiend/shared_loop/runnable.rb +26 -0
  64. data/lib/archfiend/subprocess_loop.rb +46 -0
  65. data/lib/archfiend/thread_loop.rb +35 -0
  66. data/lib/archfiend/version.rb +3 -0
  67. data/scripts/travis/install +13 -0
  68. data/scripts/travis/script +43 -0
  69. metadata +280 -0
data/Gemfile ADDED
@@ -0,0 +1,7 @@
1
+ source 'https://rubygems.org'
2
+
3
+ git_source(:github) { |repo_name| "https://github.com/#{repo_name}" }
4
+
5
+ # Specify your gem's dependencies in archfiend.gemspec
6
+
7
+ gemspec
@@ -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
@@ -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.
@@ -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
+ [![Build Status](https://travis-ci.com/toptal/archfiend.svg?branch=master)](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).
@@ -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)
@@ -0,0 +1,6 @@
1
+ require 'bundler/gem_tasks'
2
+ require 'rspec/core/rake_task'
3
+
4
+ RSpec::Core::RakeTask.new(:spec)
5
+
6
+ task default: :spec
@@ -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
@@ -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__)
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+ set -vx
5
+
6
+ bundle install
7
+
8
+ # Do any other automated setup that you need to do here
@@ -0,0 +1,4 @@
1
+ #!/usr/bin/env ruby
2
+ require 'archfiend'
3
+
4
+ Archfiend::CLI.start(ARGV)
@@ -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