Class: Jets::Booter

Inherits:
Object
  • Object
show all
Defined in:
lib/jets/booter.rb

Class Method Summary collapse

Class Method Details

.app_initializersObject

All Turbines



133
134
135
136
137
# File 'lib/jets/booter.rb', line 133

def app_initializers
  Dir.glob("#{Jets.root}/config/initializers/**/*").sort.each do |path|
    load path
  end
end

.boot!Object



6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
# File 'lib/jets/booter.rb', line 6

def boot!
  return if @booted

  confirm_jets_project!
  Jets::Bundle.require

  Jets.application.setup!

  # Turbines are loaded after setup_autoload_paths in Jets.application.setup!  Some Turbine options are defined
  # in the project so setup must happen before internal Turbines are loaded.
  load_internal_turbines

  run_turbines(:initializers)
  # Load configs after Turbine initializers so Turbines can defined some config options and they are available in
  # user's project environment configs.
  Jets.application.configs!
  app_initializers
  run_turbines(:after_initializers)
  Jets.application.finish!

  setup_db # establish db connections in Lambda Execution Context.
  # The eager load calls connects_to in models and establish those connections in Lambda Execution Context also.
  internal_finisher
  eager_load

  # TODO: Figure out how to build middleware during Jets.boot without breaking jets new and webpacker:install
  # build_middleware_stack

  @booted = true
end

.build_middleware_stackObject

Builds and memoize stack so it only gets built on bootup



151
152
153
# File 'lib/jets/booter.rb', line 151

def build_middleware_stack
  Jets.application.build_stack
end

.check_config_ru!Object



167
168
169
170
171
172
173
174
175
176
# File 'lib/jets/booter.rb', line 167

def check_config_ru!
  config_ru = File.read("#{Jets.root}/config.ru")
  unless config_ru.include?("Jets.boot")
    puts 'The config.ru file is missing Jets.boot.  Please add Jets.boot after require "jets"'.color(:red)
    puts "This was changed as made in Jets v1.1.0."
    puts "To have Jets update the config.fu file for you, you can run:\n\n"
    puts "  jets upgrade"
    exit 1
  end
end

.confirm_jets_project!Object

Cannot call this for the jets new



156
157
158
159
160
161
# File 'lib/jets/booter.rb', line 156

def confirm_jets_project!
  unless File.exist?("#{Jets.root}/config/application.rb")
    puts "It does not look like you are running this command within a jets project.  Please confirm that you are in a jets project and try again.".color(:red)
    exit 1
  end
end

.connect_dbObject

Eager connect to database, so connections are established in the Lambda Execution Context and get reused. Interestingly, the connections info is stored in the shared state but the connection doesnt show up on ‘show processlist` until after a query. Have confirmed that the connection is reused and the connection count stays the same.



96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
# File 'lib/jets/booter.rb', line 96

def connect_db
  if ActiveRecord::Base.legacy_connection_handling
    primary_hash_config = ActiveRecord::Base.configurations.configs_for(env_name: Jets.env).find { |hash_config|
      hash_config.name == "primary"
    }
  
    primary_config = primary_hash_config.configuration_hash # configuration_hash is a normal Ruby Hash

    ActiveRecord::Base.establish_connection(primary_config)
  else
    configs = ActiveRecord::Base.configurations.configs_for(env_name: Jets.env, include_replicas: true)

    databases = { }
    databases[:writing] = :primary if configs.any? { |config| config.name == "primary" }
    databases[:reading] = :primary_replica if configs.any? { |config| config.name == "primary_replica" }

    ActiveRecord::Base.connects_to database: databases
  end
end

.eager_loadObject



56
57
58
59
# File 'lib/jets/booter.rb', line 56

def eager_load
  preload_extensions
  Jets::Autoloaders.main.eager_load # Eager load project code. Rather have user find out early than later on AWS Lambda.
end

.internal_finisherObject

Runs right before eager_load



38
39
40
# File 'lib/jets/booter.rb', line 38

def internal_finisher
  load_shared_extensions
end

.load_internal_turbinesObject



116
117
118
119
120
# File 'lib/jets/booter.rb', line 116

def load_internal_turbines
  Jets::Autoloaders.once.on_setup do
    Jets::Mailer # only one right now
  end
end

.load_shared_extensionsObject

Shared extensions are added near the end because they require the Jets app load paths to first. We eager load the extensions and then use the loaded modules to extend Jets::Stack directly. Originally used an included hook but thats too early before app/shared/extensions is in the load_path.



45
46
47
48
49
50
51
52
53
54
# File 'lib/jets/booter.rb', line 45

def load_shared_extensions
  base_path = "#{Jets.root}/app/shared/extensions"
  Dir.glob("#{base_path}/**/*.rb").each do |path|
    next unless File.file?(path)

    class_name = path.sub("#{base_path}/", '').sub(/\.rb/,'').camelize
    mod = class_name.constantize # autoload
    Jets::Stack.extend(mod)
  end
end

.messageObject



163
164
165
# File 'lib/jets/booter.rb', line 163

def message
  "Jets booting up in #{Jets.env.color(:green)} mode!"
end

.preload_extensionsObject



61
62
63
64
65
66
67
68
69
70
# File 'lib/jets/booter.rb', line 61

def preload_extensions
  base_path = "#{Jets.root}/app/extensions"
  Dir.glob("#{base_path}/**/*.rb").each do |path|
    next unless File.file?(path)

    class_name = path.sub("#{base_path}/", '').sub(/\.rb/,'').camelize
    klass = class_name.constantize # autoload
    Jets::Lambda::Functions.extend(klass)
  end
end

.run_turbines(name) ⇒ Object

run_turbines(:initializers) run_turbines(:after_initializers)



141
142
143
144
145
146
147
148
# File 'lib/jets/booter.rb', line 141

def run_turbines(name)
  Jets::Turbine.subclasses.each do |subclass|
    hooks = subclass.send(name) || []
    hooks.each do |label, block|
      block.call(Jets.application)
    end
  end
end

.setup_dbObject

Using ActiveRecord outside of Rails, so we need to set up the db connection ourself.

Only connects to database for ActiveRecord and when config/database.yml exists. Dynomite handles connecting to the clients lazily.



76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
# File 'lib/jets/booter.rb', line 76

def setup_db
  return unless File.exist?("#{Jets.root}/config/database.yml")

  db_configs = Jets.application.config.database
  # DatabaseTasks.database_configuration for db:create db:migrate tasks
  # Documented in DatabaseTasks that this is the right way to set it when
  # using ActiveRecord rake tasks outside of Rails.
  ActiveRecord::Tasks::DatabaseTasks.database_configuration = db_configs

  if db_configs.configs_for(env_name: Jets.env).blank?
    abort("ERROR: config/database.yml exists but no environment section configured for #{Jets.env}")
  end
  ActiveRecord::Base.configurations = db_configs
  connect_db
end

.turbine_initializersObject

All Turbines



123
124
125
126
127
128
129
130
# File 'lib/jets/booter.rb', line 123

def turbine_initializers
  Jets::Turbine.subclasses.each do |subclass|
    initializers = subclass.initializers || []
    initializers.each do |label, block|
      block.call(Jets.application)
    end
  end
end