dyoder-waves 0.7.7 → 0.8.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 (171) hide show
  1. data/bin/waves +19 -56
  2. data/doc/HISTORY +1 -0
  3. data/doc/LICENSE +22 -0
  4. data/doc/README +1 -0
  5. data/doc/VERSION +1 -0
  6. data/lib/caches/file.rb +48 -0
  7. data/lib/caches/memcached.rb +40 -0
  8. data/lib/caches/simple.rb +25 -0
  9. data/lib/caches/synchronized.rb +25 -0
  10. data/lib/commands/console.rb +35 -0
  11. data/lib/commands/generate.rb +52 -0
  12. data/lib/commands/help.rb +5 -0
  13. data/lib/commands/{waves-server.rb → server.rb} +16 -3
  14. data/lib/dispatchers/base.rb +21 -20
  15. data/lib/dispatchers/default.rb +11 -63
  16. data/lib/ext/float.rb +13 -0
  17. data/lib/{utilities → ext}/hash.rb +2 -2
  18. data/lib/{utilities → ext}/integer.rb +5 -2
  19. data/lib/ext/kernel.rb +20 -0
  20. data/lib/ext/module.rb +20 -0
  21. data/lib/{utilities → ext}/object.rb +3 -5
  22. data/lib/ext/string.rb +20 -0
  23. data/lib/ext/symbol.rb +11 -0
  24. data/lib/ext/tempfile.rb +5 -0
  25. data/lib/foundations/classic.rb +64 -0
  26. data/lib/foundations/compact.rb +50 -0
  27. data/lib/helpers/basic.rb +11 -0
  28. data/lib/helpers/doc_type.rb +34 -0
  29. data/lib/helpers/extended.rb +21 -0
  30. data/lib/helpers/form.rb +3 -1
  31. data/lib/helpers/formatting.rb +3 -3
  32. data/lib/helpers/layouts.rb +37 -0
  33. data/lib/helpers/model.rb +8 -4
  34. data/lib/helpers/view.rb +2 -4
  35. data/lib/layers/inflect/english.rb +67 -0
  36. data/lib/layers/mvc.rb +18 -18
  37. data/lib/layers/mvc/controllers.rb +41 -0
  38. data/lib/layers/mvc/extensions.rb +52 -0
  39. data/lib/layers/orm/{active_record.rb → providers/active_record.rb} +12 -18
  40. data/lib/layers/orm/{active_record → providers/active_record}/migrations/empty.rb.erb +0 -0
  41. data/lib/layers/orm/{active_record → providers/active_record}/tasks/generate.rb +1 -1
  42. data/lib/layers/orm/{active_record → providers/active_record}/tasks/schema.rb +1 -1
  43. data/lib/layers/orm/{data_mapper.rb → providers/data_mapper.rb} +3 -4
  44. data/lib/layers/orm/providers/filebase.rb +25 -0
  45. data/lib/layers/orm/{sequel.rb → providers/sequel.rb} +16 -12
  46. data/lib/layers/orm/{sequel → providers/sequel}/migrations/empty.rb.erb +0 -0
  47. data/lib/layers/orm/{sequel → providers/sequel}/tasks/generate.rb +5 -3
  48. data/lib/layers/orm/{sequel → providers/sequel}/tasks/schema.rb +2 -2
  49. data/lib/{renderers → layers/renderers}/erubis.rb +10 -13
  50. data/lib/layers/renderers/haml.rb +47 -0
  51. data/lib/layers/renderers/markaby.rb +29 -0
  52. data/lib/matchers/accept.rb +21 -0
  53. data/lib/matchers/base.rb +30 -0
  54. data/lib/matchers/content_type.rb +17 -0
  55. data/lib/matchers/path.rb +67 -0
  56. data/lib/matchers/query.rb +21 -0
  57. data/lib/matchers/request.rb +27 -0
  58. data/lib/matchers/resource.rb +19 -0
  59. data/lib/matchers/traits.rb +19 -0
  60. data/lib/matchers/uri.rb +20 -0
  61. data/lib/renderers/mixin.rb +15 -29
  62. data/lib/resources/mixin.rb +132 -0
  63. data/lib/resources/paths.rb +34 -0
  64. data/lib/runtime/configuration.rb +55 -135
  65. data/lib/runtime/console.rb +4 -1
  66. data/lib/runtime/logger.rb +24 -48
  67. data/lib/runtime/mime_types.rb +516 -2
  68. data/lib/runtime/mocks.rb +14 -0
  69. data/lib/runtime/monitor.rb +32 -0
  70. data/lib/runtime/request.rb +107 -39
  71. data/lib/runtime/response.rb +5 -2
  72. data/lib/runtime/response_mixin.rb +43 -22
  73. data/lib/runtime/runtime.rb +67 -0
  74. data/lib/runtime/server.rb +14 -101
  75. data/lib/runtime/session.rb +4 -43
  76. data/lib/runtime/worker.rb +86 -0
  77. data/lib/servers/base.rb +42 -0
  78. data/lib/servers/mongrel.rb +13 -0
  79. data/lib/servers/webrick.rb +13 -0
  80. data/lib/tasks/gem.rb +1 -0
  81. data/lib/tasks/generate.rb +67 -62
  82. data/lib/views/errors.rb +49 -0
  83. data/lib/views/mixin.rb +34 -82
  84. data/lib/waves.rb +36 -55
  85. data/samples/blog/Rakefile +25 -0
  86. data/samples/blog/configurations/default.rb +11 -0
  87. data/samples/blog/configurations/development.rb +29 -0
  88. data/samples/blog/configurations/production.rb +26 -0
  89. data/samples/blog/models/comment.rb +23 -0
  90. data/samples/blog/models/entry.rb +31 -0
  91. data/samples/blog/public/css/site.css +13 -0
  92. data/samples/blog/public/javascript/jquery-1.2.6.min.js +32 -0
  93. data/samples/blog/public/javascript/site.js +13 -0
  94. data/samples/blog/resources/entry.rb +39 -0
  95. data/samples/blog/resources/map.rb +9 -0
  96. data/samples/blog/schema/migrations/001_initial_schema.rb +17 -0
  97. data/samples/blog/schema/migrations/002_add_comments.rb +18 -0
  98. data/samples/blog/schema/migrations/templates/empty.rb.erb +9 -0
  99. data/samples/blog/startup.rb +8 -0
  100. data/samples/blog/templates/comment/add.mab +12 -0
  101. data/samples/blog/templates/comment/list.mab +6 -0
  102. data/samples/blog/templates/entry/edit.mab +14 -0
  103. data/samples/blog/templates/entry/list.mab +16 -0
  104. data/samples/blog/templates/entry/show.mab +18 -0
  105. data/samples/blog/templates/entry/summary.mab +9 -0
  106. data/samples/blog/templates/errors/not_found_404.mab +7 -0
  107. data/{app → samples/blog}/templates/errors/server_error_500.mab +0 -0
  108. data/samples/blog/templates/layouts/default.mab +19 -0
  109. data/samples/blog/templates/waves/status.mab +85 -0
  110. data/templates/classic/Rakefile +130 -0
  111. data/templates/classic/configurations/default.rb.erb +9 -0
  112. data/{app → templates/classic}/configurations/development.rb.erb +3 -7
  113. data/{app → templates/classic}/configurations/production.rb.erb +3 -4
  114. data/templates/classic/resources/map.rb.erb +8 -0
  115. data/templates/classic/startup.rb.erb +11 -0
  116. data/{app → templates/classic}/templates/errors/not_found_404.mab +0 -0
  117. data/templates/classic/templates/errors/server_error_500.mab +2 -0
  118. data/{app → templates/classic}/templates/layouts/default.mab +0 -0
  119. data/templates/compact/startup.rb.erb +11 -0
  120. metadata +967 -144
  121. data/app/Rakefile +0 -14
  122. data/app/bin/waves-console +0 -4
  123. data/app/bin/waves-server +0 -4
  124. data/app/configurations/mapping.rb.erb +0 -13
  125. data/app/controllers/.gitignore +0 -0
  126. data/app/doc/.gitignore +0 -0
  127. data/app/helpers/.gitignore +0 -0
  128. data/app/lib/application.rb.erb +0 -5
  129. data/app/lib/tasks/.gitignore +0 -0
  130. data/app/log/.gitignore +0 -0
  131. data/app/models/.gitignore +0 -0
  132. data/app/public/css/.gitignore +0 -0
  133. data/app/public/flash/.gitignore +0 -0
  134. data/app/public/images/.gitignore +0 -0
  135. data/app/public/javascript/.gitignore +0 -0
  136. data/app/schema/migrations/.gitignore +0 -0
  137. data/app/startup.rb +0 -5
  138. data/app/tmp/sessions/.gitignore +0 -0
  139. data/app/views/.gitignore +0 -0
  140. data/bin/waves-console +0 -4
  141. data/bin/waves-server +0 -4
  142. data/lib/commands/waves-console.rb +0 -21
  143. data/lib/controllers/base.rb +0 -11
  144. data/lib/controllers/mixin.rb +0 -165
  145. data/lib/foundations/default.rb +0 -26
  146. data/lib/foundations/simple.rb +0 -30
  147. data/lib/helpers/asset_helper.rb +0 -67
  148. data/lib/helpers/common.rb +0 -66
  149. data/lib/helpers/default.rb +0 -13
  150. data/lib/helpers/number_helper.rb +0 -25
  151. data/lib/helpers/tag_helper.rb +0 -58
  152. data/lib/helpers/url_helper.rb +0 -77
  153. data/lib/layers/default_errors.rb +0 -26
  154. data/lib/layers/orm/filebase.rb +0 -22
  155. data/lib/layers/simple.rb +0 -35
  156. data/lib/layers/simple_errors.rb +0 -23
  157. data/lib/mapping/mapping.rb +0 -289
  158. data/lib/mapping/pretty_urls.rb +0 -96
  159. data/lib/renderers/markaby.rb +0 -33
  160. data/lib/runtime/application.rb +0 -69
  161. data/lib/runtime/blackboard.rb +0 -57
  162. data/lib/runtime/debugger.rb +0 -9
  163. data/lib/runtime/response_proxy.rb +0 -30
  164. data/lib/tasks/cluster.rb +0 -26
  165. data/lib/utilities/inflect.rb +0 -110
  166. data/lib/utilities/inflect/english.rb +0 -84
  167. data/lib/utilities/module.rb +0 -21
  168. data/lib/utilities/proc.rb +0 -16
  169. data/lib/utilities/string.rb +0 -61
  170. data/lib/utilities/symbol.rb +0 -10
  171. data/lib/views/base.rb +0 -9
