sub_zero 0.0.4 → 0.0.5

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 1d2f91d35235df49176ba39a8f3cd6bf5cbca454
4
- data.tar.gz: ada80f112ceff71a231d9bf2b05c05ce30cb66a2
3
+ metadata.gz: 41d022d98d371aa71c53fbe297f481015d5293f7
4
+ data.tar.gz: d6f1bdd5be50e6ed39640cafe7e350647e8f38e7
5
5
  SHA512:
6
- metadata.gz: 496a8f67eb47c3105724e05cab034f5efd519c120f7d6807de1173b2015c57692a622d6f25204fa11446be2a5fb84276d9c58dbe2727929108d79f85bcc11ac1
7
- data.tar.gz: 5d0dc86764da65b7eacff51daa6431fd091a7a2055864bc8c84377bf8f15488df15ebc569c382ea2505e1cdfb6103ccc33929fbfb43ff962b329d9d64bf25174
6
+ metadata.gz: 127f4ed3c1f8606bbdfb28203aefb15743cb4a54d5619e4c6033faab2bccc806c1bd9ca9be0f6c71da013c966c7e93bc913aea9deb5e68c8ba98a2e3e9068efa
7
+ data.tar.gz: af1707609bc526c600b64a60d909f97bce87b7e9731c3b72eaee9824d97161726517c5fd4319673905b4ab3cf4849ecf8cab63631427c6033eba52727cf30b28
@@ -1,7 +1,8 @@
1
1
  module SubZero
2
2
  module CLI
3
3
  class App < Thor
4
- register SubZero::CLI::New, 'new', 'new TYPE NAME', 'Creates a new TYPE (service/client) named NAME'
4
+ register SubZero::CLI::New, 'new', 'new TYPE NAME',
5
+ 'Creates a new TYPE (service/client) named NAME'
5
6
  end
6
7
  end
7
8
  end
@@ -1,12 +1,5 @@
1
- require 'active_support/string_inquirer'
2
- require 'active_support/hash_with_indifferent_access'
3
-
4
1
  module SubZero
5
2
  class Client
6
- autoload :Configuration, 'sub_zero/client/configuration'
7
- autoload :Socket, 'sub_zero/client/socket'
8
-
9
- include Socket
10
3
 
11
4
  attr_reader :sid, :config
12
5
 
@@ -15,11 +8,24 @@ module SubZero
15
8
  yield @config if block_given?
16
9
  end
17
10
 
11
+ def socket
12
+ Socket.new config
13
+ end
14
+
18
15
  def call verb, payload = {}, options = {}
19
16
  sz_verb = verb.to_s.upcase.gsub('_', '/')
20
- status, result = zeromq_fetch(sz_verb, payload, options)
21
- result = handle_result(status, result).with_indifferent_access
22
- block_given? ? yield(result) : result
17
+
18
+ request = Message.new(type: 'REQ', subtype: sid, verb: sz_verb,
19
+ payload: payload, options: options)
20
+
21
+ response = socket.call(request)
22
+
23
+ if block_given?
24
+ yield response
25
+ else
26
+ fail Error.new(response) if response.error?
27
+ response.payload
28
+ end
23
29
  end
24
30
 
25
31
  def call! verb, payload = {}, options = {}, &block
@@ -32,33 +38,24 @@ module SubZero
32
38
 
33
39
  def method_missing method, payload = {}, options = {}, &block
34
40
  if method.to_s.end_with? '!'
35
- call! method.delete('!'), payload, options, &block
41
+ call! method.to_s.delete('!'), payload, options, &block
36
42
  else
37
43
  call method, payload, options, &block
38
44
  end
39
45
  end
40
46
 
41
- def handle_result status, result
42
- case status
43
- when :ok
44
- result
45
- when :error
46
- fail Error.new(result['error'])
47
- end
48
- end
49
-
50
47
  class Error < ::StandardError
51
48
 
52
49
  attr_reader :result
53
50
 
54
- def initialize result
55
- super result['message']
51
+ def initialize response
52
+ super response.payload['message']
56
53
  set_backtrace caller
57
- @result = result
54
+ @result = response
58
55
  end
59
56
 
