manveru-innate 2009.02.06

Sign up to get free protection for your applications and to get access to all the features.
Files changed (101) hide show
  1. data/CHANGELOG +1409 -0
  2. data/COPYING +18 -0
  3. data/MANIFEST +100 -0
  4. data/README.md +485 -0
  5. data/Rakefile +139 -0
  6. data/example/app/retro_games.rb +57 -0
  7. data/example/app/whywiki_erb/layout/wiki.html.erb +15 -0
  8. data/example/app/whywiki_erb/spec/wiki.rb +19 -0
  9. data/example/app/whywiki_erb/start.rb +45 -0
  10. data/example/app/whywiki_erb/view/edit.html.erb +6 -0
  11. data/example/app/whywiki_erb/view/index.html.erb +10 -0
  12. data/example/custom_middleware.rb +43 -0
  13. data/example/error_handling.rb +31 -0
  14. data/example/hello.rb +12 -0
  15. data/example/howto_spec.rb +60 -0
  16. data/example/link.rb +35 -0
  17. data/example/providing_hash.rb +46 -0
  18. data/example/session.rb +42 -0
  19. data/innate.gemspec +118 -0
  20. data/lib/innate.rb +191 -0
  21. data/lib/innate/action.rb +156 -0
  22. data/lib/innate/adapter.rb +89 -0
  23. data/lib/innate/cache.rb +117 -0
  24. data/lib/innate/cache/api.rb +106 -0
  25. data/lib/innate/cache/drb.rb +58 -0
  26. data/lib/innate/cache/file_based.rb +39 -0
  27. data/lib/innate/cache/marshal.rb +17 -0
  28. data/lib/innate/cache/memory.rb +22 -0
  29. data/lib/innate/cache/yaml.rb +17 -0
  30. data/lib/innate/core_compatibility/basic_object.rb +9 -0
  31. data/lib/innate/core_compatibility/string.rb +3 -0
  32. data/lib/innate/current.rb +37 -0
  33. data/lib/innate/dynamap.rb +81 -0
  34. data/lib/innate/helper.rb +195 -0
  35. data/lib/innate/helper/aspect.rb +62 -0
  36. data/lib/innate/helper/cgi.rb +39 -0
  37. data/lib/innate/helper/flash.rb +36 -0
  38. data/lib/innate/helper/link.rb +55 -0
  39. data/lib/innate/helper/partial.rb +90 -0
  40. data/lib/innate/helper/redirect.rb +85 -0
  41. data/lib/innate/helper/send_file.rb +18 -0
  42. data/lib/innate/log.rb +23 -0
  43. data/lib/innate/log/color_formatter.rb +43 -0
  44. data/lib/innate/log/hub.rb +72 -0
  45. data/lib/innate/mock.rb +49 -0
  46. data/lib/innate/node.rb +471 -0
  47. data/lib/innate/options.rb +91 -0
  48. data/lib/innate/options/dsl.rb +155 -0
  49. data/lib/innate/request.rb +165 -0
  50. data/lib/innate/response.rb +18 -0
  51. data/lib/innate/route.rb +109 -0
  52. data/lib/innate/session.rb +104 -0
  53. data/lib/innate/session/flash.rb +94 -0
  54. data/lib/innate/setup.rb +23 -0
  55. data/lib/innate/spec.rb +42 -0
  56. data/lib/innate/state.rb +22 -0
  57. data/lib/innate/state/accessor.rb +130 -0
  58. data/lib/innate/state/fiber.rb +68 -0
  59. data/lib/innate/state/thread.rb +39 -0
  60. data/lib/innate/traited.rb +20 -0
  61. data/lib/innate/trinity.rb +22 -0
  62. data/lib/innate/version.rb +3 -0
  63. data/lib/innate/view.rb +67 -0
  64. data/lib/innate/view/erb.rb +17 -0
  65. data/lib/innate/view/none.rb +9 -0
  66. data/lib/rack/middleware_compiler.rb +62 -0
  67. data/lib/rack/reloader.rb +192 -0
  68. data/spec/example/hello.rb +14 -0
  69. data/spec/example/link.rb +29 -0
  70. data/spec/helper.rb +2 -0
  71. data/spec/innate/cache/common.rb +45 -0
  72. data/spec/innate/cache/marshal.rb +5 -0
  73. data/spec/innate/cache/memory.rb +5 -0
  74. data/spec/innate/cache/yaml.rb +5 -0
  75. data/spec/innate/dynamap.rb +22 -0
  76. data/spec/innate/helper.rb +66 -0
  77. data/spec/innate/helper/aspect.rb +80 -0
  78. data/spec/innate/helper/cgi.rb +37 -0
  79. data/spec/innate/helper/flash.rb +148 -0
  80. data/spec/innate/helper/link.rb +82 -0
  81. data/spec/innate/helper/partial.rb +66 -0
  82. data/spec/innate/helper/redirect.rb +148 -0
  83. data/spec/innate/helper/send_file.rb +21 -0
  84. data/spec/innate/helper/view/aspect_hello.erb +1 -0
  85. data/spec/innate/helper/view/locals.erb +1 -0
  86. data/spec/innate/helper/view/loop.erb +4 -0
  87. data/spec/innate/helper/view/num.erb +1 -0
  88. data/spec/innate/helper/view/partial.erb +1 -0
  89. data/spec/innate/helper/view/recursive.erb +8 -0
  90. data/spec/innate/mock.rb +84 -0
  91. data/spec/innate/node.rb +180 -0
  92. data/spec/innate/node/bar.html +1 -0
  93. data/spec/innate/node/foo.html.erb +1 -0
  94. data/spec/innate/node/with_layout.erb +3 -0
  95. data/spec/innate/options.rb +90 -0
  96. data/spec/innate/parameter.rb +154 -0
  97. data/spec/innate/request.rb +73 -0
  98. data/spec/innate/route.rb +129 -0
  99. data/spec/innate/session.rb +59 -0
  100. data/spec/innate/traited.rb +55 -0
  101. metadata +160 -0