@@ -0,0 +1,14 @@
1
+ module Waves
2
+ module Mocks
3
+
4
+ def dispatcher ; Waves::Dispatchers::Default ; end
5
+ def request ; Rack::MockRequest.new( dispatcher.new ) ; end
6
+ def env( uri, opts ) ; Rack::MockRequest.env_for( uri, opts ) ; end
7
+ def get( uri, opts = {} ) ; request.get( uri, opts ) ; end
8
+ def put( uri, opts = {} ) ; request.put( uri, opts ) ; end
9
+ def post( uri, opts = {} ) ; request.post( uri, opts ) ; end
10
+ def delete( uri, opts = {} ) ; request.delete( uri, opts ) ; end
11
+ def head( uri, opts = {} ) ; request.request( 'HEAD', uri, opts ) ; end
12
+
13
+ end
14
+ end
@@ -0,0 +1,32 @@
1
+ module Waves
2
+
3
+ class Monitor
4
+
5
+ def initialize( options ) ; @options = options ; end
6
+
7
+ def start( manager )
8
+ @manager = manager
9
+ @pid = fork do
10
+ safe_trap('INT','TERM') do
11
+ Waves::Logger.info "Monitor stopped ..."
12
+ exit
13
+ end
14
+ loop { fix unless check ; sleep interval }
15
+ end
16
+ end
17
+
18
+ def fix
19
+ @manager.restart
20
+ end
21
+
22
+ # you need to implement this
23
+ def check ; true ; end
24
+
25
+ # defaults to every 60 seconds
26
+ def interval ; @options[ :interval ] ; end
27
+
28
+ def stop ; Process.kill( 'INT', @pid ) ; end
29
+
30
+ end
31
+
32
+ end
@@ -1,78 +1,146 @@
1
1
  module Waves