60
57
  def code
61
- result['code']
58
+ result.payload['code']
62
59
  end
63
60
 
64
61
  def status
@@ -0,0 +1,10 @@
1
+ module SubZero
2
+ module Configuration
3
+ extend self
4
+
5
+ def default
6
+ { ip: '127.0.0.1', port: 7777 }
7
+ end
8
+
9
+ end
10
+ end
@@ -0,0 +1,10 @@
1
+ module SubZero
2
+ module Environment
3
+
4
+ def env
5
+ environment = ENV['SUBZERO_ENV'] || ENV['SZ_ENV'] || 'development'
6
+ ActiveSupport::StringInquirer.new environment
7
+ end
8
+
9
+ end
10
+ end
@@ -0,0 +1,58 @@
1
+ require 'colorize'
2
+
3
+ module SubZero
4
+ module Loggable
5
+
6
+ COLORS = [:red, :green, :yellow, :blue, :magenta, :cyan,
7
+ :light_red, :light_green, :light_yellow, :light_blue, :light_magenta, :light_cyan]
8
+
9
+ SEVERITIES = [:info, :warn, :error, :debug]
10
+
11
+ SEVERITY_COLORS = { info: :light_blue }
12
+
13
+ SEVERITIES.each do |severity|
14
+ define_method severity do |message, context = {}|
15
+ log message, { severity: severity }.merge(context)
16
+ end
17
+ end
18
+
19
+ def error exception, message
20
+ super message, error: exception
21
+ end
22
+
23
+ def log message, context = {}
24
+ sender_class = self.kind_of?(Class) ? self : self.class
25
+ context.merge! sender_class: sender_class.to_s
26
+ context[:severity] ||= :info
27
+
28
+ puts log_colored_message(message, context)
29
+ end
30
+
31
+ def self.included(base)
32
+ base.extend self
33
+ end
34
+
35
+ private
36
+
37
+ def log_colored_message(message, context)
38
+ msg = log_colored_severity(context[:severity])
39
+ msg << " #{Time.now.strftime('%Y%m%d%H%M%S%L')}"
40
+
41
+ if sender_class = context.delete(:sender_class)
42
+ msg = log_colored_term(sender_class)
43
+ end
44
+
45
+ msg << " #{message}"
46
+ end
47
+
48
+ def log_colored_severity(severity)
49
+ severity.to_s.colorize SEVERITY_COLORS[severity.to_sym]
50
+ end
51
+
52
+ def log_colored_term(term)
53
+ index = Integer("0x#{Digest::MD5.hexdigest(term)[0, 2]}") % 12
54
+ term.colorize COLORS[index]
55
+ end
56
+
57
+ end
58
+ end
@@ -1,11 +1,10 @@
1
1
  module SubZero
2
2
  module Common
3
+ include SubZero::Environment
4
+
3
5
  def log msg, level='DEBUG'
4
6
  puts "#{level}: #{msg}"
5
7
  end
6
8
 
7
- def env
8
- ENV['SUBZERO_ENV'] || 'development'
9
- end
10
9
  end