@@ -0,0 +1,89 @@
1
+ module Rack
2
+ module Handler
3
+ autoload :Thin, 'rack/handler/thin'
4
+ autoload :Ebb, 'ebb'
5
+ autoload :SwiftipliedMongrel, 'rack/handler/swiftiplied_mongrel'
6
+
7
+ register 'thin', 'Rack::Handler::Thin'
8
+ register 'ebb', 'Rack::Handler::Ebb'
9
+ register 'smongrel', 'Rack::Handler::SwiftipliedMongrel'
10
+ end
11
+ end
12
+
13
+ module Innate
14
+
15
+ # Lightweight wrapper around Rack::Handler, will apply our options in a
16
+ # unified manner and deal with adapters that don't like to do what we want or
17
+ # where Rack doesn't want to take a stand.
18
+
19
+ module Adapter
20
+ class << self
21
+
22
+ # Pass given app to the Handler, handler is chosen based on
23
+ # config.adapter option.
24
+ # If there is a method named start_name_of_adapter it will be run instead
25
+ # of the default run method of the handler, this makes it easy to define
26
+ # custom startup of handlers for your server of choice
27
+ def start(app, options = Innate.options)
28
+ adapter_name = options[:adapter].to_s.downcase
29
+ config = { :Host => options[:host], :Port => options[:port] }
30
+ Log.debug "Innate uses #{adapter_name}"
31
+
32
+ if respond_to?(method = "start_#{adapter_name}")
33
+ send(method, app, config)
34
+ else
35
+ Rack::Handler.get(adapter_name).run(app, config)
36
+ end
37
+ end
38
+
39
+ # Due to buggy autoload on Ruby 1.8 we have to require 'ebb' manually.
40
+ # This most likely happens because autoload doesn't respect the require
41
+ # of rubygems and uses the C require directly.
42
+ def start_ebb(app, config)
43
+ require 'ebb'
44
+ Rack::Handler.get('ebb').run(app, config)
45
+ end
46
+
47
+ # We want webrick to use our logger.
48
+
49
+ def start_webrick(app, config)
50
+ handler = Rack::Handler.get('webrick')
51
+ config = {
52
+ :BindAddress => config[:Host],
53
+ :Port => config[:Port],
54
+ :Logger => Log,
55
+ :AccessLog => [
56
+ [Log, ::WEBrick::AccessLog::COMMON_LOG_FORMAT],
57
+ [Log, ::WEBrick::AccessLog::REFERER_LOG_FORMAT]]
58
+ }
59
+
60
+ handler.run(app, config)
61
+ end
62
+
63
+ # Thin shouldn't give excessive output, especially not to $stdout
64
+
65
+ def start_thin(app, config)
66
+ require 'thin'
67
+ handler = Rack::Handler.get('thin')
68
+ ::Thin::Logging.silent = true
69
+ handler.run(app, config)
70
+ end
71
+
72
+ # swiftcore has its own handler outside of rack
73
+
74
+ def start_emongrel(app, config)
75
+ require 'swiftcore/evented_mongrel'
76
+ handler = Rack::Handler.get('emongrel')
77
+ handler.run(app, config)
78
+ end
79
+
80
+ # swiftcore has its own handler outside of rack
81
+
82
+ def start_smongrel(app, config)
83
+ require 'swiftcore/swiftiplied_mongrel'
84
+ handler = Rack::Handler.get('smongrel')
85
+ handler.run(app, config)
86
+ end
87
+ end
88
+ end
89
+ end
@@ -0,0 +1,117 @@
1
+ module Innate
2
+ # Cache manager and wrapper.
3
+ #
4
+ # Provides a convenient wrapper around caches to keep method name confusion
5
+ # at a minimum while still having short and meaningful method names for every
6
+ # cache instance.
7
+ #
8
+ # The default caching is specified in lib/innate.rb in the config section.
9
+ # At the time of writing it defaults to Innate::Cache::Memory but can be
10
+ # changed easily.
11
+ #
12
+ # Configuration has to be done before Innate::setup_dependencies is being
13
+ # called.
14
+ #
15
+ # Configuration:
16
+ #
17
+ # Innate.options.cache do |cache|
18
+ # cache.names = [:session, :user]
19
+ # cache.session = Innate::Cache::Marshal
20
+ # cache.user = Innate::Cache::YAML
21
+ # end
22
+ #
23
+ # Usage for storing:
24
+ #
25
+ # # Storing with a time to live (10 seconds)
26
+ # Innate::Cache.user.store(:manveru, "Michael Fellinger", :ttl => 10)
27
+ #
28
+ # # Storing indefinitely
29
+ # Innate::Cache.user[:Pistos] = "unknown"
30
+ # # or without :ttl argument
31
+ # Innate::Cache.user.store(:Pistos, "unknown")
32
+ #
33
+ # Usage for retrieving:
34
+ #
35
+ # # we stored this one for 10 seconds
36
+ # Innate::Cache.user.fetch(:manveru, 'not here anymore')
37
+ # # => "Michael Fellinger"
38
+ # sleep 11
39
+ # Innate::Cache.user.fetch(:manveru, 'not here anymore')
40
+ # # => "not here anymore"
41
+ #
42
+ # Innate::Cache.user[:Pistos]
43
+ # # => "unknown"
44
+ # Innate::Cache.user.fetch(:Pistos)
45
+ # # => "unknown"
46
+ #
47
+ #
48
+ # For more details and to find out how to implement your own cache please
49
+ # read the documentation of Innate::Cache::API
50
+ #
51
+ # NOTE:
52
+ # * Some caches might expose their contents for everyone else on the same
53
+ # system, or even on connected systems. The rule as usual is, not to
54
+ # cache sensitive information.
55
+
56
+ class Cache
57
+ autoload :API, 'innate/cache/api'
58
+ autoload :DRb, 'innate/cache/drb'
59
+ autoload :YAML, 'innate/cache/yaml'
60
+ autoload :Memory, 'innate/cache/memory'
61
+ autoload :Marshal, 'innate/cache/marshal'
62
+ autoload :FileBased, 'innate/cache/file_based'
63
+
64
+ attr_reader :name, :instance
65
+
66
+ def initialize(name, klass = nil)
67
+ @name = name.to_s.dup.freeze
68
+
69
+ options = Innate.options
70
+
71
+ klass ||= options[:cache, @name.to_sym]
72
+ @instance = klass.new
73
+
74
+ @instance.cache_setup(
75
+ options.env.host,
76
+ options.env.user,
77
+ options.app.name,
78
+ @name
79
+ )
80
+ end
81
+
82
+ def self.setup
83
+ Innate.options.cache.names.each{|name| add(name) }
84
+ end
85
+
86
+ def self.register(cache)
87
+ key = cache.name
88
+ source = "def self.%s() @%s; end
89
+ def self.%s=(o) @%s = o; end" % [key, key, key, key]
90
+ self.class_eval(source, __FILE__, __LINE__)
91
+
92
+ self.send("#{key}=", cache)
93
+ end
94
+
95
+ def self.add(name)
96
+ register(new(name))
97
+ end
98
+
99
+ def clear
100
+ instance.cache_clear
101
+ end
102
+
103
+ def delete(*keys)
104
+ instance.cache_delete(*keys)
105
+ end
106
+
107
+ def fetch(key, default = nil)
108
+ instance.cache_fetch(key, default)
109
+ end
110
+ alias [] fetch
111
+
112
+ def store(key, value, options = {})
113
+ instance.cache_store(key, value, options)
114
+ end
115
+ alias []= store
116
+ end
117
+ end
@@ -0,0 +1,106 @@
1
+ module Innate
2
+ class Cache
3
+
4
+ # This is the API every Cache has to conform to.
5
+ #
6
+ # The default behaviour is tailored for the Memory cache, override any
7
+ # behaviour as you need.
8
+ #
9
+ # +key+ may be a String or Symbol
10
+ # +value+ is a Hash of serializable (as according to Marshal) objects
11
+ #
12
+ # Every cache instance has to respond to:
13
+ #
14
+ # ::new()
15
+ # #cache_setup(hostname, username, appname, cachename)
16
+ # #cache_clear()
17
+ # #cache_delete(*keys)
18
+ # #cache_fetch(key, default = nil)
19
+ # #cache_store(key, value, options = {})
20
+ #
21
+ # We are prefixing cache_ to make the intent clear and implementation
22
+ # easier, as there may be existing behaviour associated with the
23
+ # non-prefixed version.
24
+ #
25
+ # Also note that we create one instance per cache name-space.
26
+ module API
27
+ # Executed after #initialize and before any other method.
28
+ #
29
+ # Some parameters identifying the current process will be passed so
30
+ # caches that act in one global name-space can use them as a prefix.
31
+ #
32
+ # Treat all arguments as Strings.
33
+ #
34
+ # +hostname+ the hostname of the machine.
35
+ # +username+ user executing this process.
36
+ # +appname+ identifier for the application being executed.
37
+ # +cachename+ name-space of the cache, like 'session' or 'action'
38
+ def cache_setup(hostname, username, appname, cachename)
39
+ end
40
+
41
+ # Remove all key/value pairs from the cache.
42
+ # Should behave as if #delete had been called with all +keys+ as argument.
43
+ def cache_clear
44
+ clear
45
+ end
46
+
47
+ # Remove the corresponding key/value pair for each key passed.
48
+ # If removing is not an option it should set the corresponding value to nil.
49
+ #
50
+ # If only one key was deleted, answer with the corresponding value.
51
+ # If multiple keys were deleted, answer with an Array containing the values.
52
+ def cache_delete(key, *keys)
53
+ if keys.empty?
54
+ if value = yield(key)
55
+ value[:value]
56
+ end
57
+ else
58
+ [key, *keys].map{|k| cache_delete(k) }
59
+ end
60
+ end
61
+
62
+ # Answer with the value associated with the +key+, +nil+ if not found or
63
+ # expired.
64
+ def cache_fetch(key, default = nil)
65
+ value = default
66
+
67
+ if entry = yield(key)
68
+ if expires = entry[:expires]
69
+ if expires > Time.now
70
+ value = entry[:value]
71
+ else
72
+ cache_delete(key)
73
+ end
74
+ else
75
+ value = entry[:value]
76
+ end
77
+ end
78
+
79
+ return value
80
+ end
81
+
82
+ # Set +key+ to +value+.
83
+ #
84
+ # +options+ may be one of:
85
+ # :ttl => time to live in seconds if given in Numeric
86
+ # infinite or maximum if not given
87
+ #
88
+ # Usage:
89
+ # Cache.value.store(:num, 3, :ttl => 20)
90
+ # Cache.value.fetch(:num) # => 3
91
+ # sleep 21
92
+ # Cache.value.fetch(:num) # => nil
93
+ #
94
+ def cache_store(key, value, options = {})
95
+ ttl = options[:ttl]
96
+
97
+ value_hash = {:value => value}
98
+ value_hash[:expires] = Time.now + ttl if ttl
99
+
100
+ yield(key, value_hash)
101
+
102
+ return value
103
+ end
104
+ end
105
+ end
106
+ end
@@ -0,0 +1,58 @@
1
+ require 'drb'
2
+
3
+ module Innate
4
+ module Cache
5
+
6
+ # Cache utilizing a DRb server.
7
+ #
8
+ # You will need to run a corresponding DRb server to use this cache. The
9
+ # example below is using a normal Hash, but it is recommended to use a
10
+ # thread-safe alternative like SyncHash.
11
+ #
12
+ # Example for DRb server:
13
+ #
14
+ # require 'drb'
15
+ #
16
+ # URI = "druby://127.0.0.1:9069"
17
+ # CACHE = {}
18
+ #
19
+ # $SAFE = 1 # disable eval and friends
20
+ #
21
+ # DRb.start_service(URI, CACHE)
22
+ # DRb.thread.join
23
+ #
24
+ # Usage for all caches:
25
+ #
26
+ # Innate.options.cache.default = Innate::Cache::DRb
27
+ #
28
+ # Usage for sessions only:
29
+ #
30
+ # Innate.options.cache.session = Innate::Cache::DRb
31
+ class DRb
32
+ include Cache::API
33
+
34
+ OPTIONS = {:address => '127.0.0.1', :port => 9069}
35
+
36
+ def cache_setup(*args)
37
+ address, port = OPTIONS.values_at(:address, :port)
38
+ @store = DRbObject.new(nil, "druby://#{address}:#{port}")
39
+ end
40
+
41
+ def cache_clear
42
+ @store.clear
43
+ end
44
+
45
+ def cache_store(*args)
46
+ super{|key, value| @store[key] = value }
47
+ end
48
+
49
+ def cache_fetch(*args)
50
+ super{|key| @store[key] }
51
+ end
52
+
53
+ def cache_delete(*args)
54
+ super{|key| @store.delete(key) }
55
+ end
56
+ end
57
+ end
58
+ end
@@ -0,0 +1,39 @@
1
+ module Innate
2
+ class Cache
3
+
4
+ # Used by caches that serialize their contents to the filesystem.
5
+ module FileBased
6
+ def cache_setup(*args)
7
+ @prefix = args.compact.join('-')
8
+
9
+ @dir = File.join(Dir.tmpdir, self.class::DIR)
10
+ FileUtils.mkdir_p(@dir)
11
+
12
+ @filename = File.join(@dir, @prefix + self.class::EXT)
13
+ @store = self.class::STORE.new(@filename)
14
+ end
15
+
16
+ def cache_clear
17
+ FileUtils.mkdir_p(@dir)
18
+ FileUtils.rm_f(@filename)
19
+ @store = self.class::STORE.new(@filename)
20
+ end
21
+
22
+ def cache_store(*args)
23
+ super{|key, value| transaction{|store| store[key] = value } }
24
+ end
25
+
26
+ def cache_fetch(*args)
27
+ super{|key| transaction{|store| store[key] } }
28
+ end
29
+
30
+ def cache_delete(*args)
31
+ super{|key| transaction{|store| store.delete(key) } }
32
+ end
33
+
34
+ def transaction(&block)
35
+ Innate.sync{ @store.transaction(&block) }
36
+ end
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,17 @@
1
+ require 'pstore'
2
+
3
+ module Innate
4
+ class Cache
5
+ # Keeps every cache in a separate file like this:
6
+ #
7
+ # /tmp/innate-cache-marshal/delta-manveru-session.marshal
8
+ class Marshal
9
+ include Cache::API
10
+ include Cache::FileBased
11
+
12
+ STORE = ::PStore
13
+ DIR = 'innate-cache-marshal'
14
+ EXT = '.marshal'
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,22 @@
1
+ module Innate
2
+ class Cache
3
+ # Memory cache is simply a Hash with the Cache::API, it's the reference
4
+ # implementation for every other cache.
5
+
6
+ class Memory < Hash
7
+ include Cache::API
8
+
9
+ def cache_store(*args)
10
+ super{|key, value| self[key] = value }
11
+ end
12
+
13
+ def cache_fetch(*args)
14
+ super{|key| self[key] }
15
+ end
16
+
17
+ def cache_delete(*args)
18
+ super{|key| delete(key) }
19
+ end
20
+ end
21
+ end
22
+ end