asir 0.2.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 (121) hide show
  1. data/.gitignore +11 -0
  2. data/Gemfile +16 -0
  3. data/README.textile +50 -0
  4. data/Rakefile +83 -0
  5. data/VERSION +1 -0
  6. data/asir.gemspec +36 -0
  7. data/asir.riterate.yml +114 -0
  8. data/bin/asir +6 -0
  9. data/doc/Rakefile +8 -0
  10. data/doc/asir-sequence.pic +84 -0
  11. data/doc/asir-sequence.svg +1559 -0
  12. data/doc/sequence.pic +430 -0
  13. data/example/asir_control.sh +24 -0
  14. data/example/asir_control_client_http.rb +14 -0
  15. data/example/asir_control_client_zmq.rb +15 -0
  16. data/example/config/asir_config.rb +63 -0
  17. data/example/delayed_service.rb +15 -0
  18. data/example/ex01.rb +12 -0
  19. data/example/ex02.rb +12 -0
  20. data/example/ex03.rb +19 -0
  21. data/example/ex04.rb +33 -0
  22. data/example/ex05.rb +16 -0
  23. data/example/ex06.rb +26 -0
  24. data/example/ex07.rb +28 -0
  25. data/example/ex08.rb +30 -0
  26. data/example/ex09.rb +25 -0
  27. data/example/ex10.rb +24 -0
  28. data/example/ex11.rb +48 -0
  29. data/example/ex12.rb +34 -0
  30. data/example/ex13.rb +35 -0
  31. data/example/ex14.rb +30 -0
  32. data/example/ex15.rb +13 -0
  33. data/example/ex16.rb +33 -0
  34. data/example/ex17.rb +41 -0
  35. data/example/ex18.rb +62 -0
  36. data/example/ex19.rb +32 -0
  37. data/example/ex20.rb +28 -0
  38. data/example/ex21.rb +28 -0
  39. data/example/ex22.rb +15 -0
  40. data/example/ex23.rb +20 -0
  41. data/example/ex24.rb +35 -0
  42. data/example/example_helper.rb +51 -0
  43. data/example/sample_service.rb +162 -0
  44. data/example/unsafe_service.rb +12 -0
  45. data/hack_night/README.txt +18 -0
  46. data/hack_night/exercise/prob-1.rb +18 -0
  47. data/hack_night/exercise/prob-2.rb +21 -0
  48. data/hack_night/exercise/prob-3.rb +16 -0
  49. data/hack_night/exercise/prob-4.rb +36 -0
  50. data/hack_night/exercise/prob-5.rb +36 -0
  51. data/hack_night/exercise/prob-6.rb +95 -0
  52. data/hack_night/exercise/prob-7.rb +34 -0
  53. data/hack_night/solution/math_service.rb +11 -0
  54. data/hack_night/solution/prob-1.rb +12 -0
  55. data/hack_night/solution/prob-2.rb +15 -0
  56. data/hack_night/solution/prob-3.rb +17 -0
  57. data/hack_night/solution/prob-4.rb +37 -0
  58. data/hack_night/solution/prob-5.rb +21 -0
  59. data/hack_night/solution/prob-6.rb +33 -0
  60. data/hack_night/solution/prob-7.rb +36 -0
  61. data/lab/phony_proc.rb +31 -0
  62. data/lib/asir.rb +253 -0
  63. data/lib/asir/additional_data.rb +25 -0
  64. data/lib/asir/channel.rb +130 -0
  65. data/lib/asir/client.rb +111 -0
  66. data/lib/asir/code_block.rb +57 -0
  67. data/lib/asir/code_more.rb +50 -0
  68. data/lib/asir/coder.rb +26 -0
  69. data/lib/asir/coder/base64.rb +19 -0
  70. data/lib/asir/coder/chain.rb +30 -0
  71. data/lib/asir/coder/identity.rb +23 -0
  72. data/lib/asir/coder/json.rb +30 -0
  73. data/lib/asir/coder/marshal.rb +17 -0
  74. data/lib/asir/coder/null.rb +23 -0
  75. data/lib/asir/coder/proc.rb +22 -0
  76. data/lib/asir/coder/sign.rb +48 -0
  77. data/lib/asir/coder/xml.rb +213 -0
  78. data/lib/asir/coder/yaml.rb +33 -0
  79. data/lib/asir/coder/zlib.rb +21 -0
  80. data/lib/asir/configuration.rb +32 -0
  81. data/lib/asir/error.rb +34 -0
  82. data/lib/asir/identity.rb +36 -0
  83. data/lib/asir/initialization.rb +23 -0
  84. data/lib/asir/log.rb +82 -0
  85. data/lib/asir/main.rb +396 -0
  86. data/lib/asir/message.rb +31 -0
  87. data/lib/asir/message/delay.rb +35 -0
  88. data/lib/asir/object_resolving.rb +15 -0
  89. data/lib/asir/result.rb +39 -0
  90. data/lib/asir/retry_behavior.rb +54 -0
  91. data/lib/asir/transport.rb +241 -0
  92. data/lib/asir/transport/beanstalk.rb +217 -0
  93. data/lib/asir/transport/broadcast.rb +34 -0
  94. data/lib/asir/transport/buffer.rb +115 -0
  95. data/lib/asir/transport/composite.rb +19 -0
  96. data/lib/asir/transport/connection_oriented.rb +180 -0
  97. data/lib/asir/transport/delay.rb +38 -0
  98. data/lib/asir/transport/delegation.rb +53 -0
  99. data/lib/asir/transport/fallback.rb +36 -0
  100. data/lib/asir/transport/file.rb +88 -0
  101. data/lib/asir/transport/http.rb +54 -0
  102. data/lib/asir/transport/local.rb +21 -0
  103. data/lib/asir/transport/null.rb +14 -0
  104. data/lib/asir/transport/payload_io.rb +52 -0
  105. data/lib/asir/transport/rack.rb +73 -0
  106. data/lib/asir/transport/retry.rb +41 -0
  107. data/lib/asir/transport/stream.rb +35 -0
  108. data/lib/asir/transport/subprocess.rb +30 -0
  109. data/lib/asir/transport/tcp_socket.rb +34 -0
  110. data/lib/asir/transport/webrick.rb +50 -0
  111. data/lib/asir/transport/zmq.rb +110 -0
  112. data/lib/asir/uuid.rb +32 -0
  113. data/lib/asir/version.rb +3 -0
  114. data/spec/const_get_speed_spec.rb +33 -0
  115. data/spec/debug_helper.rb +20 -0
  116. data/spec/example_spec.rb +88 -0
  117. data/spec/json_spec.rb +128 -0
  118. data/spec/spec_helper.rb +3 -0
  119. data/spec/xml_spec.rb +144 -0
  120. data/stylesheets/slides.css +105 -0
  121. metadata +173 -0