11
- end
10
+ end
@@ -0,0 +1,65 @@
1
+ module SubZero
2
+ class Message
3
+ module Parser
4
+ extend ActiveSupport::Concern
5
+
6
+ def to_source
7
+ frames = []
8
+
9
+ if subtype.present?
10
+ frames << "#{type}:#{subtype}"
11
+ else
12
+ frames << type
13
+ end
14
+
15
+ frames << rid
16
+
17
+ if status.present?
18
+ frames << "#{verb}:#{status}"
19
+ else
20
+ frames << verb
21
+ end
22
+
23
+ frames << payload.to_msgpack
24
+ frames << options.to_msgpack
25
+
26
+ frames
27
+ end
28
+
29
+ module ClassMethods
30
+
31
+ def from_source source
32
+ type = source.shift
33
+
34
+ if type.index ':'
35
+ type, subtype = type.split(':')
36
+ end
37
+
38
+ rid = source.shift
39
+ verb = source.shift
40
+
41
+ if verb.index ':'
42
+ verb, status = verb.split(':')
43
+ end
44
+
45
+ payload = MessagePack.unpack(source.shift).with_indifferent_access
46
+
47
+ unless source.empty?
48
+ routing_info = MessagePack.unpack(source.shift).with_indifferent_access
49
+ end
50
+
51
+ new type: type, rid: rid, verb: verb, payload: payload,
52
+ subtype: subtype, status: status, routing_info: routing_info
53
+ end
54
+
55
+ def parse source, request = nil
56
+ from_source(source).tap do |m|
57
+ m.validate_response!(request) if request
58
+ end
59
+ end
60
+
61
+ end
62
+
63
+ end
64
+ end
65
+ end
@@ -0,0 +1,29 @@
1
+ module SubZero
2
+ class Message
3
+ module Validations
4
+
5
+ def validate_response! request
6
+ broker_reply = type == 'BRO'
7
+ service_reply = type == 'REP' && subtype == request.sid
8
+
9
+ unless broker_reply || service_reply
10
+ fail Socket::Error, "unexpected result type: #{type}, " +
11
+ "subtype: #{subtype}. " + to_s
12
+ end
13
+
14
+ unless rid == request.rid
15
+ fail Socket::Error, "rid mismatch. sent: #{request.rid}, " +
16
+ "received: #{rid}. " + to_s
17
+ end
18
+
19
+ unless verb == request.verb && response?
20
+ fail Socket::Error, "reply verb mismatch: #{verb}, " +
21
+ "status: #{status}. " + to_s
22
+ end
23
+
24
+ true
25
+ end
26
+
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,49 @@
1
+ require_relative 'message/parser'
2
+ require_relative 'message/validations'
3
+
4
+ module SubZero
5
+ class Message
6
+ include Parser
7
+ include Validations
8
+
9
+ attr_accessor :type,
10
+ :subtype,
11
+ :rid,
12
+ :verb,
13
+ :status,
14
+ :payload,
15
+ :options
16
+
17
+ def initialize args = {}
18
+ @type, @subtype = args.values_at(:type, :subtype)
19
+ @rid = args[:rid] || SecureRandom.uuid
20
+ @verb, @status = args.values_at(:verb, :status)
21
+ @payload = args[:payload] || {}
22
+ @options = args[:options] || {}
23
+ end
24
+
25
+ alias :sid :subtype
26
+ alias :routing_info :options
27
+
28
+ def heartbeat?
29
+ verb == 'PONG'
30
+ end
31
+
32
+ def request?
33
+ status.blank?
34
+ end
35
+
36
+ def response?
37
+ not request?
38
+ end
39
+
40
+ def success?
41
+ status == 'OK'
42
+ end
43
+
44
+ def error?
45
+ status == 'NOK'
46
+ end
47
+
48
+ end
49
+ end
@@ -0,0 +1,30 @@
1
+ module SubZero
2
+ module Service
3
+ class Handler
4
+
5
+ attr_reader :message
6
+
7
+ delegate :rid, :verb, :payload, to: :message
8
+
9
+ alias :request_id :rid
10
+ alias :params :payload
11
+
12
+ def initialize message
13
+ @message = message
14
+ end
15
+
16
+ # verb, payload = nil
17
+ # payload (same verb with :OK)
18
+ def reply *args
19
+ end
20
+
21
+ def reply_with payload
22
+ reply verb, payload
23
+ end
24
+
25
+ def error code, message
26
+ end
27
+
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,40 @@
1
+ require 'active_support/inflector'
2
+
3
+ module SubZero
4
+ module Service
5
+ module Router
6
+
7
+ def routes
8
+ @routes ||= {}
9
+ end
10
+
11
+ def route &block
12
+ instance_eval &block
13
+ end
14
+
15
+ def verb args
16
+ name, route = Hash[args].first
17
+ routes[name.to_s.upcase] = handler_caller(route)
18
+
19
+ true
20
+ end
21
+
22
+ private
23
+
24
+ def handler_caller route
25
+ handler, action = route.to_s.split('#')
26
+
27
+ begin
28
+ handler_name = "Handlers::#{handler.camelize}"
29
+ handler_class = const_get(handler_name)
30
+ rescue
31
+ fail "Handler not found: #{handler_name}"
32
+ end
33
+
34
+ proc { |message| handler_class.new(message).send action }
35
+ end
36
+
37
+ end
38
+ end
39
+ end
40
+
@@ -0,0 +1,33 @@
1
+ module SubZero
2
+ module Runner
3
+
4
+ def run!
5
+ Daemons.run_proc sid, daemon_configuration do
6
+ start = Time.now
7
+ ping_at = start + 5
8
+
9
+ Signal.trap('INT') { socket.down!; exit }
10
+ Signal.trap('TERM') { socket.down!; exit }
11
+
12
+ socket.up!
13
+
14
+ loop do
15
+ socket.run &method(:resolve)
16
+
17
+ now = Time.now
18
+
19
+ if now >= ping_at
20
+ socket.ping
21
+ ping_at = now + 15
22
+ end
23
+
24
+ break if $stop_requested
25
+ end
26
+
27
+ socket.down!
28
+ exit 0
29
+ end
30
+ end
31
+
32
+ end
33
+ end
@@ -0,0 +1,31 @@
1
+ require_relative 'service/handler'
2
+ require_relative 'service/router'
3
+ require_relative 'service/runner'
4
+
5
+ module SubZero
6
+ module Service
7
+ include Router
8
+ include Loggable
9
+ include Runner
10
+
11
+ def sid service_id = nil
12
+ @sid = service_id.to_sym if service_id
13
+ @sid
14
+ end
15
+
16
+ def resolve message
17
+ if handler = routes[message.verb]
18
+ handler[message]
19
+ else
20
+ # TODO verb mismatch error
21
+ end
22
+ end
23
+
24
+ private
25
+
26
+ def socket
27
+ Socket.new
28
+ end
29
+
30
+ end
31
+ end
@@ -0,0 +1,25 @@
1
+ module SubZero
2
+ class Socket
3
+ module Sender
4
+
5
+ def call request
6
+ response = nil
7
+ t = request.options.fetch(:timeout, 1000) / 1000.0
8
+
9
+ ::Timeout.timeout t do
10
+ context do |c|
11
+ socket c do |s|
12
+ send_message s, request
13
+ response = receive_message(s, request)
14
+ end
15
+ end
16
+ end
17
+
18
+ response
19
+ rescue ::Timeout::Error
20
+ raise SubZero::Socket::TimeoutError
21
+ end
22
+
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,59 @@
1
+ module SubZero
2
+ class Socket
3
+ module Server
4
+
5
+ def run &handle_message
6
+ context do |c|
7
+ socket c do |s|
8
+ poll s do |m|
9
+ handle_message[m]
10
+ end
11
+ end
12
+ end
13
+ rescue => e
14
+ error e, 'failed while running server, going to retry'
15
+ retry
16
+ end
17
+
18
+ def up!
19
+ send_server_verb 'UP'
20
+ end
21
+
22
+ def down!
23
+ send_server_verb 'DOWN'
24
+ end
25
+
26
+ def ping
27
+ send_server_verb 'PING'
28
+ end
29
+
30
+ def send_server_verb verb
31
+ context do |c|
32
+ socket c do |s|
33
+ send_message s, Message.new(type: 'SRV', verb: verb)
34
+ end
35
+ end
36
+ end
37
+
38
+ def poll socket
39
+ ZMQ::Poller.new.tap do |p|
40
+ p.register socket, ZMQ::POLLIN
41
+ p.poll 1
42
+
43
+ p.readables.each do |s|
44
+ s.recv_strings source = []
45
+
46
+ begin
47
+ message = Message.parse(source)
48
+ rescue => e
49
+ error e, 'error parsing message'
50
+ end
51
+
52
+ yield message if message
53
+ end
54
+ end
55
+ end
56
+
57
+ end
58
+ end
59
+ end
@@ -0,0 +1,65 @@
1
+ require 'ffi-rzmq'
2
+ require 'msgpack'
3
+
4
+ require_relative 'socket/sender'
5
+ require_relative 'socket/server'
6
+
7
+ module SubZero
8
+ class Socket
9
+ include Loggable
10
+ include Sender
11
+ include Server
12
+
13
+ class Error < StandardError; end
14
+ class TimeoutError < Socket::Error; end
15
+
16
+ attr_reader :config
17
+
18
+ def initialize config = Configuration.default
19
+ @config = config
20
+ end
21
+
22
+ def context
23
+ context = ZMQ::Context.create(1)
24
+ fail Socket::Error, 'failed to create context' unless context
25
+ yield context
26
+ check! context.terminate
27
+ rescue Socket::Error
28
+ check! context.terminate
29
+ raise
30
+ end
31
+
32
+ def socket context
33
+ socket = context.socket ZMQ::DEALER
34
+ socket.identity = SecureRandom.hex(10)
35
+ check! socket.connect("tcp://#{config[:ip]}:#{config[:port]}")
36
+ yield socket
37
+ check! socket.close
38
+ rescue Socket::Error
39
+ check! socket.close
40
+ raise
41
+ end
42
+
43
+ def send_message socket, message
44
+ frames = message.to_source
45
+ last = frames.pop
46
+ frames.each { |f| check! socket.send_string f.to_s, ZMQ::SNDMORE }
47
+ check! socket.send_string last
48
+ end
49
+
50
+ def receive_message socket, request
51
+ check! socket.recv_strings(frames = [])
52
+ Message.parse frames, request
53
+ end
54
+
55
+ def check! result_code
56
+ return if ZMQ::Util.resultcode_ok? result_code
57
+
58
+ fail Socket::Error, "operation failed, errno [#{ZMQ::Util.errno}], " +
59
+ "description [#{ZMQ::Util.error_string}]"
60
+ rescue
61
+ raise Socket::Error "operation failed, cannot have errno"
62
+ end
63
+
64
+ end
65
+ end
@@ -1,3 +1,3 @@
1
1
  module SubZero