2
- # Waves::Request represents an HTTP request and provides convenient methods for accessing request attributes. See Rack::Request for documentation of any method not defined here.
2
+
3
+ # Waves::Request represents an HTTP request and provides convenient methods for accessing request attributes.
4
+ # See Rack::Request for documentation of any method not defined here.
5
+
3
6
  class Request
4
7
 
5
8
  class ParseError < Exception ; end
6
9
 
7
- attr_reader :response, :session, :blackboard
10
+ class Query ; include Attributes ; end
11
+
12
+ attr_reader :response, :session, :traits
8
13
 
9
14
  # Create a new request. Takes a env parameter representing the request passed in from Rack.
10
15
  # You shouldn't need to call this directly.
11
16
  def initialize( env )
12
- @request = Rack::Request.new( env )
17
+ @traits = Class.new { include Attributes }.new( :waves => {} )
18
+ @request = Rack::Request.new( env ).freeze
13
19
  @response = Waves::Response.new( self )
14
20
  @session = Waves::Session.new( self )
15
- @blackboard = Waves::Blackboard.new( self )
16
21
  end
17
22
 
18
23
  def rack_request; @request; end
19
-
20
- # Accessor not explicitly defined by Waves::Request are delegated to Rack::Request.
21
- # Check the Rack documentation for more information.
22
- def method_missing(name,*args)
23
- @request.send(name,*args)
24
+
25
+ # Methods delegated directly to rack
26
+ %w( url scheme host port body query_string content_type media_type content_length referer ).each do |m|
27
+ define_method( m ) { @request.send( m ) }
24
28
  end
