trinidad 1.1.1 → 1.2.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.
@@ -1,3 +1,9 @@
1
+ == Trinidad 1.2.0 (2011-05-24)
2
+
3
+ * Zero downtime hot deploy
4
+ * Autodetect framework and threadsafe environment
5
+ * Upgrade jruby-rack dependency to 1.0.9
6
+
1
7
  == Trinidad 1.1.1 (2011-03-27)
2
8
 
3
9
  * Remove shared runtime initialization
@@ -3,37 +3,17 @@
3
3
  Trinidad allows you to run a rails or rackup applications within an embedded Apache Tomcat container.
4
4
 
5
5
  * Mail list: http://groups.google.com/group/rails-trinidad
6
- * Bug tracker: http://github.com/calavera/trinidad/issues
6
+ * Bug tracker: http://github.com/trinidad/trinidad/issues
7
7
  * Irc channel on Freenode: #trinidad
8
8
 
9
9
  == INSTALL:
10
10
 
11
- jgem install trinidad
11
+ $ jruby -S gem install trinidad
12
12
 
13
13
  == USAGE:
14
14
 
15
- Rails applications:
16
-
17
- $ cd myrailsapp
18
- $ jruby -S trinidad
19
-
20
- Rack applications:
21
-
22
- $ cd myrackapplication
23
-
24
- $ jruby -S trinidad -r path_to_rackup/rackup_file
25
-
26
- or if the name of the file is config.ru
27
-
28
- $ jruby -S trinidad -r path_to_rackup
29
-
30
- or if config.ru is in the base directory
31
-
32
- $ jruby -S trinidad -r
33
-
34
- or if config.ru is under the directory WEB-INF
35
-
36
- $ jruby -S trinidad
15
+ $ cd myapp
16
+ $ jruby -S trinidad
37
17
 
38
18
  == CONFIGURATION:
39
19
 
@@ -47,7 +27,7 @@ Trinidad allows you to configure some parameters when the server is started from
47
27
  * -r, --rackup [RACKUP_FILE] => run a provided rackup file instead of a rails application, by default it's config.ru.
48
28
  * --public PUBLIC_DIR => specify the public directory for your application, by default it's 'public'.
49
29
  * -t, --threadsafe => shortcut to work in threadsafe mode. Setting jruby_min_runtimes and jruby_max_runtimes to 1 in the configuration file the server behaves as the same way.
50
- * -l, --load EXTENSION_NAME => load an extension to use its command line options.
30
+ * -l, --load EXTENSION_NAMES => load extensions to use their command line options.
51
31
  * --address HOST => set the server host.
52
32
  * -g, --log LEVEL => set the log level, default INFO.
53
33
  * --apps APPS_BASE_DIRECTORY => set the applications base directory.
@@ -58,7 +38,7 @@ The server can also be configured from a yaml file. By default, if a file is not
58
38
 
59
39
  You can also specify a default web.xml to config your web application. By default the server tries to load the file <em>config/web.xml</em> but you can modify this path adding the option <em>default_web_xml</em> within your configuration file.
60
40
 
61
- Other advanced options can be found in the wiki: http://wiki.github.com/calavera/trinidad/advanced-configuration
41
+ Other advanced options can be found in the wiki: http://wiki.github.com/trinidad/trinidad/advanced-configuration
62
42
 
63
43
  == HOT DEPLOYMENT:
64
44
 
@@ -70,16 +50,16 @@ modified with the option `:monitor`.
70
50
 
71
51
  From the version 0.8.0 Trinidad allows to extend the server with more Tomcat features, here there is a list with the current available extensions:
72
52
 
73
- * Database connection pooling: http://github.com/calavera/trinidad-dbpool
53
+ * Database connection pooling: http://github.com/trinidad/trinidad-dbpool
74
54
  * Daemons:
75
- ** Daemon based on Akuma (ala GF gem): http://github.com/calavera/trinidad_daemon_extension
76
- ** Daemon based on Apache Commons Daemon (supports Unix and Windows systems): http://github.com/calavera/trinidad_daemon
77
- * Hot deploy, do hot deploys monitorizing a temporal file, ala Passenger: http://github.com/calavera/trinidad_hotdeploy_extension
78
- * Sandbox, management console and REST api: http://github.com/calavera/trinidad_sandbox_extension
79
- * Logging, enhance the Trinidad's logging system: http://github.com/calavera/trinidad_logging_extension
80
- * Lifecycle, application and server lifecycle management: http://github.com/calavera/trinidad_lifecycle_extension
81
-
82
- You can find further information on how to write your own extension in the wiki: http://wiki.github.com/calavera/trinidad/extensions
55
+ ** Daemon based on Akuma (ala GF gem): http://github.com/trinidad/trinidad_daemon_extension
56
+ ** Daemon based on Apache Commons Daemon (supports Unix and Windows systems): http://github.com/trinidad/trinidad_daemon
57
+ * Sandbox, management console and REST api: http://github.com/trinidad/trinidad_sandbox_extension
58
+ * Logging, enhance the Trinidad's logging system: http://github.com/trinidad/trinidad_logging_extension
59
+ * Lifecycle, application and server lifecycle management: http://github.com/trinidad/trinidad_lifecycle_extension
60
+ * Scheduler, based on Quartz: http://github.com/trinidad/trinidad_scheduler_extension
61
+
62
+ You can find further information on how to write your own extension in the wiki: http://wiki.github.com/trinidad/trinidad/extensions
83
63
 
84
64
  == Copyright
85
65
 
File without changes
@@ -11,6 +11,7 @@ require 'trinidad/extensions'
11
11
  require 'trinidad/command_line_parser'
12
12
  require 'trinidad/jars'
13
13
  require 'trinidad/server'
14
+ require 'trinidad/lifecycle/takeover'
14
15
  require 'trinidad/lifecycle/lifecycle_listener_host'
15
16
  require 'trinidad/lifecycle/lifecycle_listener_base'
16
17
  require 'trinidad/lifecycle/lifecycle_listener_default'
@@ -21,5 +22,5 @@ require 'trinidad/rackup_web_app'
21
22
  require 'trinidad/war_web_app'
22
23
 
23
24
  module Trinidad
24
- VERSION = '1.1.1'
25
+ VERSION = '1.2.0'
25
26
  end
@@ -121,8 +121,10 @@ module Trinidad
121
121
  exit
122
122
  end
123
123
 
124
- opts.on('-l', '--load EXTENSION_NAME', 'load options for a given extension') do |name|
125
- Trinidad::Extensions.configure_options_extensions({name => {}}, opts, default_options)
124
+ opts.on('-l', '--load EXTENSION_NAMES', Array, 'load options for extensions') do |ext_names|
125
+ ext_names.each do |ext|
126
+ Trinidad::Extensions.configure_options_extensions({ext => {}}, opts, default_options)
127
+ end
126
128
  end
127
129
 
128
130
  opts.on('--apps', '--apps APPS_BASE_DIR', 'applications base directory') do |path|
@@ -14,12 +14,17 @@ module Trinidad
14
14
 
15
15
  def configure_deployment_descriptor(context)
16
16
  if descriptor = @webapp.default_deployment_descriptor
17
- context.setDefaultWebXml(descriptor)
18
-
19
- context_config = Trinidad::Tomcat::ContextConfig.new
17
+ listeners = context.findLifecycleListeners
18
+ context_config = listeners && listeners.find do |listener|
19
+ listener.is_a?(Trinidad::Tomcat::ContextConfig)
20
+ end
21
+
22
+ unless context_config
23
+ context_config = Trinidad::Tomcat::ContextConfig.new
24
+ context.addLifecycleListener(context_config)
25
+ end
26
+
20
27
  context_config.setDefaultWebXml(descriptor)
21
-
22
- context.addLifecycleListener(context_config)
23
28
  end
