ernie 1.2.0 → 1.3.0

Sign up to get free protection for your applications and to get access to all the features.
data/History.txt CHANGED
@@ -1,3 +1,10 @@
1
+ = 1.3.0 / 2009-11-30
2
+ * API Additions
3
+ * Add loglevel for setting log level
4
+ * Add Ernie.auto_start bool
5
+ * Major changes
6
+ * Better logging granularity
7
+
1
8
  = 1.2.0 / 2009-11-23
2
9
  * API Additions
3
10
  * Add Ernie.expose
data/README.md CHANGED
@@ -32,18 +32,18 @@ Running
32
32
  -n, --number NUMBER Number of handler instances
33
33
  -d, --detached Run as a daemon
34
34
  -P, --pidfile PIDFILE Location to write pid file.
35
-
35
+
36
36
  Commands:
37
37
  <none> Start an Ernie server.
38
38
  reload-handlers Gracefully reload all of the the ruby handlers
39
39
  and use the new code for all subsequent requests.
40
40
  stats Print a list of connection and handler statistics.
41
-
41
+
42
42
  Examples:
43
43
  ernie -d -p 9999 -n 10 -h calc.rb
44
44
  Start the ernie server in the background on port 9999 with ten
45
45
  handlers, using the calc.rb handler file.
46
-
46
+
47
47
  ernie reload-handlers -p 9999
48
48
  Reload the handlers for the ernie server currently running on
49
49
  port 9999.
@@ -51,34 +51,56 @@ Running
51
51
  Example Handler
52
52
  ---------------
53
53
 
54
- Using the DSL:
54
+ Using a Ruby module and Ernie.expose:
55
55
 
56
56
  require 'ernie'
57
57
 
58
- mod(:calc) do
59
- fun(:add) do |a, b|
58
+ module Calc
59
+ def add(a, b)
60
60
  a + b
61
61
  end
62
62
  end
63
-
64
- Using Ernie.expose:
63
+
64
+ Ernie.expose(:calc, Calc)
65
+
66
+ Using the DSL (this will be deprecated in a future release):
65
67
 
66
68
  require 'ernie'
67
-
68
- module Calc
69
- def add(a, b)
69
+
70
+ mod(:calc) do
71
+ fun(:add) do |a, b|
70
72
  a + b
71
73
  end
72
74
  end
73
-
74
- Ernie.expose(:calc, Calc)
75
+
76
+
77
+ Logging
78
+ -------
79
+
80
+ You can have logging sent to a file by adding these lines to your handler:
81
+
82
+ logfile('/var/log/ernie.log')
83
+ loglevel(Logger::INFO)
84
+
85
+ This will log startup info, requests, and error messages to the log. Choosing
86
+ Logger::DEBUG will include the response (be careful, doing this can generate
87
+ very large log files).
88
+
89
+
90
+ Autostart
91
+ ---------
92
+
93
+ Normally Ernie handlers will become active after the file has been loaded in.
94
+ you can disable this behavior by setting:
95
+
96
+ Ernie.auto_start = false
75
97
 
76
98
 
77
99
  Example BERT-RPC call for above example
78
100
  ---------------------------------------
79
101
 
80
102
  -> {call, calc, add, [1, 2]}
81
-
103
+
82
104
  <- {reply, 3}
83
105
 
84
106
 