2
- VERSION = '0.0.4'
2
+ VERSION = '0.0.5'
3
3
  end
data/lib/sub_zero.rb CHANGED
@@ -1,17 +1,30 @@
1
1
  require 'yaml'
2
2
  require 'securerandom'
3
3
  require 'timeout'
4
+ require 'digest/md5'
4
5
 
5
6
  require 'thor'
6
7
  require 'thor/group'
7
8
 
9
+ require 'active_support/string_inquirer'
10
+ require 'active_support/hash_with_indifferent_access'
11
+ require 'active_support/concern'
12
+ require 'active_support/core_ext/module/delegation'
13
+
8
14
  require_relative 'sub_zero/version'
15
+ require_relative 'sub_zero/environment'
9
16
  require_relative 'sub_zero/main'
10
17
 
11
18
  module SubZero
12
- autoload :CLI, 'sub_zero/cli'
13
- autoload :Client, 'sub_zero/client'
19
+ autoload :CLI, 'sub_zero/cli'
20
+ autoload :Client, 'sub_zero/client'
21
+ autoload :Configuration, 'sub_zero/configuration'
22
+ autoload :Loggable, 'sub_zero/loggable'
23
+ autoload :Message, 'sub_zero/message'
24
+ autoload :Service, 'sub_zero/service'
25
+ autoload :Socket, 'sub_zero/socket'
14
26
  extend self