25
29
 
26
30
  # The request path (PATH_INFO). Ex: +/entry/2008-01-17+
27
- def path
28
- @request.path_info
29
- end
30
-
31
- # The request domain. Ex: +www.fubar.com+
32
- def domain
33
- @request.host
34
- end
35
-
36
- # The request content type.
37
- def content_type
38
- @request.env['CONTENT_TYPE']
39
- end
31
+ def path ; @request.path_info ; end
40
32
 
41
- # Supported request methods
42
- METHODS = %w{get post put delete head options trace}
33
+ # Access to "params" - aka the query string - as a hash
34
+ def query ; @request.params ; end
35
+
36
+ alias_method :params, :query
37
+ alias_method :domain, :host
43
38
 
44
- # Override the Rack methods for querying the request method.
45
- METHODS.each do |method|
46
- class_eval "def #{method}?; method == :#{method} end"
47
- end
39
+ # Request method predicates, defined in terms of #method.
40
+ %w{get post put delete head options trace}.
41
+ each { |m| define_method( m ) { method.to_s == m } }
48
42
 
49
43
  # The request method. Because browsers can't send PUT or DELETE
50
44
  # requests this can be simulated by sending a POST with a hidden
51
45
  # field named '_method' and a value with 'PUT' or 'DELETE'. Also
52
46
  # accepted is when a query parameter named '_method' is provided.
53
47
  def method
