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,88 @@
1
+ require 'asir/transport/stream'
2
+ require 'asir/transport/payload_io'
3
+
4
+ module ASIR
5
+ class Transport
6
+ # !SLIDE
7
+ # File Transport
8
+ #
9
+ # Send Message one-way to a file.
10
+ # Can be used as a log or named pipe service.
11
+ class File < Stream
12
+ include PayloadIO # _write, _read
13
+ attr_accessor :file, :mode, :perms, :stream
14
+
15
+ def initialize opts = nil; @one_way = true; super; end
16
+
17
+ # Writes a Message payload String.
18
+ def _send_message message, message_payload
19
+ _write message_payload, stream
20
+ ensure
21
+ close if ::File.pipe?(file)
22
+ end
23
+
24
+ # Returns a Message payload String.
25
+ def _receive_message stream, additional_data
26
+ [ _read(stream), nil ]
27
+ end
28
+
29
+ # one-way; no Result.
30
+ def _send_result message, result, result_payload, stream, message_state
31
+ nil
32
+ end
33
+
34
+ # one-way; no Result.
35
+ def _receive_result message, opaque_result
36
+ nil
37
+ end
38
+
39
+ # !SLIDE
40
+ # File Transport Support
41
+
42
+ def stream
43
+ @stream ||=
44
+ begin
45
+ stream = ::File.open(file, mode || "w+")
46
+ ::File.chmod(perms, file) rescue nil if @perms
47
+ after_connect!(stream) if respond_to?(:after_connect!)
48
+ stream
49
+ end
50
+ end
51
+
52
+ # !SLIDE
53
+ # Process (receive) messages from a file.
54
+
55
+ def serve_file!
56
+ ::File.open(file, "r") do | stream |
57
+ @running = true
58
+ serve_stream! stream, nil # One-way: no result stream.
59
+ end
60
+ end
61
+
62
+ # !SLIDE
63
+ # Named Pipe Server
64
+
65
+ def prepare_pipe_server!
66
+ # _log [ :prepare_pipe_server!, file ]
67
+ unless ::File.exist? file
68
+ system(cmd = "mkfifo #{file.inspect}") or raise "cannot run #{cmd.inspect}"
69
+ ::File.chmod(perms, file) rescue nil if perms
70
+ end
71
+ end
72
+
73
+ def run_pipe_server!
74
+ # _log [ :run_pipe_server!, file ]
75
+ with_server_signals! do
76
+ @running = true
77
+ while @running
78
+ serve_file!
79
+ end
80
+ end
81
+ end
82
+
83
+ # !SLIDE END
84
+ end
85
+ # !SLIDE END
86
+ end
87
+ end
88
+
@@ -0,0 +1,54 @@
1
+ require 'asir'
2
+
3
+ require 'rubygems'
4
+ gem 'httpclient'
5
+ require 'httpclient'
6
+ require 'uri'
7
+
8
+ module ASIR
9
+ class Transport
10
+ # !SLIDE
11
+ # HTTP Transport
12
+ #
13
+ # Using HTTPClient.
14
+ class HTTP < self
15
+ attr_accessor :uri, :server, :debug
16
+
17
+ # Client-side: HTTPClient
18
+
19
+ def client
20
+ @client ||=
21
+ Channel.new(:on_connect =>
22
+ lambda { | channel | ::HTTPClient.new })
23
+ end
24
+
25
+ def close
26
+ @client.close if @client
27
+ ensure
28
+ @client = nil unless Channel === @client
29
+ end
30
+
31
+ # Send the Message payload String using HTTP POST.
32
+ # Returns the HTTPClient::Request response object.
33
+ def _send_message message, message_payload
34
+ client.with_stream! do | client |
35
+ client.post(uri, message_payload)
36
+ end
37
+ end
38
+
39
+ # Recieve the Result payload String from the opaque
40
+ # HTTPClient::Request response object returned from #_send_message.
41
+ def _receive_result message, http_result_message
42
+ # $stderr.puts " ### http_result_message.content.encoding = #{http_result_message.content.encoding.inspect}" rescue nil
43
+ # $stderr.puts " ### http_result_message.content = #{http_result_message.content.inspect}" rescue nil
44
+ http_result_message.content.to_s
45
+ end
46
+
47
+ CONTENT_TYPE = 'Content-Type'.freeze
48
+ APPLICATION_BINARY = 'application/binary'.freeze
49
+
50
+ end
51
+ # !SLIDE END
52
+ end # class
53
+ end # module
54
+
@@ -0,0 +1,21 @@
1
+ module ASIR
2
+ class Transport
3
+ # !SLIDE
4
+ # Local Transport
5
+ #
6
+ # Send Message to same process.
7
+ # Requires Identity Coder.
8
+ class Local < self
9
+ # Returns Result object after invoking Message.
10
+ def _send_message message, message_payload
11
+ invoke_message!(message)
12
+ end
13
+
14
+ # Returns Result object from #send_message.
15
+ def _receive_result message, opaque_result
16
+ opaque_result
17
+ end
18
+ end
19
+ # !SLIDE END
20
+ end
21
+ end
@@ -0,0 +1,14 @@
1
+ module ASIR
2
+ class Transport
3
+ # !SLIDE
4
+ # Null Transport
5
+ #
6
+ # Never send Message.
7
+ class Null < self
8
+ def _send_message message, message_payload
9
+ nil
10
+ end
11
+ end
12
+ # !SLIDE END
13
+ end
14
+ end
@@ -0,0 +1,52 @@
1
+ module ASIR
2
+ class Transport
3
+ # !SLIDE
4
+ # Payload IO for Transport
5
+ #
6
+ # Framing
7
+ # * Line containing the number of bytes in the payload.
8
+ # * The payload bytes.
9
+ # * Blank line.
10
+ module PayloadIO
11
+ class UnexpectedResponse < Error; end
12
+
13
+ NEWLINE = "\n"
14
+
15
+ def _write payload, stream
16
+ stream.puts payload.size
17
+ stream.write payload
18
+ stream.write NEWLINE
19
+ stream.flush
20
+ stream
21
+ end
22
+
23
+ def _read stream
24
+ size = stream.readline.chomp.to_i
25
+ payload = stream.read(size)
26
+ stream.readline
27
+ payload
28
+ end
29
+
30
+ def _read_line_and_expect! stream, regexp
31
+ line = stream.readline
32
+ unless match = regexp.match(line)
33
+ _log { "_read_line_and_expect! #{stream} #{regexp.inspect} !~ #{line.inspect}" }
34
+ raise UnexpectedResponse, "expected #{regexp.inspect}, received #{line.inspect}"
35
+ end
36
+ match
37
+ end
38
+
39
+ # !SLIDE pause
40
+ def close
41
+ if @stream
42
+ _before_close! stream if respond_to?(:_before_close!)
43
+ @stream.close
44
+ end
45
+ ensure
46
+ @stream = nil unless Channel === @stream
47
+ end
48
+
49
+ # !SLIDE resume
50
+ end
51
+ end
52
+ end
@@ -0,0 +1,73 @@
1
+ require 'asir/transport/http'
2
+ require 'rack'
3
+
4
+ module ASIR
5
+ class Transport
6
+ # !SLIDE
7
+ # Rack Transport
8
+ class Rack < HTTP
9
+ # Receive the Message payload String from the Rack::Request object.
10
+ # Returns the [ Rack::Request, Rack::Response ] as the message_state.
11
+ def _receive_message rack_req_res, additional_data
12
+ body = rack_req_res.first.body.read
13
+ [ body, rack_req_res ]
14
+ end
15
+
16
+ # Send the Result payload String in the Rack::Response object as application/binary.
17
+ def _send_result message, result, result_payload, rack_rq_rs, message_state
18
+ rack_response = rack_rq_rs[1]
19
+ rack_response[CONTENT_TYPE] = APPLICATION_BINARY
20
+ rack_response.write result_payload
21
+ end
22
+
23
+ # Constructs a Rackable App from this Transport.
24
+ def rack_app &blk
25
+ App.new(self, &blk)
26
+ end
27
+
28
+ # Rack Transport Application.
29
+ class App
30
+ def initialize transport = nil, &blk
31
+ @app = transport
32
+ instance_eval &blk if blk
33
+ end
34
+
35
+ def call env
36
+ @app.call(env)
37
+ end
38
+ end
39
+
40
+ # Rack application handler.
41
+ def call(env)
42
+ rq = ::Rack::Request.new(env)
43
+ rs = ::Rack::Response.new
44
+ rack_rq_rs = [ rq, rs ]
45
+ serve_message! rack_rq_rs, rack_rq_rs
46
+ rs.finish # => [ status, header, rbody ]
47
+ end
48
+
49
+ ###############################
50
+ # Dummy server.
51
+
52
+ def prepare_server! opts = { }
53
+ self
54
+ end
55
+
56
+ # WEBrick under Rack.
57
+ def run_server!
58
+ #require 'rack/handler'
59
+ u = URI.parse(uri); port = u.port # <= REFACTOR
60
+ ::Rack::Handler::WEBrick.run \
61
+ ::Rack::ShowExceptions.new(::Rack::Lint.new(self.rack_app)),
62
+ :Port => port
63
+ self
64
+ end
65
+
66
+ def stop_server!
67
+ # NOT IMPLEMENTED
68
+ self
69
+ end
70
+ end
71
+ # !SLIDE END
72
+ end
73
+ end
@@ -0,0 +1,41 @@
1
+ require 'asir/transport/delegation'
2
+ require 'asir/retry_behavior'
3
+
4
+ module ASIR
5
+ class Transport
6
+ # !SLIDE
7
+ # Retry Transport
8
+ class Retry < self
9
+ include Delegation, RetryBehavior
10
+
11
+ # The transport to delegate to.
12
+ attr_accessor :transport
13
+ # Proc to call(transport, message) before retry.
14
+ attr_accessor :before_retry
15
+
16
+ def _send_message message, message_payload
17
+ first_exception = nil
18
+ with_retry do | action, data |
19
+ case action
20
+ when :try
21
+ transport.send_message(message)
22
+ when :rescue #, exc
23
+ first_exception ||= data
24
+ _handle_send_message_exception! transport, message, data
25
+ when :retry #, exc
26
+ before_retry.call(self, message) if before_retry
27
+ when :failed
28
+ @on_failed_message.call(self, message) if @on_failed_message
29
+ if first_exception && @reraise_first_exception
30
+ $! = first_exception
31
+ raise
32
+ end
33
+ nil # fallback to raise RetryError
34
+ end
35
+ end
36
+ end
37
+ end
38
+ # !SLIDE END
39
+ end
40
+ end
41
+
@@ -0,0 +1,35 @@
1
+ module ASIR
2
+ class Transport
3
+ # !SLIDE
4
+ # Stream Transport
5
+ #
6
+ # Base class handles Messages on a stream.
7
+ # Stream Transports require a Coder that encodes to and from String payloads.
8
+ class Stream < self
9
+
10
+ # !SLIDE
11
+ # Serve all Messages from a stream.
12
+ def serve_stream! in_stream, out_stream
13
+ with_server_signals! do
14
+ while @running && ! in_stream.eof?
15
+ begin
16
+ serve_stream_message! in_stream, out_stream
17
+ rescue Error::Terminate => err
18
+ @running = false
19
+ _log [ :serve_stream_terminate, err ]
20
+ rescue ::Exception => err
21
+ _log [ :serve_stream_error, err ]
22
+ end
23
+ end
24
+ end
25
+ end
26
+
27
+ # !SLIDE
28
+ # Serve a Message from a stream.
29
+ def serve_stream_message! in_stream, out_stream
30
+ serve_message! in_stream, out_stream
31
+ end
32
+ end
33
+ # !SLIDE END
34
+ end
35
+ end
@@ -0,0 +1,30 @@
1
+ require 'asir/transport/local'
2
+
3
+ module ASIR
4
+ class Transport
5
+ # !SLIDE
6
+ # Subprocess Transport
7
+ #
8
+ # Send one-way Message to a forked subprocess.
9
+ class Subprocess < Local
10
+ def initialize *args
11
+ @one_way = true; super
12
+ end
13
+
14
+ def _send_message message, message_payload
15
+ Process.fork do
16
+ send_result(super, nil, nil)
17
+ end
18
+ end
19
+
20
+ # one-way; no Result
21
+ def _receive_result message, opaque_result
22
+ end
23
+
24
+ # one-way; no Result
25
+ def _send_result message, result, result_payload, stream, message_state
26
+ end
27
+ end
28
+ # !SLIDE END
29
+ end
30
+ end
@@ -0,0 +1,34 @@
1
+ require 'asir/transport/connection_oriented'
2
+ require 'socket'
3
+
4
+ module ASIR
5
+ class Transport
6
+ # !SLIDE
7
+ # TCP Socket Transport
8
+ class TcpSocket < ConnectionOriented
9
+ # !SLIDE
10
+ # TCP Socket Client
11
+ def _client_connect!
12
+ sock = TCPSocket.open(address, port)
13
+ end
14
+
15
+ # !SLIDE
16
+ # TCP Socket Server
17
+ def _server!
18
+ @server = TCPServer.open(port)
19
+ @server.setsockopt(Socket::SOL_SOCKET, Socket::SO_KEEPALIVE, false)
20
+ end
21
+
22
+ def _server_accept_connection! server
23
+ server.accept
24
+ end
25
+
26
+ def _server_close_connection! stream
27
+ stream.close rescue nil
28
+ end
29
+ end
30
+ # !SLIDE END
31
+ end # class
32
+ end # module
33
+
34
+