24
29
  descriptor
25
30
  end
@@ -1,16 +1,19 @@
1
1
  module Trinidad
2
2
  module Lifecycle
3
+
3
4
  class Host
4
5
  include Trinidad::Tomcat::LifecycleListener
5
6
 
6
7
  attr_reader :contexts
7
8
 
8
- def initialize(*contexts)
9
+ def initialize(tomcat, *contexts)
10
+ @tomcat = tomcat
9
11
  @contexts = contexts
10
12
  end
11
13
 
12
14
  def lifecycleEvent(event)
13
15
  host = event.lifecycle
16
+
14
17
  case event.type
15
18
  when Trinidad::Tomcat::Lifecycle::BEFORE_START_EVENT
16
19
  init_monitors
@@ -27,6 +30,7 @@ module Trinidad
27
30
  unless File.exist?(dir = File.dirname(monitor))
28
31
  Dir.mkdir dir
29
32
  end
33
+
30
34
  file = File.new(monitor, opts)
31
35
  c[:mtime] = file.mtime
32
36
  end
@@ -38,12 +42,39 @@ module Trinidad
38
42
  sleep(0.5) unless File.exist?(c[:monitor])
39
43
  next unless File.exist?(c[:monitor])
40
44
 
41
- if (mtime = File.mtime(c[:monitor])) > c[:mtime]
45
+ if (mtime = File.mtime(c[:monitor])) > c[:mtime] && !c[:lock]
46
+ c[:lock] = true
42
47
  c[:mtime] = mtime
43
- c[:context].reload
48
+ c[:context] = create_takeover(c)
49
+ Thread.new { c[:context].start }
44
50
  end
45
51
  end
46
52
  end
53
+
54
+ def create_takeover(c)
55
+ web_app = c[:app]
56
+ old_context = c[:context]
57
+
58
+ context = Trinidad::Tomcat::StandardContext.new
59
+ context.name = rand.to_s
60
+ context.path = old_context.path
61
+ context.doc_base = web_app.web_app_dir
62
+
63
+ context.add_lifecycle_listener Trinidad::Tomcat::Tomcat::DefaultWebXmlListener.new
64
+
65
+ config = Trinidad::Tomcat::ContextConfig.new
66
+ config.default_web_xml = 'org/apache/catalin/startup/NO_DEFAULT_XML'
67
+ context.add_lifecycle_listener config
68
+
69
+ Trinidad::Extensions.configure_webapp_extensions(web_app.extensions, @tomcat, context)
70
+
71
+ context.add_lifecycle_listener(web_app.define_lifecycle)
72
+ context.add_lifecycle_listener(Trinidad::Lifecycle::Takeover.new(c))
73
+
74
+ old_context.parent.add_child context
75
+
76
+ context
77
+ end
47
78
  end
48
79
  end
49
80
  end
@@ -1,6 +1,17 @@
1
1
  module Trinidad
2
2
  module Lifecycle
3
3
  class War < Base
4
+ def lifecycleEvent(event)
5
+ case event.type
6
+ when Trinidad::Tomcat::Lifecycle::AFTER_STOP_EVENT
7
+ destroy_expanded_app
8
+ when Trinidad::Tomcat::Lifecycle::BEFORE_START_EVENT
9
+ expand_app(event.lifecycle)
10
+ end
11
+
12
+ super
13
+ end
14
+
4
15
  def configure_defaults(context)
5
16
  super
6
17
  configure_class_loader(context)
@@ -11,6 +22,22 @@ module Trinidad
11
22
  loader.container = context
12
23
  context.loader = loader
13
24
  end
