trinidad 1.1.1 → 1.2.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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: []