27
+ extend Environment
15
28
 
16
29
  def client service_id
17
30
  block_given? ? Client.new(service_id, &block) : Client.new(service_id)
data/spec/spec_helper.rb CHANGED
@@ -0,0 +1,9 @@
1
+ ENV['SZ_ENV'] ||= 'test'
2
+
3
+ $:.push '.'
4
+
5
+ require 'rspec'
6
+ require 'pry'
7
+ require 'sub_zero'
8
+
9
+ Dir['spec/support/**/*.rb'].each &method(:require)
@@ -0,0 +1,72 @@
1
+ require 'spec_helper'
2
+
3
+ describe SubZero::Client do
4
+
5
+ subject { described_class.new :sid }
6
+
7
+ let(:config) { { ip: '127.0.0.1', port: 7777 } }
8
+
9
+ its(:sid) { should eq('SID') }
10
+ its(:config) { should eq(config) }
11
+
12
+ describe '#socket' do
13
+ let(:socket) { double :socket }
14
+
15
+ before do
16
+ SubZero::Socket.stub(:new).with(config) { socket }
17
+ end
18
+
19
+ its(:socket) { should eq(socket) }
20
+ end
21
+
22
+ describe '#call' do
23
+ let(:socket) { double :socket }
24
+ let(:response) { double :response, error?: false, payload: { found: true } }
25
+
26
+ before do
27
+ subject.stub(:socket) { socket }
28
+
29
+ socket.should_receive :call do |request|
30
+ request.type.should eq('REQ')
31
+ request.sid.should eq('SID')
32
+ request.verb.should eq('GET/USER')
33
+ request.payload.should eq(id: 2)
34
+ request.options.should eq(timeout: 30)
35
+ response
36
+ end
37
+ end
38
+
39
+ it 'returns response payload' do
40
+ subject.call(:get_user, { id: 2 }, { timeout: 30 }).should eq(found: true)
41
+ end
42
+
43
+ it 'injects full response in block' do
44
+ subject.call :get_user, { id: 2 }, { timeout: 30 } do |result|
45
+ result.should eq(response)
46
+ end
47
+ end
48
+ end
49
+
50
+ describe '#[]' do
51
+ let(:response) { double :response }
52
+
53
+ it 'is a different way to do call' do
54
+ subject.should_receive(:call).with(:get_user) { response }
55
+ subject[:get_user].should eq(response)
56
+ end
57
+ end
58
+
59
+ describe 'calling verbs via method missing' do
60
+ let(:response) { double :response }
61
+ let(:args) { [{ id: 2 }, { timeout: 3000 }] }
62
+
63
+ it 'calls verb with method missing name' do
64
+ subject.should_receive(:call).with(:get_user, *args) { response }
65
+ subject.get_user(*args).should eq(response)
66
+
67
+ subject.should_receive(:call!).with('get_user', *args) { response }
68
+ subject.get_user!(*args).should eq(response)
69
+ end
70
+ end
71
+
72
+ end
@@ -0,0 +1,16 @@
1
+ require 'spec_helper'
2
+
3
+ describe SubZero::Environment do
4
+
5
+ subject do
6
+ Class.new { extend SubZero::Environment }
7
+ end
8
+
9
+ its(:env) { should eq('test') }
10
+
11
+ specify '#env?' do
12
+ subject.env.test?.should be_true
13
+ subject.env.development?.should be_false
14
+ end
15
+
16
+ end
@@ -0,0 +1,38 @@
1
+ require 'spec_helper'
2
+
3
+ describe SubZero::Service do
4
+
5
+ class Auditing
6
+ extend SubZero::Service
7
+
8
+ sid :auditing
9
+ end
10
+
11
+ class Auditing
12
+ module Handlers
13
+ class Logs < SubZero::Service::Handler
14
+ end
15
+ end
16
+ end
17
+
18
+ subject { Auditing }
19
+
20
+ describe '.sid' do
21
+ it 'retrieves sid' do
22
+ subject.sid.should eq(:auditing)
23
+ end
24
+ end
25
+
26
+ describe '.route' do
27
+ before do
28
+ subject.route do
29
+ verb list: 'logs#index'
30
+ end
31
+ end
32
+
33
+ it 'defines routes' do
34
+ subject.routes.key?('LIST').should be_true
35
+ end
36
+ end
37
+
38
+ end
data/sub_zero.gemspec CHANGED
@@ -4,7 +4,7 @@ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
4
  require 'sub_zero/version'
