ernie 1.0.0 → 1.1.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.
data/History.txt CHANGED
@@ -1,3 +1,8 @@
1
+ = 1.1.0 / 2009-10-28
2
+ * Major changes
3
+ * Remove dependency on Erlectricity
4
+ * Simplify processing loop
5
+
1
6
  = 1.0.0 / 2009-10-19
2
7
  * No Changes. Production ready!
3
8
 
data/Rakefile CHANGED
@@ -11,8 +11,7 @@ begin
11
11
  gem.authors = ["Tom Preston-Werner"]
12
12
  gem.files.include(["ext"])
13
13
  gem.extensions << 'ext/extconf.rb'
14
- gem.add_dependency('erlectricity', '>= 1.1.0')
15
- gem.add_dependency('bert', '>= 1.0.0')
14
+ gem.add_dependency('bert', '>= 1.1.0')
16
15
  gem.add_dependency('bertrpc', '>= 1.0.0')
17
16
 
18
17
  # gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings
data/VERSION.yml CHANGED
@@ -1,4 +1,4 @@
1
1
  ---
2
+ :minor: 1
2
3
  :patch: 0
3
4
  :major: 1
4
- :minor: 0
data/ernie.gemspec CHANGED
@@ -5,11 +5,11 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = %q{ernie}
8
- s.version = "1.0.0"
8
+ s.version = "1.1.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-10-19}
12
+ s.date = %q{2009-10-28}
13
13
  s.default_executable = %q{ernie}
14
14
  s.email = %q{tom@mojombo.com}
15
15
  s.executables = ["ernie"]
@@ -66,17 +66,14 @@ Gem::Specification.new do |s|
66
66
  s.specification_version = 3
67
67
 
68
68
  if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
69
- s.add_runtime_dependency(%q<erlectricity>, [">= 1.1.0"])
70
- s.add_runtime_dependency(%q<bert>, [">= 1.0.0"])
69
+ s.add_runtime_dependency(%q<bert>, [">= 1.1.0"])
71
70
  s.add_runtime_dependency(%q<bertrpc>, [">= 1.0.0"])
72
71
  else
73
- s.add_dependency(%q<erlectricity>, [">= 1.1.0"])
74
- s.add_dependency(%q<bert>, [">= 1.0.0"])
72
+ s.add_dependency(%q<bert>, [">= 1.1.0"])
75
73
  s.add_dependency(%q<bertrpc>, [">= 1.0.0"])
76
74
  end
77
75
  else
78
- s.add_dependency(%q<erlectricity>, [">= 1.1.0"])
79
- s.add_dependency(%q<bert>, [">= 1.0.0"])
76
+ s.add_dependency(%q<bert>, [">= 1.1.0"])
80
77
  s.add_dependency(%q<bertrpc>, [">= 1.0.0"])
81
78
  end
82
79
  end
data/examples/calc.rb CHANGED
@@ -14,6 +14,10 @@ mod(:slowcalc) do
14
14
  sleep(rand * 2)
15
15
  a + b
16
16
  end
17
+
18
+ fun(:superslow) do
19
+ sleep 10
20
+ end
17
21
  end
18
22
 
19
23
  # Throw an error
data/lib/ernie.rb CHANGED
@@ -11,6 +11,11 @@ class Ernie
11
11
  self.current_mod = nil
12
12
  self.logger = nil
13
13
 
14
+ # Record a module.
15
+ # +name+ is the module Symbol
16
+ # +block+ is the Block containing function definitions
17
+ #
18
+ # Returns nothing
14
19
  def self.mod(name, block)
15
20
  m = Mod.new(name)
16
21
  self.current_mod = m
@@ -18,69 +23,129 @@ class Ernie
18
23
  block.call
19
24
  end
20
25
 
26
+ # Record a function.
27
+ # +name+ is the function Symbol
28
+ # +block+ is the Block to associate
29
+ #
30
+ # Returns nothing
21
31
  def self.fun(name, block)