54
- @method ||= begin
55
- request_method = @request.request_method.downcase
56
- if request_method == 'post'
57
- _method = @request['_method']
58
- _method.downcase! if _method
59
- METHODS.include?(_method) ? _method.intern : :post
60
- else
61
- request_method.intern
62
- end
63
- end
48
+ @method ||= ( ( ( m = @request.request_method.downcase ) == 'post' and
49
+ ( n = @request['_method'] ) ) ? n.downcase : m ).intern
50
+ end
51
+
52
+ def []( key ) ; @request.env[ key.to_s.upcase ] ; end
53
+
54
+ # access HTTP headers as methods
55
+ def method_missing( name, *args, &body )
56
+ return super unless args.empty? and body.nil?
57
+ key = "HTTP_#{name.to_s.upcase}"
58
+ @request.env[ key ] if @request.env.has_key?( key )
64
59
  end
65
60
 
66
61
  # Raise a not found exception.
67
62
  def not_found
68
- raise Waves::Dispatchers::NotFoundError.new( @request.url + ' not found.' )
63
+ raise Waves::Dispatchers::NotFoundError, "#{@request.url} not found."
69
64
  end
70
65
 
71
66
  # Issue a redirect for the given path.
72
67
  def redirect( path, status = '302' )
73
68
  raise Waves::Dispatchers::Redirect.new( path, status )
74
69
  end
70
+
71
+ class Accept < Array
72
+
73
+ def =~(arg) ; self.include? arg ; end
74
+ def ===(arg) ; self.include? arg ; end
75
+
76
+ def include?(arg)
77
+ return arg.any? { |pat| self.include?( pat ) } if arg.is_a? Array
78
+ arg = arg.to_s.split('/')
79
+ self.any? do |entry|
80
+ false if entry == '*/*' or entry == '*'
81
+ entry = entry.split('/')
82
+ if arg.size == 1 # implicit wildcard in arg
83
+ arg[0] == entry[0] or arg[0] == entry[1]
84
+ else
85
+ arg == entry
86
+ end
87
+ end
88
+ end
89
+
90
+ def self.parse(string)
91
+ string.split(',').inject(self.new) { |a, entry| a << entry.split( ';' ).first.strip; a }
92
+ end
93
+
94
+ def default
95
+ return 'text/html' if self.include?('text/html')
96
+ find { |entry| ! entry.match(/\*/) } || 'text/html'
97
+ end
98
+
99
+ end
100
+
101
+ # this is a hack - need to incorporate browser variations for "accept" here ...
102
+ # def accept ; Accept.parse(@request.env['HTTP_ACCEPT']).unshift( Waves.config.mime_types[ path ] ).compact.uniq ; end
103
+ def accept ; @accept ||= Accept.parse( Waves.config.mime_types[ path.downcase ] || 'text/html' ) ; end
104
+ def accept_charset ; @charset ||= Accept.parse(@request.env['HTTP_ACCEPT_CHARSET']) ; end
105
+ def accept_language ; @lang ||= Accept.parse(@request.env['HTTP_ACCEPT_LANGUAGE']) ; end
106
+
107
+ module Utilities
108
+
109
+ def self.destructure( hash )
110
+ destructured = {}
111
+ hash.keys.map { |key| key.split('.') }.each do |keys|
112
+ destructure_with_array_keys(hash, '', keys, destructured)
113
+ end
114
+ destructured
115
+ end
75
116
 
117
+ private
118
+
119
+ def self.destructure_with_array_keys( hash, prefix, keys, destructured )
120
+ if keys.length == 1
121
+ key = "#{prefix}#{keys.first}"
122
+ val = hash[key]
123
+ destructured[keys.first.intern] = case val
124
+ when String
125
+ val.strip
126
+ when Hash, Array
127
+ val
128
+ when Array
129
+ val
130
+ when nil
131
+ raise key.inspect
132
+ end
133
+ else
134
+ destructured = ( destructured[keys.first.intern] ||= {} )
135
+ new_prefix = "#{prefix}#{keys.shift}."
136
+ destructure_with_array_keys( hash, new_prefix, keys, destructured )
137
+ end
138
+ end
139
+
140
+ end
141
+
76
142
  end