5
5
 
6
6
  Gem::Specification.new do |spec|
7
- spec.name = "sub_zero"
7
+ spec.name = 'sub_zero'
8
8
  spec.version = SubZero::VERSION
9
9
  spec.authors = ["Victor Rodrigues", "Bruno Antunes"]
10
10
  spec.email = ["victorc.rodrigues@gmail.com", "sardaukar.siet@gmail.com"]
@@ -21,9 +21,12 @@ Gem::Specification.new do |spec|
21
21
  spec.add_development_dependency 'bundler', '~> 1.3'
22
22
  spec.add_development_dependency 'rake'
23
23
  spec.add_development_dependency 'rspec'
24
+ spec.add_development_dependency 'pry'
24
25
 
25
26
  spec.add_dependency 'thor'
26
27
  spec.add_dependency 'msgpack'
27
28
  spec.add_dependency 'ffi-rzmq'
28
29
  spec.add_dependency 'activesupport'
30
+ spec.add_dependency 'colorize'
31
+ spec.add_dependency 'daemons'
29
32
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: sub_zero
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.4
4
+ version: 0.0.5
5
5
  platform: ruby
6
6
  authors:
7
7
  - Victor Rodrigues
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2013-08-29 00:00:00.000000000 Z
12
+ date: 2013-09-17 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: bundler
@@ -53,6 +53,20 @@ dependencies:
53
53
  - - '>='