@@ -88,7 +110,7 @@ Using the BERTRPC gem to make calls to Ernie
88
110
  You can make BERT-RPC calls from Ruby with the [BERTRPC gem](http://github.com/mojombo/bertrpc):
89
111
 
90
112
  require 'bertrpc'
91
-
113
+
92
114
  svc = BERTRPC::Service.new('localhost', 8000)
93
115
  svc.call.calc.add(1, 2)
94
116
  # => 3
@@ -99,10 +121,14 @@ Contribute
99
121
 
100
122
  If you'd like to hack on Ernie, start by forking my repo on GitHub:
101
123
 
102
- http://github.com/mojombo/ernie
124
+ http://github.com/mojombo/ernie
125
+
126
+ To get all of the dependencies, install the gem first. To run ernie from
127
+ source, you must first build the Erlang code:
128
+
129
+ rake ebuild
103
130
 
104
- To get all of the dependencies, install the gem first. The best way to get
105
- your changes merged back into core is as follows:
131
+ The best way to get your changes merged back into core is as follows:
106
132
 
107
133
  1. Clone down your fork
108
134
  1. Create a topic branch to contain your change
@@ -118,4 +144,4 @@ your changes merged back into core is as follows:
118
144
  Copyright
119
145
  ---------
120
146
 
121
- Copyright (c) 2009 Tom Preston-Werner. See LICENSE for details.
147
+ Copyright (c) 2009 Tom Preston-Werner. See LICENSE for details.
data/VERSION.yml CHANGED
@@ -1,4 +1,5 @@
1
1
  ---
2
- :minor: 2
2
+ :minor: 3
3
+ :build:
3
4
  :patch: 0
4
5
  :major: 1
data/ernie.gemspec CHANGED
@@ -1,19 +1,19 @@
1
1
  # Generated by jeweler
2
- # DO NOT EDIT THIS FILE
3
- # Instead, edit Jeweler::Tasks in Rakefile, and run `rake gemspec`
2
+ # DO NOT EDIT THIS FILE DIRECTLY
3
+ # Instead, edit Jeweler::Tasks in rakefile, and run the gemspec command
4
4
  # -*- encoding: utf-8 -*-
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = %q{ernie}
8
- s.version = "1.2.0"
8
+ s.version = "1.3.0"
9
9
 
10
10
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
11
  s.authors = ["Tom Preston-Werner"]
12
- s.date = %q{2009-11-23}
12
+ s.date = %q{2009-11-30}
13
13
  s.default_executable = %q{ernie}
14
14
  s.email = %q{tom@mojombo.com}
15
15
  s.executables = ["ernie"]
16
- s.extensions = ["ext/extconf.rb"]
16
+ s.extensions = ["ext/extconf.rb", "ext/extconf.rb"]
17
17
  s.extra_rdoc_files = [
18
18
  "LICENSE",
19
19
  "README.md"
@@ -79,3 +79,4 @@ Gem::Specification.new do |s|
79
79
  s.add_dependency(%q<bertrpc>, [">= 1.0.0"])
80
80
  end
81
81
  end
82
+
data/examples/dsl.rb CHANGED
@@ -1,6 +1,9 @@
1
1
  $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
2
2
  require 'ernie'
3
3
 
4
+ # logfile('/tmp/ernie.log')
5
+ # loglevel(Logger::INFO)
6
+
4
7
  mod(:test) do
5
8
  # Add two numbers together
6
9
  fun(:add) do |a, b|
data/lib/ernie.rb CHANGED
@@ -4,12 +4,15 @@ require 'logger'
4
4
 
5
5
  class Ernie
6
6
  class << self
7
- attr_accessor :mods, :current_mod, :logger
7
+ attr_accessor :mods, :current_mod, :log
8
+ attr_accessor :auto_start
8
9
  end
9
10
 
10
11
  self.mods = {}
11
12
  self.current_mod = nil
12
- self.logger = nil
13
+ self.log = Logger.new(STDOUT)
14
+ self.log.level = Logger::INFO
15
+ self.auto_start = true
13
16
 
14
17
  # Record a module.
15
18
  # +name+ is the module Symbol
@@ -53,15 +56,15 @@ class Ernie
53
56
  #
54
57
  # Returns nothing
55
58
  def self.logfile(file)
56
- self.logger = Logger.new(file)
59
+ self.log = Logger.new(file)
57
60
  end
58
61
 
59
- # If logging is enabled, log the given text.
60
- # +text+ is the String to log
62
+ # Set the log level.
63
+ # +level+ is the Logger level (Logger::WARN, etc)
61
64
  #
62
65
  # Returns nothing
63
- def self.log(text)
64
- self.logger.info(text) if self.logger
66
+ def self.loglevel(level)
67
+ self.log.level = level
65
68
  end
66
69
 
67
70
  # Dispatch the request to the proper mod:fun.
@@ -114,8 +117,8 @@ class Ernie
114
117
  #
115
118
  # Loops forever
116
119
  def self.start
117
- self.log("Starting")
118
- self.log(self.mods.inspect)
120
+ self.log.info("(#{Process.pid}) Starting")
121
+ self.log.debug(self.mods.inspect)
119
122
 
120
123
  input = IO.new(3)
121
124
  output = IO.new(4)
@@ -126,31 +129,32 @@ class Ernie
126
129
  iruby = self.read_berp(input)
127
130
  unless iruby
128
131
  puts "Could not read BERP length header. Ernie server may have gone away. Exiting now."
132
+ self.log.info("(#{Process.pid}) Could not read BERP length header. Ernie server may have gone away. Exiting now.")
129
133
  exit!
130
134
  end
131
135
 
132
136
  if iruby.size == 4 && iruby[0] == :call
133
137
  mod, fun, args = iruby[1..3]
134
- self.log("-> " + iruby.inspect)
138
+ self.log.info("-> " + iruby.inspect)
135
139
  begin
136
140
  res = self.dispatch(mod, fun, args)
137
141
  oruby = t[:reply, res]
138
- self.log("<- " + oruby.inspect)
142
+ self.log.debug("<- " + oruby.inspect)
139
143
  write_berp(output, oruby)
140
144
  rescue ServerError => e
141
145
  oruby = t[:error, t[:server, 0, e.class.to_s, e.message, e.backtrace]]
142
- self.log("<- " + oruby.inspect)
143
- self.log(e.backtrace.join("\n"))
146
+ self.log.error("<- " + oruby.inspect)
147
+ self.log.error(e.backtrace.join("\n"))
144
148
  write_berp(output, oruby)
145
149
  rescue Object => e
146
150
  oruby = t[:error, t[:user, 0, e.class.to_s, e.message, e.backtrace]]
147
- self.log("<- " + oruby.inspect)
148
- self.log(e.backtrace.join("\n"))
151
+ self.log.error("<- " + oruby.inspect)
152
+ self.log.error(e.backtrace.join("\n"))
149
153
  write_berp(output, oruby)
150
154
  end
151
155
  elsif iruby.size == 4 && iruby[0] == :cast
152
156
  mod, fun, args = iruby[1..3]
153
- self.log("-> " + [:cast, mod, fun, args].inspect)
157
+ self.log.info("-> " + [:cast, mod, fun, args].inspect)
154
158
  begin
155
159
  self.dispatch(mod, fun, args)
156
160
  rescue Object => e
@@ -158,9 +162,9 @@ class Ernie
158
162
  end
159
163
  write_berp(output, t[:noreply])
160
164
  else
161
- self.log("-> " + iruby.inspect)
165
+ self.log.error("-> " + iruby.inspect)
162
166
  oruby = t[:error, t[:server, 0, "Invalid request: #{iruby.inspect}"]]
163
- self.log("<- " + oruby.inspect)
167
+ self.log.error("<- " + oruby.inspect)
164
168
  write_berp(output, oruby)
165
169
  end
166
170
  end
@@ -178,6 +182,7 @@ class Ernie::Mod
178
182
  end
179
183
 
180
184
  def fun(name, block)
185
+ raise TypeError, "block required" if block.nil?
181
186
  self.funs[name] = block
182
187
  end
183
188
  end
@@ -196,6 +201,10 @@ def logfile(name)
196
201
  Ernie.logfile(name)
197
202
  end
198
203
 
204
+ def loglevel(level)
205
+ Ernie.loglevel(level)
206
+ end
207
+
199
208
  at_exit do
200
- Ernie.start unless $test
209
+ Ernie.start if Ernie.auto_start
201
210
  end
data/test/ernie_test.rb CHANGED
@@ -2,11 +2,29 @@ require File.dirname(__FILE__) + '/helper'
2
2
 
3
3
  class ErnieTest < Test::Unit::TestCase
4
4
  context "mod" do
5
+ should "yield to the block" do
6
+ called = false
7
+ mod(:foo) { called = true }
8
+ assert called, "mod did not yield to the block"
9
+ end
10
+
5
11
  should "add a mod to the mods hash" do
6
12
  mod(:foo) { }
7
13
  assert Ernie.mods[:foo]
8
14
  assert Ernie.mods[:foo].instance_of?(Ernie::Mod)
9
15
  end
16
+
17
+ should "overwrite previous mod with the same name" do
18
+ first_mod_object, second_mod_object = nil, nil
19
+ mod(:foo) { first_mod_object = Ernie.current_mod }
20
+ mod(:foo) { second_mod_object = Ernie.current_mod }
21
+ assert_not_same second_mod_object, first_mod_object
22
+ end
23
+
24
+ should "set the mod's name" do
25
+ mod(:foo) { }
26
+ assert_equal :foo, Ernie.mods[:foo].name
27
+ end
10
28
  end
11
29
 
12
30
  context "fun" do
@@ -14,6 +32,17 @@ class ErnieTest < Test::Unit::TestCase
14
32
  mod(:foo) { fun(:bar) { } }
15
33
  assert Ernie.mods[:foo].funs[:bar]
16
34
  end
35
+
36
+ should "dispatch to a fun" do
37
+ mod(:foo) { fun(:echo) { |arg| arg } }
38
+ assert 'hello', Ernie.dispatch(:foo, :echo, 'hello')
39
+ end
40
+
41
+ should "fail when no block is provided" do
42
+ assert_raises(TypeError) do
43
+ mod(:foo) { fun(:bar) }
44
+ end
45
+ end
17
46
  end
18
47
 
19
48
  module TestExposingModule
data/test/helper.rb CHANGED
@@ -7,11 +7,11 @@ ERNIE_ROOT = File.join(File.dirname(__FILE__), *%w[..])
7
7
  $:.unshift(File.join(ERNIE_ROOT, 'lib'))
8
8
 
9
9
  require 'ernie'
10
+ Ernie.auto_start = false
11
+
10
12
  begin
11
13
  require 'bertrpc'
12
14
  rescue LoadError
13
15
  puts "You need bertrpc gem installed to run tests."
14
16
  exit!(1)
15
17
  end
16
-
17
- $test = true
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ernie
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.2.0
4
+ version: 1.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Tom Preston-Werner
@@ -9,7 +9,7 @@ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
 
12
- date: 2009-11-23 00:00:00 -08:00
12
+ date: 2009-11-30 00:00:00 -08:00
13
13
  default_executable: ernie
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
@@ -38,6 +38,7 @@ executables:
38
38
  - ernie
39
39
  extensions:
40
40
  - ext/extconf.rb
41
+ - ext/extconf.rb
41
42
  extra_rdoc_files:
42
43
  - LICENSE
43
44
  - README.md