77
143
 
78
144
  end
145
+
146
+
@@ -1,7 +1,10 @@
1
1
  module Waves
2
+
2
3
  # Waves::Response represents an HTTP response and has methods for constructing a response.
3
4
  # These include setters for +content_type+, +content_length+, +location+, and +expires+
4
- # headers. You may also set the headers directly using the [] operator. See Rack::Response for documentation of any method not defined here.
5
+ # headers. You may also set the headers directly using the [] operator.
6
+ # See Rack::Response for documentation of any method not defined here.
7
+
5
8
  class Response
6
9
 
7
10
  attr_reader :request
@@ -28,7 +31,7 @@ module Waves
28
31
  # attempt to further modify the response once this method is called. You don't usually
29
32
  # need to call it yourself, since it is called by the dispatcher once request processing
30
33
  # is finished.
31
- def finish ; request.session.save ; @response.finish ; end
34
+ def finish ; @response.finish ; end
32
35
 
33
36
  # Methods not explicitly defined by Waves::Response are delegated to Rack::Response.
34
37
  # Check the Rack documentation for more informations
@@ -3,36 +3,57 @@ module Waves
3
3
  # Defines a set of methods that simplify accessing common request and response methods.
4
4
  # These include methods not necessarily associated with the Waves::Request and Waves::Response
5
5
  # objects, but which may still be useful for constructing a response.
6
- #
7
6
  # This mixin assumes that a @request@ accessor already exists.
8
- module ResponseMixin
7
+
8
+ module ResponseMixin
9
+
9
10
  # Access the response.
10
11
  def response; request.response; end
11
- # Access the request parameters.
12
- def params; request.params; end
13
- # Access the request session.
14
- def session; request.session; end
15
- # Access the request path.
16
- def path; request.path; end
17
- # Access the request url.
18
- def url; request.url; end
19
- # Access the request domain.
20
- def domain; request.domain; end
12
+
13
+ def resource ; traits.waves.resource ; end
14
+
15
+ def traits ; request.traits ; end
16
+
17
+ # Access to the query string as a object where the keys are accessors
18
+ # You can still access the original query as request.query
19
+ def query ; @query ||= Waves::Request::Query.new( request.query ) ; end
20
+
21
+ # Elements captured the path
22
+ def captured ; @captured ||= traits.waves.captured ; end
23
+
24
+ # Both the query and capture merged together
25
+ def params
26
+ query = captured ? request.query.merge( captured.to_h ) : request.query
27
+ @params ||= Waves::Request::Query.new( query )
28
+ end
29
+
30
+ %w( session path url domain not_found ).each do | m |
31
+ define_method( m ) { request.send( m ) }
32
+ end
33
+
21
34
  # Issue a redirect for the given location.
22
35
  def redirect(location, status = '302'); request.redirect(location, status); end
23
- # Access the primary application's models
24
- def models; Waves.application.models; end
25
- # Access the primary application's views
26
- def views; Waves.application.views; end
27
- # Access the primary application's controllers
28
- def controllers; Waves.application.controllers; end
29
- # Raise a "not found" exception.
30
- def not_found; request.not_found; end
31
36
  # Access the Waves::Logger.
32
37
  def log; Waves::Logger; end
33
- # Access the Blackboard
34
- def blackboard; request.blackboard; end
38
+ # access stuff from an app
39
+ def app_name ; self.class.rootname.snake_case.to_sym ; end
40
+ def app ; eval( "::#{app_name.to_s.camel_case}" ) ; end
41
+ def paths( rname = nil )
42
+ ( rname.nil? ? resource.class.paths : app::Resources[ rname ].paths ).new( request )
43
+ end
44
+
45
+ def basename ; @basename ||= path.sub(/\.([^\.]+)$/,'') ; end
35
46
 