25
+
26
+ def destroy_expanded_app
27
+ require 'fileutils'
28
+ FileUtils.rm_rf @webapp.web_app_dir.gsub(/\.war$/, '')
29
+ end
30
+
31
+ def expand_app(context)
32
+ if !File.exist?(context.doc_base)
33
+ host = context.parent
34
+ war_file = java.io.File.new(@webapp.web_app_dir)
35
+ war = java.net.URL.new("jar:" + war_file.toURI.toURL.to_s + "!/")
36
+ path_name = File.basename(context.doc_base)
37
+
38
+ Trinidad::Tomcat::ExpandWar.expand(host, war, path_name)
39
+ end
40
+ end
14
41
  end
15
42
  end
16
43
  end
@@ -0,0 +1,25 @@
1
+ module Trinidad
2
+ module Lifecycle
3
+ class Takeover
4
+ include Trinidad::Tomcat::LifecycleListener
5
+ def initialize(old)
6
+ @old = old
7
+ end
8
+
9
+ def lifecycleEvent(event)
10
+ if event.type == Trinidad::Tomcat::Lifecycle::AFTER_START_EVENT
11
+ begin
12
+ name = @old[:context].name
13
+
14
+ @old[:context].stop
15
+ @old[:context].destroy
16
+
17
+ event.lifecycle.name = name
18
+ ensure
19
+ @old.delete(:lock)
20
+ end
21
+ end
22
+ end
23
+ end
24
+ end
25
+ end
@@ -55,7 +55,7 @@ module Trinidad
55
55
  end
56
56
 
57
57
  def load_host_monitor(apps)
58
- @tomcat.host.add_lifecycle_listener(Trinidad::Lifecycle::Host.new(*apps))
58
+ @tomcat.host.add_lifecycle_listener(Trinidad::Lifecycle::Host.new(@tomcat, *apps))
59
59
  end
60
60
 
61
61
  def create_from_web_apps
@@ -83,9 +83,6 @@ module Trinidad
83
83
  :context_path => (name == 'default' ? '' : "/#{name.to_s}"),
84
84
  :web_app_dir => File.expand_path(path)
85
85
  }
86
- if File.directory?(path) && File.exist?(File.expand_path('config.ru', path))
87
- app_config[:rackup] = 'config.ru'
88
- end
89
86
 
90
87
  create_web_app(app_config)
91
88
  end
@@ -100,10 +97,9 @@ module Trinidad
100
97
 
101
98
  Trinidad::Extensions.configure_webapp_extensions(web_app.extensions, @tomcat, app_context)
102
99
 
103
- lifecycle = web_app.war? ? Lifecycle::War.new(web_app) : Lifecycle::Default.new(web_app)
104
- app_context.add_lifecycle_listener(lifecycle)
100
+ app_context.add_lifecycle_listener(web_app.define_lifecycle)
105
101
 
106
- {:context => app_context, :monitor => web_app.monitor}
102
+ {:context => app_context, :app => web_app, :monitor => web_app.monitor}
107
103
  end
108
104
 
109
105
  def add_service_connector(options, protocol = nil)
@@ -194,6 +190,8 @@ module Trinidad
194
190
  end
195
191
 
196
192
  def start
193
+ trap_signals(@tomcat)
194
+
197
195
  @tomcat.start
198
196
  @tomcat.server.await
199
197
  end
@@ -212,5 +210,10 @@ module Trinidad
212
210
  config[:web_apps] = { :default => default_app }
213
211
  end
214
212
  end
213
+
214
+ def trap_signals(tomcat)
215
+ trap('INT') { tomcat.stop }
216
+ trap('TERM') { tomcat.stop }
217
+ end
215
218
  end
216
219
  end
@@ -11,5 +11,9 @@ module Trinidad
11
11
  def monitor
12
12
  File.expand_path(web_app_dir)
13
13
  end
14
+
15
+ def define_lifecycle
16
+ Trinidad::Lifecycle::War.new(self)
17
+ end
14
18
  end
15
19
  end
@@ -3,6 +3,8 @@ module Trinidad
3
3
  attr_reader :config, :app_config, :class_loader, :servlet
4
4
 
5
5
  def self.create(config, app_config)