22
32
  self.current_mod.fun(name, block)
23
33
  end
24
34
 
35
+ # Set the logfile to given path.
36
+ # +file+ is the String path to the logfile
37
+ #
38
+ # Returns nothing
25
39
  def self.logfile(file)
26
40
  self.logger = Logger.new(file)
27
41
  end
28
42
 
43
+ # If logging is enabled, log the given text.
44
+ # +text+ is the String to log
45
+ #
46
+ # Returns nothing
29
47
  def self.log(text)
30
48
  self.logger.info(text) if self.logger
31
49
  end
32
50
 
51
+ # Dispatch the request to the proper mod:fun.
52
+ # +mod+ is the module Symbol
53
+ # +fun+ is the function Symbol
54
+ # +args+ is the Array of arguments
55
+ #
56
+ # Returns the Ruby object response
33
57
  def self.dispatch(mod, fun, args)
34
- xargs = BERT::Decoder.convert(args)
35
- self.log("-- " + [mod, fun, xargs].inspect)
36
58
  self.mods[mod] || raise(ServerError.new("No such module '#{mod}'"))
37
59
  self.mods[mod].funs[fun] || raise(ServerError.new("No such function '#{mod}:#{fun}'"))
38
- res = self.mods[mod].funs[fun].call(*xargs)
39
- BERT::Encoder.convert(res)
60
+ self.mods[mod].funs[fun].call(*args)
40
61
  end
41
62
 
63
+ # Read the length header from the wire.
64
+ # +input+ is the IO from which to read
65
+ #
66
+ # Returns the size Integer if one was read
67
+ # Returns nil otherwise
68
+ def self.read_4(input)
69
+ raw = input.read(4)
70
+ return nil unless raw
71
+ raw.unpack('N').first
72
+ end
73
+
74
+ # Read a BERP from the wire and decode it to a Ruby object.
75
+ # +input+ is the IO from which to read
76
+ #
77
+ # Returns a Ruby object if one could be read
78
+ # Returns nil otherwise
79
+ def self.read_berp(input)
80
+ packet_size = self.read_4(input)
81
+ return nil unless packet_size
82
+ bert = input.read(packet_size)
83
+ BERT.decode(bert)
84
+ end
85
+
86
+ # Write the given Ruby object to the wire as a BERP.
87
+ # +output+ is the IO on which to write
88
+ # +ruby+ is the Ruby object to encode
89
+ #
90
+ # Returns nothing
91
+ def self.write_berp(output, ruby)
92
+ data = BERT.encode(ruby)
93
+ output.write([data.length].pack("N"))
94
+ output.write(data)
95
+ end
96
+
97
+ # Start the processing loop.
98
+ #
99
+ # Loops forever
42
100
  def self.start
43
101
  self.log("Starting")
44
102
  self.log(self.mods.inspect)
45
- receive do |f|
46
- f.when([:call, Symbol, Symbol, Array]) do |mod, fun, args|
47
- self.log("-> " + [:call, mod, fun, args].inspect)
103
+
104
+ input = IO.new(3)
105
+ output = IO.new(4)
106
+ input.sync = true
107
+ output.sync = true
108
+
109
+ loop do
110
+ iruby = self.read_berp(input)
111
+ unless iruby
112
+ puts "Could not read BERP length header. Ernie server may have gone away. Exiting now."
113
+ exit!
114
+ end
115
+
116
+ if iruby.size == 4 && iruby[0] == :call
117
+ mod, fun, args = iruby[1..3]
118
+ self.log("-> " + iruby.inspect)
48
119
  begin
49
120
  res = self.dispatch(mod, fun, args)
50
- xres = [:reply, res]
51
- self.log("<- " + xres.inspect)
52
- f.send!(xres)
121
+ oruby = t[:reply, res]
122
+ self.log("<- " + oruby.inspect)
123
+ write_berp(output, oruby)
53
124
  rescue ServerError => e