47
+ def extension
48
+ @extension ||= if ( m = path.match(/\.([^\.]+)$/) )
49
+ m[1]
50
+ end
51
+ end
52
+
53
+ def render( path, assigns = {} )
54
+ Waves::Views::Base.new( request ).render( path, assigns )
55
+ end
56
+
36
57
  end
37
58
 
38
59
  end
@@ -0,0 +1,67 @@
1
+ module Waves
2
+
3
+ # A temporary measure until the applications "array" becomes a hash.
4
+ # Currently used to keep track of all loaded Waves applications.
5
+ class Applications < Array
6
+ def []( name ) ; self.find { |app| app == name.to_s.camel_case } ; end
7
+ end
8
+
9
+ def self.config; instance.config ; end
10
+
11
+ # The list of all loaded applications
12
+ def self.applications ; @applications ||= Applications.new ; end
13
+
14
+ # Access the principal Waves application.
15
+ def self.main ; applications.first ; end
16
+
17
+ # Register a module as a Waves application.
18
+ def self.<< ( app )
19
+ applications << app if Module === app
20
+ end
21
+
22
+ # Returns the most recently created instance of Waves::Runtime.
23
+ def self.instance ; Waves::Runtime.instance ; end
24
+
25
+ def self.version ; File.read( File.expand_path( "#{File.dirname(__FILE__)}/../../doc/VERSION" ) ) ; end
26
+ def self.license ; File.read( File.expand_path( "#{File.dirname(__FILE__)}/../../doc/LICENSE" ) ) ; end
27
+
28
+ def self.method_missing(name,*args,&block) ; instance.send(name,*args,&block) ; end
29
+
30
+ # A Waves::Runtime takes an inert application module and gives it concrete, pokeable form.
31
+ # Waves::Server and Waves::Console are types of runtime.
32
+ class Runtime
33
+
34
+ class << self; attr_accessor :instance; end
35
+
36
+ # Accessor for options passed to the runtime.
37
+ attr_reader :options
38
+
39
+ # Create a new Waves application instance.
40
+ def initialize( options={} )
41
+ @options = options
42
+ Dir.chdir options[:directory] if options[:directory]
43
+ Runtime.instance = self
44
+ end
45
+
46
+ # The 'mode' of the runtime determines which configuration it will run under.
47
+ def mode ; options[:mode]||:development ; end
48
+
49
+ # Returns true if debug was set to true in the current configuration.
50
+ def debug? ; options[:debugger] or config.debug ; end
51
+
52
+ # Returns the current configuration.
53
+ def config ; Waves.main::Configurations[ mode ] ; end
54
+
55
+ # Reload the modules specified in the current configuration.
56
+ def reload ; config.reloadable.each { |mod| mod.reload } ; end
57
+
58
+ # Start and / or access the Waves::Logger instance.
59
+ def log ; @log ||= Waves::Logger.start ; end
60
+
61
+ # Provides access to the server mutex for thread-safe operation.
62
+ def synchronize( &block ) ; ( @mutex ||= Mutex.new ).synchronize( &block ) ; end
63
+ def synchronize? ; !options[ :turbo ] ; end
64
+
65
+ end
66
+
67
+ end
@@ -1,107 +1,20 @@
1
1
  module Waves