6
+ autodetect_configuration(config, app_config)
7
+
6
8
  war?(app_config) ? WarWebApp.new(config, app_config) :
7
9
  rackup?(app_config) ? RackupWebApp.new(config, app_config) : RailsWebApp.new(config, app_config)
8
10
  end
@@ -96,6 +98,10 @@ module Trinidad
96
98
  File.expand_path(m_file, work_dir)
97
99
  end
98
100
 
101
+ def define_lifecycle
102
+ Trinidad::Lifecycle::Default.new(self)
103
+ end
104
+
99
105
  protected
100
106
  def add_parameter_unless_exist(param_name, param_value)
101
107
  @params[param_name] = param_value unless web_context_param(param_name)
@@ -129,5 +135,30 @@ module Trinidad
129
135
  end
130
136
  @servlet = {:class => servlet_class, :name => servlet_name}
131
137
  end
138
+
139
+ def self.autodetect_configuration(config, app_config)
140
+ # Check for Rails threadsafe mode
141
+ environment = app_config[:environment] || config[:environment]
142
+ if threadsafe_instance?(app_config[:web_app_dir], environment)
143
+ app_config[:jruby_min_runtimes] = 1
144
+ app_config[:jruby_max_runtimes] = 1
145
+ end
146
+
147
+ # Check for rackup (but still use config/environment.rb for Rails 3)
148
+ if !app_config[:rackup] && !config[:rackup] &&
149
+ File.exists?("#{app_config[:web_app_dir]}/config.ru") &&
150
+ !File.exists?("#{app_config[:web_app_dir]}/config/environment.rb")
151
+ app_config[:rackup] = 'config.ru'
152
+ end
153
+ end
154
+
155
+ def self.threadsafe_instance?(app_base, environment)
156
+ threadsafe_match?("#{app_base}/config/environments/#{environment}.rb") ||
157
+ threadsafe_match?("#{app_base}/config/environment.rb")
158
+ end
159
+
160
+ def self.threadsafe_match?(file)
161
+ File.exist?(file) && File.readlines(file).any? { |l| l =~ /^[^#]*threadsafe!/ }
162
+ end
132
163
  end
133
164
  end
metadata CHANGED
@@ -2,7 +2,7 @@
2
2
  name: trinidad
3
3
  version: !ruby/object:Gem::Version
4
4
  prerelease:
5
- version: 1.1.1
5
+ version: 1.2.0
6
6
  platform: ruby
7
7
  authors:
8
8
  - David Calavera
@@ -10,7 +10,7 @@ autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
12
 
13
- date: 2011-03-27 00:00:00 -07:00
13
+ date: 2011-05-24 00:00:00 -07:00
14
14
  default_executable: trinidad
15
15
  dependencies:
16
16
  - !ruby/object:Gem::Dependency
@@ -21,7 +21,7 @@ dependencies:
21
21
  requirements:
22
22
  - - ">="
23
23
  - !ruby/object:Gem::Version
24
- version: 1.0.0
24
+ version: 1.0.1
25
25
  type: :runtime
26
26
  version_requirements: *id001
27
27
  - !ruby/object:Gem::Dependency
@@ -32,7 +32,7 @@ dependencies:
32
32
  requirements:
33
33
  - - ">="
34
34
  - !ruby/object:Gem::Version
35
- version: 1.0.6
35
+ version: 1.0.9
36
36
  type: :runtime
37
37
  version_requirements: *id002
38
38
  - !ruby/object:Gem::Dependency
@@ -95,6 +95,7 @@ files:
95
95
  - lib/trinidad/lifecycle/lifecycle_listener_default.rb
96
96
  - lib/trinidad/lifecycle/lifecycle_listener_host.rb
97
97
  - lib/trinidad/lifecycle/lifecycle_listener_war.rb
98
+ - lib/trinidad/lifecycle/takeover.rb
98
99
  has_rdoc: true
99
100
  homepage: http://github.com/calavera/trinidad
100
101
  licenses: []