54
54
  - !ruby/object:Gem::Version
55
55
  version: '0'
56
+ - !ruby/object:Gem::Dependency
57
+ name: pry
58
+ requirement: !ruby/object:Gem::Requirement
59
+ requirements:
60
+ - - '>='
61
+ - !ruby/object:Gem::Version
62
+ version: '0'
63
+ type: :development
64
+ prerelease: false
65
+ version_requirements: !ruby/object:Gem::Requirement
66
+ requirements:
67
+ - - '>='
68
+ - !ruby/object:Gem::Version
69
+ version: '0'
56
70
  - !ruby/object:Gem::Dependency
57
71
  name: thor
58
72
  requirement: !ruby/object:Gem::Requirement
@@ -109,6 +123,34 @@ dependencies:
109
123
  - - '>='
110
124
  - !ruby/object:Gem::Version
111
125
  version: '0'
126
+ - !ruby/object:Gem::Dependency
127
+ name: colorize
128
+ requirement: !ruby/object:Gem::Requirement
129
+ requirements:
130
+ - - '>='
131
+ - !ruby/object:Gem::Version
132
+ version: '0'
133
+ type: :runtime
134
+ prerelease: false
135
+ version_requirements: !ruby/object:Gem::Requirement
136
+ requirements:
137
+ - - '>='
138
+ - !ruby/object:Gem::Version
139
+ version: '0'
140
+ - !ruby/object:Gem::Dependency
141
+ name: daemons
142
+ requirement: !ruby/object:Gem::Requirement
143
+ requirements:
144
+ - - '>='
145
+ - !ruby/object:Gem::Version
146
+ version: '0'
147
+ type: :runtime
148
+ prerelease: false
149
+ version_requirements: !ruby/object:Gem::Requirement
150
+ requirements:
151
+ - - '>='
152
+ - !ruby/object:Gem::Version
153
+ version: '0'
112
154
  description: ZeroMQ SOA solution
113
155
  email:
114
156
  - victorc.rodrigues@gmail.com
@@ -148,12 +190,26 @@ files:
148
190
  - lib/sub_zero/cli/templates/ruby/service/verbs.tt
149
191
  - lib/sub_zero/cli/templates/ruby/service/version.tt
150
192
  - lib/sub_zero/client.rb
151
- - lib/sub_zero/client/configuration.rb
152
- - lib/sub_zero/client/socket.rb
193
+ - lib/sub_zero/configuration.rb
194
+ - lib/sub_zero/environment.rb
195
+ - lib/sub_zero/loggable.rb
153
196
  - lib/sub_zero/main.rb
154
197
  - lib/sub_zero/main/common.rb
198
+ - lib/sub_zero/message.rb
199
+ - lib/sub_zero/message/parser.rb
200
+ - lib/sub_zero/message/validations.rb
201
+ - lib/sub_zero/service.rb
202
+ - lib/sub_zero/service/handler.rb
203
+ - lib/sub_zero/service/router.rb
204
+ - lib/sub_zero/service/runner.rb
205
+ - lib/sub_zero/socket.rb
206
+ - lib/sub_zero/socket/sender.rb
207
+ - lib/sub_zero/socket/server.rb
155
208
  - lib/sub_zero/version.rb
156
209
  - spec/spec_helper.rb
210
+ - spec/sub_zero/client_spec.rb
211
+ - spec/sub_zero/environment_spec.rb
212
+ - spec/sub_zero/service_spec.rb
157
213
  - sub_zero.gemspec