2
- # You can run the Waves::Server via the +waves-server+ command or via <tt>rake cluster:start</tt>. Run <tt>waves-server --help</tt> for options on the <tt>waves-server</tt> command. The <tt>cluster:start</tt> task uses the +mode+ environment variable to determine the active configuration. You can define +port+ to run on a single port, or +ports+ (taking an array) to run on multiple ports.
3
- #
4
- # *Example*
5
- #
6
- # Assume that +ports+ is set in the development configuration like this:
7
- #
8
- # ports [ 2020, 2021, 2022 ]
9
- #
10
- # Then you could start up instances on all three ports using:
11
- #
12
- # rake cluster:start mode=development
13
- #
14
- # This is the equivalent of running:
15
- #
16
- # waves-server -c development -p 2020 -d
17
- # waves-server -c development -p 2021 -d
18
- # waves-server -c development -p 2022 -d
19
- #
20
- # The +cluster:stop+ task stops all of the instances.
21
- #
22
- class Server < Application
23
-
24
- # Access the server thread.
25
- attr_reader :thread
26
-
27
- # Access the host we're binding to (set via the configuration).
28
- def host ; options[:host] || config.host ; end
29
-
30
- # Access the port we're listening on (set via the configuration).
31
- def port ; options[:port] || config.port ; end
32
-
33
- # Run the server as a daemon. Corresponds to the -d switch on +waves-server+.
34
- def daemonize
35
- pwd = Dir.pwd
36
- Daemonize.daemonize( Waves::Logger.output )
37
- Dir.chdir(pwd)
38
- File.write( :log / "#{port}.pid", $$ )
39
- end
40
-
41
- def trap(signal)
42
- Kernel::trap(signal) { yield }
43
- Thread.new { loop {sleep 1} } if RUBY_PLATFORM =~ /mswin32/
44
- end
45
-
46
- # Start and / or access the Waves::Logger instance.
47
- def log
48
- @log ||= Waves::Logger.start
49
- end
50
-
51
- # Start the server.
52
- def start
53
- daemonize if options[:daemon]
54
- start_debugger if options[:debugger]
55
- log.info "** Waves Server starting on #{host}:#{port}"
56
- handler, options = config.handler
57
- handler.run( config.application.to_app, options ) do |server|
58
- @server = server
59
- self.trap('INT') { puts; stop } if @server.respond_to? :stop
60
- end
61
- end
62
-
63
- # Stop the server.
64
- def stop
65
- log.info "** Waves Server Stopping ..."
66
- if options[:daemon]
67
- pid_file = :log / $$ + '.pid'; FileUtils.rm( pid_file ) if File.exist?( pid_file )
68
- end
69
- @server.stop
70
- log.info "** Waves Server Stopped"
2
+
3
+ class Server < Worker
4
+
5
+ def start_tasks
6
+ @server = config.server.new( application, host, port )
7
+ @server.start
71
8
  end
72
-
73
- # Provides access to the server mutex for thread-safe operation.
74
- def synchronize( &block ) ; ( @mutex ||= Mutex.new ).synchronize( &block ) ; end
75
-
76
- class << self
77
- private :new, :dup, :clone
78
- # Start or restart the server.
79
- def run( options={} )
80
- @server.stop if @server; @server = new( options ); @server.start
81
- end
82
-
83
- # Allows us to access the Waves::Server instance.
84
- def method_missing(*args)
85
- @server.send(*args)
86
- end
87
-
88
- #-- Probably wouldn't need this if I added a block parameter to method_missing.
89
- def synchronize(&block) ; @server.synchronize(&block) ; end
90
- end
91
-
9
+
10
+ def stop_tasks ; @server.stop ; end
11
+
92
12
  private
93
13
 
94
- def start_debugger
95
- begin
96
- require 'ruby-debug'
97
- Debugger.start
98
- Debugger.settings[:autoeval] = true if Debugger.respond_to?(:settings)
99
- log.info "Debugger enabled"
100
- rescue Exception
101
- log.info "You need to install ruby-debug to run the server in debugging mode. With gems, use 'gem install ruby-debug'"
102
- exit
103
- end
104
- end
14
+ def application ; @app ||= config.application.to_app ; end
15
+ def port ; @port ||= options[:port] or config.port ; end
16
+ def host ; @host ||= options[:host] or config.host ; end
17
+
105
18
  end
106
19
 
107
- end
20
+ end