54
- xres = [:error, [:server, 0, e.class.to_s, e.message, e.backtrace]]
55
- self.log("<- " + xres.inspect)
125
+ oruby = t[:error, t[:server, 0, e.class.to_s, e.message, e.backtrace]]
126
+ self.log("<- " + oruby.inspect)
56
127
  self.log(e.backtrace.join("\n"))
57
- f.send!(xres)
128
+ write_berp(output, oruby)
58
129
  rescue Object => e
59
- xres = [:error, [:user, 0, e.class.to_s, e.message, e.backtrace]]
60
- self.log("<- " + xres.inspect)
130
+ oruby = t[:error, t[:user, 0, e.class.to_s, e.message, e.backtrace]]
131
+ self.log("<- " + oruby.inspect)
61
132
  self.log(e.backtrace.join("\n"))
62
- f.send!(xres)
133
+ write_berp(output, oruby)
63
134
  end
64
- f.receive_loop
65
- end
66
-
67
- f.when([:cast, Symbol, Symbol, Array]) do |mod, fun, args|
135
+ elsif iruby.size == 4 && iruby[0] == :cast
136
+ mod, fun, args = iruby[1..3]
68
137
  self.log("-> " + [:cast, mod, fun, args].inspect)
69
138
  begin
70
139
  self.dispatch(mod, fun, args)
71
140
  rescue Object => e
72
141
  # ignore
73
142
  end
74
- f.send!([:noreply])
75
- f.receive_loop
76
- end
77
-
78
- f.when(Any) do |any|
79
- self.log("-> " + any.inspect)
80
- xres = [:error, [:server, 0, "Invalid request: #{any.inspect}"]]
81
- self.log("<- " + xres.inspect)
82
- f.send!(xres)
83
- f.receive_loop
143
+ write_berp(output, t[:noreply])
144
+ else
145
+ self.log("-> " + iruby.inspect)
146
+ oruby = t[:error, t[:server, 0, "Invalid request: #{iruby.inspect}"]]
147
+ self.log("<- " + oruby.inspect)
148
+ write_berp(output, oruby)
84
149
  end
85
150
  end
86
151
  end
@@ -37,6 +37,10 @@ class ErnieServerTest < Test::Unit::TestCase
37
37
  assert_equal 10, @svc.call.test.ternary(5, 2, 3)
38
38
  end
39
39
 
40
+ should "handle massive binaries" do
41
+ assert_equal 8 * 1024 * 1024, @svc.call.test.big(8 * 1024 * 1024).size
42
+ end
43
+
40
44
  should "get an error on missing module" do
41
45
  begin
42
46
  @svc.call.failboat.mcfail(:fail)
data/test/handler.rb CHANGED
@@ -31,6 +31,10 @@ mod(:test) do
31
31
  state
32
32
  end
33
33
 
34
+ fun(:big) do |x|
35
+ 'a' * x
36
+ end
37
+
34
38
  fun(:cry) do
35
39
  raise "abandon hope!"
36
40
  end
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.0.0
4
+ version: 1.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Tom Preston-Werner
@@ -9,19 +9,9 @@ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
 
12
- date: 2009-10-19 00:00:00 -07:00
12
+ date: 2009-10-28 00:00:00 -07:00
13
13
  default_executable: ernie
14
14
  dependencies:
15
- - !ruby/object:Gem::Dependency
16
- name: erlectricity
17
- type: :runtime
18
- version_requirement:
19
- version_requirements: !ruby/object:Gem::Requirement
20
- requirements:
21
- - - ">="
22
- - !ruby/object:Gem::Version
23
- version: 1.1.0
24
- version:
25
15
  - !ruby/object:Gem::Dependency
26
16
  name: bert
27
17
  type: :runtime
@@ -30,7 +20,7 @@ dependencies:
30
20
  requirements:
31
21
  - - ">="
32
22
  - !ruby/object:Gem::Version
33
- version: 1.0.0
23
+ version: 1.1.0
34
24
  version:
35
25
  - !ruby/object:Gem::Dependency
36
26
  name: bertrpc