158
214
  - thoughts.md
159
215
  homepage: ''
@@ -182,3 +238,6 @@ specification_version: 4
182
238
  summary: ZeroMQ GREAT SOA solution
183
239
  test_files:
184
240
  - spec/spec_helper.rb
241
+ - spec/sub_zero/client_spec.rb
242
+ - spec/sub_zero/environment_spec.rb
243
+ - spec/sub_zero/service_spec.rb
@@ -1,12 +0,0 @@
1
- module SubZero
2
- class Client
3
- module Configuration
4
- extend self
5
-
6
- def default
7
- { ip: '127.0.0.1', port: 7777 }
8
- end
9
-
10
- end
11
- end
12
- end
@@ -1,98 +0,0 @@
1
- require 'ffi-rzmq'
2
- require 'msgpack'
3
-
4
- module SubZero
5
- class Client
6
- module Socket
7
-
8
- class SocketError < StandardError; end
9
-
10
- private
11
-
12
- def zeromq_fetch verb, payload = {}, options = {}
13
- result = []
14
-
15
- timeout = options.fetch(:timeout, 1000) / 1000.0
16
-
17
- Timeout.timeout timeout do
18
- zeromq_context do |context|
19
- zeromq_socket context do |socket|
20
- rid = SecureRandom.uuid
21
- zeromq_send socket, "REQ:#{sid}", rid, verb, payload.to_msgpack, options.to_msgpack
22
- result = zeromq_result(socket, rid, verb)
23
- end
24
- end
25
- end
26
-
27
- result
28
- rescue Timeout::Error
29
- raise SubZero::Client::Error.new(code: 'timeout', message: "call timeout: #{timeout}s")
30
- end
31
-
32
- def zeromq_context
33
- context = ZMQ::Context.create(1)
34
- fail SocketError, 'failed to create context' unless context
35
- yield context
36
- ensure
37
- zcc!(context.terminate) if context
38
- end
39
-
40
- def zeromq_socket context
41
- socket = context.socket ZMQ::DEALER
42
- socket.identity = SecureRandom.hex(10)
43
- zcc! socket.connect("tcp://#{config[:ip]}:#{config[:port]}")
44
- yield socket
45
- ensure
46
- zcc! socket.close
47
- end
48
-
49
- def zeromq_send socket, *msgs
50
- last = msgs.pop
51
- msgs.each { |m| zcc! socket.send_string m, ZMQ::SNDMORE }
52
- zcc! socket.send_string last
53
- end
54
-
55
- def zeromq_check_code! result_code
56
- return if ZMQ::Util.resultcode_ok? result_code
57
-
58
- fail SocketError, "operation failed, errno [#{ZMQ::Util.errno}], " +
59
- "description [#{ZMQ::Util.error_string}]"
60
- end
61
-
62
- alias :zcc! :zeromq_check_code!
63
-
64
- def zeromq_result socket, rid, verb
65
- result = []
66
- zcc! socket.recv_strings(result)
67
-
68
- zeromq_validate_result! rid, verb, result
69
-
70
- routing_info = MessagePack.unpack(result.pop)
71
- payload = MessagePack.unpack(result.pop)
72
- rep_verb = result.pop
73
- status = rep_verb.end_with?('NOK') ? :error : :ok
74
-
75
- [status, payload]
76
- end
77
-
78
- def zeromq_validate_result! rid, verb, result
79
- type, rep_rid, rep_verb, payload = result
80
-
81
- common = "result: #{result}"
82
-
83
- unless type == "REP:#{sid}" || type == 'BRO'
84
- fail SocketError, "unexpected result type: #{type}. " + common
85
- end
86
-
87
- unless rid == rep_rid
88
- fail SocketError, "rid mismatch. sent: #{rid}, received: #{rep_id}. " + common
89
- end
90
-
91
- unless rep_verb == "#{verb}:OK" || rep_verb == "#{verb}:NOK"
92
- fail SocketError, "reply verb mismatch: #{rep_verb}. " + common
93
- end
94
- end
95
-
96
- end
97
- end
98
- end