@@ -0,0 +1,50 @@
1
+ require 'asir/transport/http'
2
+ require 'webrick'
3
+
4
+ module ASIR
5
+ class Transport
6
+ # !SLIDE
7
+ # WEBrick Transport server.
8
+ class Webrick < HTTP
9
+
10
+ # Server-side: WEBrick
11
+
12
+ # Receive the Message payload String from the HTTP Message object.
13
+ # Returns the original http_message as the message_state.
14
+ def _receive_message http_message, additional_data
15
+ [ http_message.body, http_message ]
16
+ end
17
+
18
+ # Send the Result payload String in the HTTP Response object as application/binary.
19
+ def _send_result message, result, result_payload, http_result, message_state
20
+ http_result[CONTENT_TYPE] = APPLICATION_BINARY
21
+ http_result.body = result_payload
22
+ end
23
+
24
+ def prepare_server! opts = { }
25
+ u = URI.parse(uri)
26
+ port = u.port
27
+ path = u.path
28
+ opts[:Port] ||= port
29
+ @server = ::WEBrick::HTTPServer.new(opts)
30
+ @server.mount_proc path, lambda { | rq, rs |
31
+ serve_message! rq, rs
32
+ }
33
+ self
34
+ rescue ::Exception => exc
35
+ raise Error, "Webrick Server #{uri.inspect}: #{exc.inspect}", exc.backtrace
36
+ end
37
+
38
+ def run_server!
39
+ @server.start
40
+ self
41
+ end
42
+
43
+ def stop_server!
44
+ @server.stop
45
+ self
46
+ end
47
+ end
48
+ # !SLIDE END
49
+ end
50
+ end
@@ -0,0 +1,110 @@
1
+ require 'asir/transport/connection_oriented'
2
+ gem 'zmq'
3
+ require 'zmq'
4
+
5
+ module ASIR
6
+ class Transport
7
+ # !SLIDE
8
+ # ZeroMQ Transport
9
+ class Zmq < ConnectionOriented
10
+ attr_accessor :queue
11
+
12
+ # !SLIDE
13
+ # 0MQ client.
14
+ def _client_connect!
15
+ sock = zmq_context.socket(one_way ? ZMQ::PUB : ZMQ::REQ)
16
+ sock.connect(zmq_uri)
17
+ sock
18
+ rescue ::Exception => exc
19
+ raise exc.class, "#{self.class} #{zmq_uri}: #{exc.message}", exc.backtrace
20
+ end
21
+
22
+ # !SLIDE
23
+ # 0MQ server.
24
+ def _server!
25
+ sock = zmq_context.socket(one_way ? ZMQ::SUB : ZMQ::REP)
26
+ sock.setsockopt(ZMQ::SUBSCRIBE, queue) if one_way
27
+ sock.bind("tcp://*:#{port}") # WTF?: why doesn't tcp://localhost:PORT work?
28
+ @server = sock
29
+ rescue ::Exception => exc
30
+ raise exc.class, "#{self.class} #{zmq_uri}: #{exc.message}", exc.backtrace
31
+ end
32
+
33
+ def _receive_result message, opaque_result
34
+ return nil if one_way || message.one_way
35
+ super
36
+ end
37
+
38
+ def _send_result message, result, result_payload, stream, message_state
39
+ return nil if one_way || message.one_way
40
+ super
41
+ end
42
+
43
+ def _write payload, stream
44
+ payload.insert(0, queue_) if one_way
45
+ stream.send payload, 0
46
+ stream
47
+ end
48
+
49
+ def _read stream
50
+ stream.recv 0
51
+ end
52
+
53
+ # def scheme; SCHEME; end; SCHEME = 'tcp'.freeze
54
+ def queue
55
+ @queue ||=
56
+ (
57
+ case
58
+ when @uri
59
+ x = URI.parse(@uri).path
60
+ else
61
+ x = ""
62
+ end
63
+ # x << "\t" unless x.empty?
64
+ x.freeze
65
+ )
66
+ end
67
+ def queue_
68
+ @queue_ ||=
69
+ (queue.empty? ? queue : queue + " ").freeze
70
+ end
71
+
72
+
73
+ def run_server!
74
+ _log { "run_server! #{uri}" } if @verbose >= 1
75
+ with_server_signals! do
76
+ @running = true
77
+ while @running
78
+ begin
79
+ serve_stream_message!(@server, @one_way ? nil : @server)
80
+ rescue Error::Terminate => err
81
+ @running = false
82
+ _log [ :run_server_terminate, err ]
83
+ end
84
+ end
85
+ end
86
+ self
87
+ ensure
88
+ _server_close!
89
+ end
90
+
91
+ def zmq_uri
92
+ @zmq_uri ||=
93
+ (
94
+ u = URI.parse(uri)
95
+ u.path = ''
96
+ u.to_s.freeze
97
+ )
98
+ end
99
+
100
+ def zmq_context
101
+ @@zmq_context ||=
102
+ ZMQ::Context.new(1)
103
+ end
104
+ @@zmq_context ||= nil
105
+ end
106
+ # !SLIDE END
107
+ end # class
108
+ end # module
109
+
110
+
@@ -0,0 +1,32 @@
1
+ module ASIR
2
+ # Provides an RFC4122-compliant random (version 4) UUID service.
3
+ module UUID
4
+ # Return an RFC4122-compliant random (version 4) UUID,
5
+ # represented as a string of 36 characters.
6
+ #
7
+ # Possible (but unlikely!) return value:
8
+ # "e29fc859-8d6d-4c5d-aa5a-1ab726f4a192".
9
+ #
10
+ # Possible exceptions:
11
+ # Errno::ENOENT
12
+ #
13
+ PROC_SYS_FILE = "/proc/sys/kernel/random/uuid".freeze
14
+ case
15
+ when File.exist?(PROC_SYS_FILE)
16
+ def self.generate
17
+ File.read(PROC_SYS_FILE).chomp!
18
+ end
19
+ when (gem 'uuid' rescue nil)
20
+ require 'uuid'
21
+ def self.generate
22
+ ::UUID.generate
23
+ end
24
+ else
25
+ def self.generate
26
+ raise "Unimplemented"
27
+ end
28
+ end
29
+ end
30
+ end
31
+
32
+
@@ -0,0 +1,3 @@
1
+ module ASIR
2
+ VERSION = "0.2.0"
3
+ end
@@ -0,0 +1,33 @@
1
+ module ASIR
2
+ module Test
3
+ module NamespaceCost
4
+ module Relative
5
+ def self.m
6
+ Exception
7
+ end
8
+ end
9
+ module Absolute
10
+ def self.m
11
+ ::Exception
12
+ end
13
+ end
14
+ end
15
+ end
16
+ end
17
+
18
+ describe 'Namespace Costs' do
19
+ it "uses dynamic namespacing" do
20
+ do_it ::ASIR::Test::NamespaceCost::Relative
21
+ end
22
+ it "uses static namespacing" do
23
+ do_it ::ASIR::Test::NamespaceCost::Absolute
24
+ end
25
+ def do_it obj
26
+ t0 = Time.now
27
+ 10_000_000.times do
28
+ obj.m
29
+ end
30
+ t1 = Time.now
31
+ puts "#{obj} #{t1.to_f - t0.to_f}"
32
+ end
33
+ end
@@ -0,0 +1,20 @@
1
+ require 'rubygems'
2
+ case (RUBY_PLATFORM rescue 'UNKNOWN')
3
+ when /java/
4
+ gem 'json_pure'
5
+ else
6
+ gem 'json'
7
+ case RUBY_VERSION
8
+ when /^2\./
9
+ gem 'simplecov'
10
+ when /^1\.9/
11
+ gem 'ruby-debug19'
12
+ gem 'simplecov'
13
+ # require 'ruby-debug' # BROKEN in 1.9.3-head
14
+ when /^1\.8/
15
+ gem 'ruby-debug'
16
+ gem 'rcov'
17
+ require 'ruby-debug'
18
+ end
19
+ end
20
+
@@ -0,0 +1,88 @@
1
+ require File.expand_path('../spec_helper', __FILE__)
2
+
3
+ $:.unshift File.expand_path('../../example', __FILE__)
4
+
5
+ describe "ASIR Example" do
6
+ attr_accessor :file, :expects
7
+
8
+ before(:each) do
9
+ @expects = [ ]
10
+ end
11
+
12
+ after(:each) do
13
+ @file.should_not == nil
14
+ File.open(@file) do | fh |
15
+ until fh.eof?
16
+ line = fh.readline
17
+ line.chomp!
18
+ case
19
+ when line.sub!(/^\s*#\s*EXPECT\/:\s*/, '')
20
+ expect Regexp.new(line)
21
+ when line.sub!(/^\s*#\s*EXPECT!\/:\s*/, '')
22
+ expect Regexp.new(line), :'!~'
23
+ when line.sub!(/^\s*#\s*EXPECT:\s*/, '')
24
+ expect Regexp.new(Regexp.escape(line))
25
+ when line.sub!(/^\s*#\s*EXPECT!:\s*/, '')
26
+ expect Regexp.new(Regexp.escape(line)), :'!~'
27
+ end
28
+ end
29
+ end
30
+ @output, @exit_code = run_file!(@file)
31
+ @exit_code.should == 0
32
+ @expects.empty?.should_not == true
33
+ @expects.each do | rx, mode |
34
+ $stderr.puts " Checking #{mode} #{rx.inspect}" if ENV['SPEC_VERBOSE']
35
+ case mode
36
+ when :'=~'
37
+ @output.should =~ rx
38
+ when :'!~'
39
+ @output.should_not =~ rx
40
+ else
41
+ raise ArgumentError
42
+ end
43
+ end
44
+ end
45
+
46
+ def run_file! file, output = StringIO.new('')
47
+ progname_save, stdout_save, stderr_save = $0, $stdout, $stderr
48
+ exc = system_exit = nil; exit_code = 0
49
+ begin
50
+ if true
51
+ cmd = "ASIR_EXAMPLE_SILENT=1 ruby -I example -I lib #{file}"
52
+ $stderr.puts "\n Running #{cmd}:" if ENV['SPEC_VERBOSE']
53
+ output = `#{cmd} 2>&1 | tee #{file}.out`
54
+ else
55
+ $stderr.puts "\n Loading #{file}:" if ENV['SPEC_VERBOSE']
56
+ $stdout.puts "*** #{$$}: client process"; $stdout.flush
57
+ $stdout = $stderr = output
58
+ $0 = file
59
+ Kernel.load(file, true)
60
+ output = output.string if StringIO === output
61
+ end
62
+ rescue ::SystemExit => system_exit
63
+ exit_code = 1 # ???
64
+ rescue ::Exception => exc
65
+ exit_code = -1
66
+ end
67
+ [ output, exit_code ]
68
+ ensure
69
+ $0, $stdout, $stderr = progname_save, stdout_save, stderr_save
70
+ $stderr.write output if ENV['SPEC_VERBOSE']
71
+ if exc
72
+ stderr_save.puts "ERROR: #{file}: #{exc.inspect}\n#{exc.backtrace * "\n"}"
73
+ raise exc
74
+ end
75
+ end
76
+
77
+ def expect rx, mode = :'=~'
78
+ @expects << [ rx, mode ]
79
+ end
80
+
81
+ Dir['example/**/ex[0-9]*.rb'].sort.each do | file |
82
+ title = File.open(file) { | fh | fh.read(4096) }
83
+ title = title =~ /#\s+!SLIDE[^\n]*\n\s*#\s*([^\n]+)/ && $1
84
+ it "#{file} - #{title}" do
85
+ @file = file
86
+ end
87
+ end
88
+ end
@@ -0,0 +1,128 @@
1
+ require File.expand_path('../spec_helper', __FILE__)
2
+ require 'asir/coder/json'
3
+
4
+ describe "ASIR::Coder::JSON" do
5
+ # unless RUBY_PLATFORM =~ /java/
6
+ before(:each) do
7
+ @enc = ASIR::Coder::JSON.new
8
+ @dec = @enc.dup
9
+ end
10
+
11
+ basic_objs = [ ]
12
+
13
+ [
14
+ [ nil, 'null' ],
15
+ true,
16
+ false,
17
+ ].each do | x |
18
+ x, str = *x
19
+ str ||= x.inspect
20
+ str = "[#{str}]"
21
+ basic_objs << [ x, str ]
22
+ it "should handle #{x.inspect}" do
23
+ out = @enc.encode(x)
24
+ out.should == str
25
+ @dec.decode(out).should == x
26
+ end
27
+ end
28
+
29
+ [
30
+ 1234,
31
+ 1.234,
32
+ [ :symbol, '"symbol"' ],
33
+ ].each do | x |
34
+ x, str = *x
35
+ str ||= x.inspect
36
+ str = "[#{str}]"
37
+ basic_objs << [ x, str ]
38
+ it "should handle #{x.inspect}" do
39
+ out = @enc.encode(x)
40
+ out.should == str
41
+ y = @dec.decode(out)
42
+ y = y.to_sym if Symbol === x
43
+ y.should == x
44
+ end
45
+ end
46
+
47
+ [
48
+ 'String',
49
+ ].each do | x |
50
+ x, str = *x
51
+ str ||= x.inspect
52
+ str = "[#{str}]"
53
+ basic_objs << [ x, str ]
54
+ it "should handle #{x.inspect}" do
55
+ out = @enc.encode(x)
56
+ out.should == str
57
+ y = @dec.decode(out)
58
+ y.should == x
59
+ end
60
+ end
61
+
62
+ it "should handle empty Array" do
63
+ x = [ ]
64
+ out = @enc.encode(x)
65
+ out.should == "[[]]"
66
+ @dec.decode(out).should == x
67
+ end
68
+
69
+ it "should handle Array" do
70
+ x = basic_objs.map{|e| e[0]}
71
+ out = @enc.encode(x)
72
+ out.should == "[[null,true,false,1234,1.234,\"symbol\",\"String\"]]"
73
+ y = @dec.decode(out)
74
+ y.should == x.map{|e| Symbol === e ? e.to_s : e }
75
+ end
76
+
77
+ it "should handle empty Hash" do
78
+ x = { }
79
+ out = @enc.encode(x)
80
+ out.should == "[{}]"
81
+ @dec.decode(out).should == x
82
+ end
83
+
84
+ it "should handle Hash" do
85
+ x = Hash[ *basic_objs.flatten.reverse ]
86
+ out = @enc.encode(x)
87
+ out.should =~ %r{\A\[\{}
88
+ out.should =~ %r{\}\]\Z}
89
+ basic_objs.each do | v, str |
90
+ # out.should =~ %r{#{k.inspect}:}
91
+ out.should =~ %r{#{str}}
92
+ end
93
+ y = @dec.decode(out)
94
+ y.should == x.inject({}){|h, (k, v)| h[k] = Symbol === v ? v.to_s : v; h }
95
+ end
96
+
97
+ module ASIR::Coder::Test
98
+ class Object
99
+ attr_accessor :a, :h, :o
100
+ end
101
+ end
102
+
103
+ it "should handle deep objects" do
104
+ x = ASIR::Coder::Test::Object.new
105
+ x.a = [ *basic_objs.map{|a| a[0]} ]
106
+ x.h = Hash[ *basic_objs.flatten.reverse ]
107
+ x.o = ASIR::Coder::Test::Object.new
108
+ x.o.a = 123
109
+ out = @enc.encode(x)
110
+ # FIXME:
111
+ out.should =~ %r{\A\[\"#<ASIR::Coder::Test::Object:[^>]+>\"\]\Z}
112
+ #out.should =~ %r{<#{x.class.name.gsub('::', '.')} id=\"#{x.object_id}\" >}
113
+ #out.should =~ %r{</#{x.class.name.gsub('::', '.')}>}
114
+ y = @dec.decode(out)
115
+ (String === y).should == true
116
+ =begin
117
+ FIXME:
118
+ y.a.should == x.a
119
+ y.h.should == x.h
120
+ y.o.class.should == ASIR::Coder::Test::Object
121
+ y.o.a.should == x.o.a
122
+ x.instance_variables.sort { | a, b | a.to_s <=> b.to_s }.should ==
123
+ y.instance_variables.sort { | a, b | a.to_s <=> b.to_s }
124
+ =end
125
+ end
126
+ #end
127
+ end
128
+