sub_zero 0.0.1 → 0.0.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (38) hide show
  1. checksums.yaml +4 -4
  2. data/LICENSE +20 -0
  3. data/README.md +1 -1
  4. data/bin/sub_zero +6 -0
  5. data/example/auditing/Gemfile +4 -0
  6. data/example/auditing/README.md +5 -0
  7. data/example/auditing/Rakefile +2 -0
  8. data/example/auditing/auditing.gemspec +25 -0
  9. data/example/auditing/config.yml +2 -0
  10. data/example/auditing/lib/auditing/handlers/logs.rb +30 -0
  11. data/example/auditing/lib/auditing/handlers/status.rb +29 -0
  12. data/example/auditing/lib/auditing/version.rb +3 -0
  13. data/example/auditing/lib/auditing.rb +21 -0
  14. data/example/auditing-client/run.rb +42 -0
  15. data/lib/sub_zero/cli/app.rb +7 -0
  16. data/lib/sub_zero/cli/new.rb +89 -0
  17. data/lib/sub_zero/cli/templates/ruby/client/client.tt +2 -0
  18. data/lib/sub_zero/cli/templates/ruby/service/Gemfile +8 -0
  19. data/lib/sub_zero/cli/templates/ruby/service/bin.tt +44 -0
  20. data/lib/sub_zero/cli/templates/ruby/service/handler.tt +1 -0
  21. data/lib/sub_zero/cli/templates/ruby/service/lib.tt +47 -0
  22. data/lib/sub_zero/cli/templates/ruby/service/rvmrc.tt +1 -0
  23. data/lib/sub_zero/cli/templates/ruby/service/serviceyml.tt +12 -0
  24. data/lib/sub_zero/cli/templates/ruby/service/verbs.tt +1 -0
  25. data/lib/sub_zero/cli/templates/ruby/service/version.tt +3 -0
  26. data/lib/sub_zero/cli.rb +6 -0
  27. data/lib/sub_zero/client/configuration.rb +12 -0
  28. data/lib/sub_zero/client/socket.rb +92 -0
  29. data/lib/sub_zero/client.rb +70 -0
  30. data/lib/sub_zero/main/common.rb +11 -0
  31. data/lib/sub_zero/main.rb +64 -0
  32. data/lib/sub_zero/version.rb +1 -1
  33. data/lib/sub_zero.rb +16 -2
  34. data/spec/spec_helper.rb +0 -0
  35. data/sub_zero.gemspec +10 -4
  36. data/thoughts.md +60 -0
  37. metadata +110 -6
  38. data/LICENSE.txt +0 -22
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 5a5592345c5e4af640cd01b216b282ed95f8d7d5
4
- data.tar.gz: 84a3ad5d2d34919792a6273213391dc7172005bd
3
+ metadata.gz: 0c3d06f3806bd38f972069cccc381a5e14a10552
4
+ data.tar.gz: 201442b45283cc753950167905a088a450ec613a
5
5
  SHA512:
6
- metadata.gz: a3d8f3de9e64d9c380f8329c916663eec6230b13edf321a5a4a4d52be2d6d6ef0bb741e407885392973a696c08639874922fd317a9c401750d2b1d3bee1b58f4
7
- data.tar.gz: 8f1d4fec8c5f7994ee4671593096e3512518fc67107b3c583b5a6aa8328a0599ca4ae9436bf2ff6f662f944cfda6a045b153a3020bf89536535d0035cb00fcc7
6
+ metadata.gz: 59833793e76d2543ad4ed8948f852b7a8b13b0db67e44352cf55c4df36044b16669f84cd8a6e5df9e8134a7c20f36a245bbe760b7fd3c5a30696ebe61b56dacf
7
+ data.tar.gz: 2aee09d0ea9f147d2acf510203f0b71d7619876b8dbe5750d32f6153f1710ce0e6aad0cdfdd1d96013a96643928c36a11becfc4c5f7b02e61efc2ce1eed31b3c
data/LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2013 ClubJudge B.V.
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy of
6
+ this software and associated documentation files (the "Software"), to deal in
7
+ the Software without restriction, including without limitation the rights to
8
+ use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
9
+ the Software, and to permit persons to whom the Software is furnished to do so,
10
+ subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
17
+ FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
18
+ COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
19
+ IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
20
+ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # SubZero
2
2
 
3
- TODO: Write a gem description
3
+
4
4
 
5
5
  ## Installation
6
6
 
data/bin/sub_zero ADDED
@@ -0,0 +1,6 @@
1
+ #!/usr/bin/env ruby
2
+ # -*- mode: ruby -*-
3
+
4
+ require_relative '../lib/sub_zero.rb'
5
+
6
+ SubZero::CLI::App.start
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in sub_zero.gemspec
4
+ gemspec
@@ -0,0 +1,5 @@
1
+ # SubZero: Example App
2
+
3
+ An app can be created using:
4
+
5
+ subzero new appname
@@ -0,0 +1,2 @@
1
+ require 'bundler/gem_tasks'
2
+ require 'sub_zero/service/tasks'
@@ -0,0 +1,25 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'auditing/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = 'auditing'
8
+ spec.version = Auditing::VERSION
9
+ spec.authors = ['Victor Rodrigues']
10
+ spec.email = ['victorc.rodrigues@gmail.com']
11
+ spec.description = %q{SubZero app example}
12
+ spec.summary = %q{SubZero app example}
13
+ spec.homepage = ""
14
+ spec.license = "MIT"
15
+
16
+ spec.files = `git ls-files`.split($/)
17
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
18
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
+ spec.require_paths = ["lib"]
20
+
21
+ spec.add_development_dependency 'bundler', '~> 1.3'
22
+ spec.add_development_dependency 'rake'
23
+
24
+ spec.add_dependency 'sub_zero'
25
+ end
@@ -0,0 +1,2 @@
1
+ broker:
2
+ uri: 'localhost:5560'
@@ -0,0 +1,30 @@
1
+ module Auditing
2
+ module Handlers
3
+ class Logs < SubZero::Service::Handler
4
+
5
+ def create
6
+ Log.create params
7
+ reply :ok
8
+ end
9
+
10
+ def index
11
+ reply_with Log.all
12
+ end
13
+
14
+ end
15
+ end
16
+ end
17
+
18
+ __END__
19
+
20
+ #params is the message payload desserialized from messagepack
21
+
22
+ #request_id is accessible through here
23
+
24
+ #reply(verb, payload = nil)
25
+
26
+ #reply_with(content) => same verb
27
+ #reply_with(verb, content) => other verb
28
+ (both serialize content to msgpack)
29
+
30
+ #logger might be very useful
@@ -0,0 +1,29 @@
1
+ module Auditing
2
+ module Handlers
3
+ class Status < SubZero::Service::Handler
4
+
5
+ def show
6
+ reply :working
7
+ end
8
+
9
+ def count
10
+ reply_with Log.count
11
+ end
12
+
13
+ end
14
+ end
15
+ end
16
+
17
+ __END__
18
+
19
+ #params is the message payload desserialized from messagepack
20
+
21
+ #request_id is accessible through here
22
+
23
+ #reply(verb, payload = nil)
24
+
25
+ #reply_with(content) => same verb
26
+ #reply_with(verb, content) => other verb
27
+ (both serialize content to msgpack)
28
+
29
+ #logger might be very useful
@@ -0,0 +1,3 @@
1
+ module Auditing
2
+ VERSION = '0.0.1'
3
+ end
@@ -0,0 +1,21 @@
1
+ require 'rubygems'
2
+
3
+ ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../Gemfile', __FILE__)
4
+
5
+ require 'bundler/setup' if File.exists?(ENV['BUNDLE_GEMFILE'])
6
+
7
+ module Auditing
8
+ extend SubZero::Service
9
+
10
+ sid :auditing
11
+
12
+ verbs log: 'logs#create',
13
+ retrieve: 'logs#index',
14
+ status: 'status#show',
15
+ 'status/count' => 'status#count'
16
+
17
+ end
18
+
19
+ __END__
20
+
21
+ verbs targets classes will try to be required / constantized from auditing/ or auditing/handlers as they are declared
@@ -0,0 +1,42 @@
1
+ require 'sub_zero'
2
+
3
+ Auditing = SubZero.client(:auditing)
4
+
5
+ # or
6
+
7
+ Auditing = SubZero.client :auditing do |c|
8
+ c.timeout = 5000
9
+ # what else? retry?
10
+ end
11
+
12
+ # fire and forget, just waits the Broker ACK to not care anymore, opens a thread
13
+ Auditing.log! author: 'Pedro Alvares Cabral', action: 'discovered Brazil.. heh.'
14
+
15
+ # waits for reply
16
+ ronconcon_logs = Auditing.index(author: 'Marques de Pombal')
17
+
18
+ # for more complex verbs, the base method call:
19
+
20
+ Auditing.call! 'bugs/report', error: 'error while trying to log'
21
+
22
+ Auditing.call 'stats/count'
23
+
24
+ Auditing.stats_count
25
+
26
+ # some sugar to sync call might be
27
+
28
+ Auditing['stats/count']
29
+
30
+
31
+ Auditing.stats! do |stats|
32
+ DeveloperChatRoom.push "Availabilty: #{stats[:availability]}"
33
+ end
34
+
35
+
36
+ # reply:
37
+
38
+ # ACK:NOK { error: { message: '', code: '', … } } (BROKER)
39
+ # STATS/COUNT:OK
40
+ # STATS/COUNT:NOK { error: { message: '', code: '', … }}
41
+ # retry strategy
42
+
@@ -0,0 +1,7 @@
1
+ module SubZero
2
+ module CLI
3
+ class App < Thor
4
+ register SubZero::CLI::New, 'new', 'new TYPE NAME', 'Creates a new TYPE (service/client) named NAME'
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,89 @@
1
+ module SubZero
2
+ module CLI
3
+ class New < ::Thor
4
+ include ::Thor::Actions
5
+
6
+ attr_accessor :name
7
+
8
+ def self.source_root
9
+ File.dirname(__FILE__)
10
+ end
11
+
12
+ class_option :language, desc: 'language template to use', default: 'ruby', type: :string
13
+ class_option :test_framework, desc: 'test framework to use', default: 'rspec'
14
+ class_option :with_rvm, desc: 'include .rvmrc', default: true
15
+
16
+ desc 'service NAME', 'Creates a SubZero service'
17
+ def service name=nil
18
+ if name.nil?
19
+ say "You must supply a name!"
20
+ exit 1
21
+ end
22
+
23
+ say "Creating #{name} service..."
24
+ create_service name, options
25
+ end
26
+
27
+ desc 'client NAME', 'Creates a SubZero client'
28
+ def client name=nil
29
+ if name.nil?
30
+ say "You must supply a name!"
31
+ exit 1
32
+ end
33
+
34
+ say "Creating #{name} client..."
35
+ create_client name, options
36
+ end
37
+
38
+ #######
39
+ private
40
+ #######
41
+
42
+ def create_client name, options
43
+ self.name = name # ERB ... :/
44
+ template("templates/#{options[:language]}/client.tt", "#{name}/lib/#{name}.rb")
45
+
46
+ # TODO
47
+ end
48
+
49
+ def create_service name, options
50
+ # |-- Gemfile
51
+ # |-- bin
52
+ # | `-- name
53
+ # |-- config
54
+ # | |-- service.yml
55
+ # | `-- verbs.rb
56
+ # |-- lib
57
+ # | |-- handlers
58
+ # | | `-- handler.rb
59
+ # | `-- name.rb
60
+ # |-- rvmrc
61
+ # `-- spec
62
+ # `-- name_spec.rb
63
+
64
+ name = name.downcase
65
+ self.name = name # ERB ... :/
66
+ template("templates/#{options[:language]}/service/Gemfile", "#{name}/Gemfile")
67
+ template("templates/#{options[:language]}/service/bin.tt", "#{name}/bin/#{name}")
68
+ chmod("#{name}/bin/#{name}", 0755)
69
+ template("templates/#{options[:language]}/service/serviceyml.tt", "#{name}/config/service.yml")
70
+ template("templates/#{options[:language]}/service/verbs.tt", "#{name}/config/verbs.rb")
71
+ template("templates/#{options[:language]}/service/lib.tt", "#{name}/lib/#{name}.rb")
72
+ template("templates/#{options[:language]}/service/version.tt", "#{name}/lib/#{name}/version.rb")
73
+ template("templates/#{options[:language]}/service/handler.tt", "#{name}/lib/handlers/handler.rb")
74
+
75
+ test = options[:test_framework] == "rspec" ? :spec : :test
76
+ create_file "#{name}/#{test}/#{name}_#{test}.rb"
77
+
78
+ if options[:with_rvm]
79
+ template("templates/#{options[:language]}/service/rvmrc.tt", "#{name}/.rvmrc")
80
+ end
81
+
82
+ empty_directory "#{name}/doc"
83
+
84
+ say "all done! you can start a development server with bin/#{name} run"
85
+ end
86
+
87
+ end
88
+ end
89
+ end
@@ -0,0 +1,2 @@
1
+ class <%= name.capitalize %>
2
+ end
@@ -0,0 +1,8 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gem 'daemons'
4
+ gem 'em-zeromq'
5
+ gem 'msgpack'
6
+
7
+ gem 'pry'
8
+ gem 'sub_zero', :path => '/Users/bruno/Code/1WORK/sub_zero'
@@ -0,0 +1,44 @@
1
+ #!/usr/bin/env ruby
2
+ # -*- mode: ruby -*-
3
+
4
+ require 'rubygems' unless defined?(Gem)
5
+
6
+ require 'bundler/setup'
7
+ Bundler.require
8
+
9
+ require_relative '../lib/<%= name.downcase %>.rb'
10
+
11
+ service = SubZero::Main.boot ARGV
12
+
13
+ daemon_opts = {
14
+ multiple: false,
15
+ dir_mode: :normal,
16
+ dir: service.cli_args[:pid_path], # FIXME
17
+ log_output: true,
18
+ stop_proc: lambda { $stop_requested = true }
19
+ }
20
+
21
+ Daemons.run_proc '<%= name %>', daemon_opts do
22
+ daemon = <%= name.capitalize %>::Main.new service
23
+
24
+ start = Time.now
25
+ ping_at = start + 5
26
+
27
+ Signal.trap('INT') { daemon.do_exit_cleanup; exit }
28
+
29
+ loop do
30
+ daemon.poll_sockets
31
+
32
+ now = Time.now
33
+ if now >= ping_at
34
+ daemon.ping
35
+ ping_at = now + 15
36
+ end
37
+
38
+ break if $stop_requested
39
+
40
+ end
41
+
42
+ daemon.do_exit_cleanup
43
+ exit 0
44
+ end
@@ -0,0 +1,47 @@
1
+ require_relative "<%= name.capitalize %>/version"
2
+
3
+ module <%= name.capitalize %>
4
+ class Main
5
+ include SubZero::Common
6
+
7
+ def initialize service
8
+ @config = service.config
9
+ log "INITing socket"
10
+ end
11
+
12
+ def poll_sockets
13
+ print '.'
14
+ sleep 1
15
+ end
16
+
17
+ def ping
18
+ log "ping..."
19
+ end
20
+
21
+ #######
22
+ private
23
+ #######
24
+
25
+ def send_announce_packet
26
+ $sent = Time.now
27
+ @socket.send_string "SRV", ZMQ::SNDMORE
28
+ @socket.send_string 0.to_s, ZMQ::SNDMORE
29
+ @socket.send_string "UP", ZMQ::SNDMORE
30
+
31
+ payload = { id: @config['service']['id'], sid: @config['service']['sid'] }.to_msgpack
32
+ @socket.send_string payload
33
+ end
34
+
35
+ def init_socket
36
+ @context = ZMQ::Context.new
37
+
38
+ @socket = @context.socket ZMQ::DEALER
39
+ @socket.identity = @config['service']['id']
40
+ @socket.connect "tcp://#{@config['service']['broker_host']}:#{@config['service']['broker_port']}"
41
+
42
+ @poller = ZMQ::Poller.new
43
+ @poller.register @socket, ZMQ::POLLIN
44
+ end
45
+
46
+ end
47
+ end
@@ -0,0 +1 @@
1
+ rvm use 2.0@<%= name.capitalize %> --create
@@ -0,0 +1,12 @@
1
+ defaults: &defaults
2
+ service:
3
+ broker_host: "local.clubjudge.com"
4
+ broker_port: 7777
5
+ sid: "new_service"
6
+ id: "<%= ::SecureRandom.hex(10) %>"
7
+
8
+ development:
9
+ <<: *defaults
10
+
11
+ test:
12
+ <<: *defaults
@@ -0,0 +1,3 @@
1
+ module <%= name.capitalize %>
2
+ VERSION = "0.0.1"
3
+ end
@@ -0,0 +1,6 @@
1
+ module SubZero
2
+ module CLI
3
+ autoload :App, 'sub_zero/cli/app'
4
+ autoload :New, 'sub_zero/cli/new'
5
+ end
6
+ end
@@ -0,0 +1,12 @@
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
@@ -0,0 +1,92 @@
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
+ zeromq_context do |context|
16
+ zeromq_socket context do |socket|
17
+ rid = SecureRandom.uuid
18
+ zeromq_send socket, "REQ:#{sid}", rid, verb, payload.to_msgpack, options.to_msgpack
19
+ result = zeromq_result(socket, rid, verb)
20
+ end
21
+ end
22
+
23
+ result
24
+ end
25
+
26
+ def zeromq_context
27
+ context = ZMQ::Context.create(1)
28
+ fail SocketError, 'failed to create context' unless context
29
+ yield context
30
+ ensure
31
+ zcc!(context.terminate) if context
32
+ end
33
+
34
+ def zeromq_socket context
35
+ socket = context.socket ZMQ::DEALER
36
+ socket.identity = SecureRandom.hex(10)
37
+ zcc! socket.connect("tcp://#{config[:ip]}:#{config[:port]}")
38
+ yield socket
39
+ ensure
40
+ zcc! socket.close
41
+ end
42
+
43
+ def zeromq_send socket, *msgs
44
+ last = msgs.pop
45
+ msgs.each { |m| zcc! socket.send_string m, ZMQ::SNDMORE }
46
+ zcc! socket.send_string last
47
+ end
48
+
49
+ def zeromq_check_code! result_code
50
+ return if ZMQ::Util.resultcode_ok? result_code
51
+
52
+ fail SocketError, "operation failed, errno [#{ZMQ::Util.errno}], " +
53
+ "description [#{ZMQ::Util.error_string}]"
54
+ end
55
+
56
+ alias :zcc! :zeromq_check_code!
57
+
58
+ def zeromq_result socket, rid, verb
59
+ result = []
60
+ zcc! socket.recv_strings(result)
61
+
62
+ zeromq_validate_result! rid, verb, result
63
+
64
+ routing_info = MessagePack.unpack(result.pop)
65
+ payload = MessagePack.unpack(result.pop)
66
+ rep_verb = result.pop
67
+ status = rep_verb.end_with?('NOK') ? :error : :ok
68
+
69
+ [status, payload]
70
+ end
71
+
72
+ def zeromq_validate_result! rid, verb, result
73
+ type, rep_rid, rep_verb, payload = result
74
+
75
+ common = "result: #{result}"
76
+
77
+ unless type == "REP:#{sid}" || type == 'BRO'
78
+ fail SocketError, "unexpected result type: #{type}. " + common
79
+ end
80
+
81
+ unless rid == rep_rid
82
+ fail SocketError, "rid mismatch. sent: #{rid}, received: #{rep_id}. " + common
83
+ end
84
+
85
+ unless rep_verb == "#{verb}:OK" || rep_verb == "#{verb}:NOK"
86
+ fail SocketError, "reply verb mismatch: #{rep_verb}. " + common
87
+ end
88
+ end
89
+
90
+ end
91
+ end
92
+ end
@@ -0,0 +1,70 @@
1
+ require 'active_support/string_inquirer'
2
+
3
+ module SubZero
4
+ class Client
5
+ autoload :Configuration, 'sub_zero/client/configuration'
6
+ autoload :Socket, 'sub_zero/client/socket'
7
+
8
+ include Socket
9
+
10
+ attr_reader :sid, :config
11
+
12
+ def initialize sid
13
+ @sid, @config = sid.to_s.upcase, Configuration.default
14
+ yield @config if block_given?
15
+ end
16
+
17
+ def call verb, payload = {}, options = {}
18
+ sz_verb = verb.to_s.upcase.gsub('_', '/')
19
+ status, result = zeromq_fetch(sz_verb, payload, options)
20
+ result = handle_result(status, result)
21
+ block_given? ? yield(result) : result
22
+ end
23
+
24
+ def call! verb, payload = {}, options = {}, &block
25
+ call verb, payload, options, &block
26
+ end
27
+
28
+ def [] verb
29
+ call verb
30
+ end
31
+
32
+ def method_missing method, payload = {}, options = {}, &block
33
+ if method.to_s.end_with? '!'
34
+ call! method.delete('!'), payload, options, &block
35
+ else
36
+ call method, payload, options, &block
37
+ end
38
+ end
39
+
40
+ def handle_result status, result
41
+ case status
42
+ when :ok
43
+ result
44
+ when :error
45
+ fail Error.new(result['error'])
46
+ end
47
+ end
48
+
49
+ class Error < ::StandardError
50
+
51
+ attr_reader :result
52
+
53
+ def initialize result
54
+ super result['message']
55
+ set_backtrace caller
56
+ @result = result
57
+ end
58
+
59
+ def code
60
+ result['code']
61
+ end
62
+
63
+ def status
64
+ ActiveSupport::StringInquirer.new self.code.to_s.downcase
65
+ end
66
+
67
+ end
68
+
69
+ end
70
+ end
@@ -0,0 +1,11 @@
1
+ module SubZero
2
+ module Common
3
+ def log msg, level='DEBUG'
4
+ puts "#{level}: #{msg}"
5
+ end
6
+
7
+ def env
8
+ ENV['SUBZERO_ENV'] || 'development'
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,64 @@
1
+ require_relative 'main/common'
2
+
3
+ module SubZero
4
+ module Main
5
+ include Common
6
+ extend self
7
+
8
+ attr_accessor :config, :cli_args
9
+
10
+ def boot cli_args
11
+ log "booting..."
12
+
13
+ log "\tloading service.yml"
14
+ @config = load_config
15
+ log "\tparsing CLI args"
16
+ @cli_args = parse_cli_args cli_args
17
+
18
+ self
19
+ end
20
+
21
+ #######
22
+ private
23
+ #######
24
+
25
+
26
+ def usage(s)
27
+ $stderr.puts "<%= name %> v#{SubZero::VERSION}" # change to const for the service!
28
+ $stderr.puts s
29
+ $stderr.puts "Usage: #{File.basename($0)}: [-p port] [-l log_path] [-pp pid_path]"
30
+ exit(1)
31
+ end
32
+
33
+ def parse_cli_args args
34
+ opts = {}
35
+
36
+ port = @config['service']['broker_port']
37
+ pid_path = log_path = File.join( File.dirname(__FILE__), '..')
38
+
39
+ loop { case ARGV[0]
40
+ when '-p' then ARGV.shift; port = ARGV.shift
41
+ when '-l' then ARGV.shift; log_path = ARGV.shift
42
+ when '-pp' then ARGV.shift; pid_path = ARGV.shift
43
+ when /^-/ then usage("Unknown option: #{ARGV[0].inspect}")
44
+ else break
45
+ end; }
46
+
47
+ opts[:port] = port
48
+ opts[:log_path] = log_path
49
+ opts[:pid_path] = pid_path
50
+
51
+ opts
52
+ end
53
+
54
+ def load_config
55
+ begin
56
+ YAML.load_file('config/service.yml')[env]
57
+ rescue => ex
58
+ log "could not load config file! (#{ex.message})", 'ERROR'
59
+ exit 1
60
+ end
61
+ end
62
+
63
+ end
64
+ end
@@ -1,3 +1,3 @@
1
1
  module SubZero
2
- VERSION = "0.0.1"
2
+ VERSION = "0.0.3"
3
3
  end
data/lib/sub_zero.rb CHANGED
@@ -1,5 +1,19 @@
1
- require "sub_zero/version"
1
+ require 'yaml'
2
+ require 'securerandom'
3
+
4
+ require 'thor'
5
+ require 'thor/group'
6
+
7
+ require_relative 'sub_zero/version'
8
+ require_relative 'sub_zero/main'
2
9
 
3
10
  module SubZero
4
- # Your code goes here...
11
+ autoload :CLI, 'sub_zero/cli'
12
+ autoload :Client, 'sub_zero/client'
13
+ extend self
14
+
15
+ def client service_id
16
+ block_given? ? Client.new(service_id, &block) : Client.new(service_id)
17
+ end
18
+
5
19
  end
File without changes
data/sub_zero.gemspec CHANGED
@@ -6,8 +6,8 @@ require 'sub_zero/version'
6
6
  Gem::Specification.new do |spec|
7
7
  spec.name = "sub_zero"
8
8
  spec.version = SubZero::VERSION
9
- spec.authors = ["Victor Rodrigues"]
10
- spec.email = ["victorc.rodrigues@gmail.com"]
9
+ spec.authors = ["Victor Rodrigues", "Bruno Antunes"]
10
+ spec.email = ["victorc.rodrigues@gmail.com", "sardaukar.siet@gmail.com"]
11
11
  spec.description = %q{ZeroMQ SOA solution}
12
12
  spec.summary = %q{ZeroMQ GREAT SOA solution}
13
13
  spec.homepage = ""
@@ -18,6 +18,12 @@ Gem::Specification.new do |spec|
18
18
  spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
19
  spec.require_paths = ["lib"]
20
20
 
21
- spec.add_development_dependency "bundler", "~> 1.3"
22
- spec.add_development_dependency "rake"
21
+ spec.add_development_dependency 'bundler', '~> 1.3'
22
+ spec.add_development_dependency 'rake'
23
+ spec.add_development_dependency 'rspec'
24
+
25
+ spec.add_dependency 'thor'
26
+ spec.add_dependency 'msgpack'
27
+ spec.add_dependency 'ffi-rzmq'
28
+ spec.add_dependency 'activesupport'
23
29
  end
data/thoughts.md ADDED
@@ -0,0 +1,60 @@
1
+ SubZero is meant to be a way for us to dab into polyglot architectures.
2
+
3
+ SubZero itself is made up of 3 parts:
4
+
5
+ Broker
6
+ ======
7
+
8
+ The traffic cop of the scheme. The Broker mediates requests between Services and Clients. Clients and Services cannot talk directly. Responsabilities:
9
+
10
+ - route messages between components
11
+ - know of active instances of certain Services
12
+ - have a TTL scheme to guess when components are down
13
+ - manage retries
14
+
15
+ Services
16
+ ========
17
+
18
+ Services exchange messages with clients. When a service boots up, it must register with the Broker before accepting work.
19
+
20
+ Clients
21
+ =======
22
+
23
+ Cients send requests to the Broker for specific Service IDs (but not instances of Services).
24
+
25
+ Messages
26
+ --------
27
+
28
+ There are two types of messages: Broker to Client( or Service) and Client (or Service) to Broker. Since the Broker has a DEALER socket, all of its outgoing messages are prefixed with an ID.
29
+
30
+ Typical envelope:
31
+
32
+ <pre>
33
+ ID - string matching the ZMQ identity of a socket (only for outgoing messages from the Broker)
34
+ RID - UUID that is preserved on all messages pertaining to this request
35
+ TYPE and optionally SUBTYPE after ':' - examples:
36
+ BRO (when Broker replies to PINGs from services)
37
+ SRV (when Service boots up and announces itself)
38
+ CLI:SID (Client asking for a Service reply)
39
+ REQ:ID (Broker forwarding Client request to Service)
40
+ SRV:ID (Service replying to Broker about client request)
41
+ REP:SID (Broker forwards Service reply to Clent)
42
+ VERB - can be PING, PONG, UP, ACK, SORT, TAG, etc. Victor suggested subverbs and I agree or else we'll have huge verb handlers on all Services
43
+ PAYLOAD - a MessagePack serialized hash
44
+ </pre>
45
+
46
+
47
+ Intended flow for Service authoring
48
+ ===================================
49
+
50
+ 1. sub_zero new service X
51
+ 2. cd X
52
+ 3. edit config.yml to set broker options (URI, port, etc.)
53
+ 4. add routes to verbs.rb
54
+ 5. create class with handlers (subclass of SubZero::Handler ?)
55
+ 6. when production-ready, run cap deploy to install it on /services (or whatever) in PRD
56
+ 7. call /etc/init.d/sub_zero start X in PRD to start service
57
+
58
+ Variations:
59
+ - sub_zero new service X --lang=scala ? To use different file templates?
60
+
metadata CHANGED
@@ -1,14 +1,15 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: sub_zero
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1
4
+ version: 0.0.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Victor Rodrigues
8
+ - Bruno Antunes
8
9
  autorequire:
9
10
  bindir: bin
10
11
  cert_chain: []
11
- date: 2013-07-17 00:00:00.000000000 Z
12
+ date: 2013-08-26 00:00:00.000000000 Z
12
13
  dependencies:
13
14
  - !ruby/object:Gem::Dependency
14
15
  name: bundler
@@ -38,21 +39,123 @@ dependencies:
38
39
  - - '>='
39
40
  - !ruby/object:Gem::Version
40
41
  version: '0'
42
+ - !ruby/object:Gem::Dependency
43
+ name: rspec
44
+ requirement: !ruby/object:Gem::Requirement
45
+ requirements:
46
+ - - '>='
47
+ - !ruby/object:Gem::Version
48
+ version: '0'
49
+ type: :development
50
+ prerelease: false
51
+ version_requirements: !ruby/object:Gem::Requirement
52
+ requirements:
53
+ - - '>='
54
+ - !ruby/object:Gem::Version
55
+ version: '0'
56
+ - !ruby/object:Gem::Dependency
57
+ name: thor
58
+ requirement: !ruby/object:Gem::Requirement
59
+ requirements:
60
+ - - '>='
61
+ - !ruby/object:Gem::Version
62
+ version: '0'
63
+ type: :runtime
64
+ prerelease: false
65
+ version_requirements: !ruby/object:Gem::Requirement
66
+ requirements:
67
+ - - '>='
68
+ - !ruby/object:Gem::Version
69
+ version: '0'
70
+ - !ruby/object:Gem::Dependency
71
+ name: msgpack
72
+ requirement: !ruby/object:Gem::Requirement
73
+ requirements:
74
+ - - '>='
75
+ - !ruby/object:Gem::Version
76
+ version: '0'
77
+ type: :runtime
78
+ prerelease: false
79
+ version_requirements: !ruby/object:Gem::Requirement
80
+ requirements:
81
+ - - '>='
82
+ - !ruby/object:Gem::Version
83
+ version: '0'
84
+ - !ruby/object:Gem::Dependency
85
+ name: ffi-rzmq
86
+ requirement: !ruby/object:Gem::Requirement
87
+ requirements:
88
+ - - '>='
89
+ - !ruby/object:Gem::Version
90
+ version: '0'
91
+ type: :runtime
92
+ prerelease: false
93
+ version_requirements: !ruby/object:Gem::Requirement
94
+ requirements:
95
+ - - '>='
96
+ - !ruby/object:Gem::Version
97
+ version: '0'
98
+ - !ruby/object:Gem::Dependency
99
+ name: activesupport
100
+ requirement: !ruby/object:Gem::Requirement
101
+ requirements:
102
+ - - '>='
103
+ - !ruby/object:Gem::Version
104
+ version: '0'
105
+ type: :runtime
106
+ prerelease: false
107
+ version_requirements: !ruby/object:Gem::Requirement
108
+ requirements:
109
+ - - '>='
110
+ - !ruby/object:Gem::Version
111
+ version: '0'
41
112
  description: ZeroMQ SOA solution
42
113
  email:
43
114
  - victorc.rodrigues@gmail.com
44
- executables: []
115
+ - sardaukar.siet@gmail.com
116
+ executables:
117
+ - sub_zero
45
118
  extensions: []
46
119
  extra_rdoc_files: []
47
120
  files:
48
121
  - .gitignore
49
122
  - Gemfile
50
- - LICENSE.txt
123
+ - LICENSE
51
124
  - README.md
52
125
  - Rakefile
126
+ - bin/sub_zero
127
+ - example/auditing-client/run.rb
128
+ - example/auditing/Gemfile
129
+ - example/auditing/README.md
130
+ - example/auditing/Rakefile
131
+ - example/auditing/auditing.gemspec
132
+ - example/auditing/config.yml
133
+ - example/auditing/lib/auditing.rb
134
+ - example/auditing/lib/auditing/handlers/logs.rb
135
+ - example/auditing/lib/auditing/handlers/status.rb
136
+ - example/auditing/lib/auditing/version.rb
53
137
  - lib/sub_zero.rb
138
+ - lib/sub_zero/cli.rb
139
+ - lib/sub_zero/cli/app.rb
140
+ - lib/sub_zero/cli/new.rb
141
+ - lib/sub_zero/cli/templates/ruby/client/client.tt
142
+ - lib/sub_zero/cli/templates/ruby/service/Gemfile
143
+ - lib/sub_zero/cli/templates/ruby/service/bin.tt
144
+ - lib/sub_zero/cli/templates/ruby/service/handler.tt
145
+ - lib/sub_zero/cli/templates/ruby/service/lib.tt
146
+ - lib/sub_zero/cli/templates/ruby/service/rvmrc.tt
147
+ - lib/sub_zero/cli/templates/ruby/service/serviceyml.tt
148
+ - lib/sub_zero/cli/templates/ruby/service/verbs.tt
149
+ - lib/sub_zero/cli/templates/ruby/service/version.tt
150
+ - lib/sub_zero/client.rb
151
+ - lib/sub_zero/client/configuration.rb
152
+ - lib/sub_zero/client/socket.rb
153
+ - lib/sub_zero/main.rb
154
+ - lib/sub_zero/main/common.rb
54
155
  - lib/sub_zero/version.rb
156
+ - spec/spec_helper.rb
55
157
  - sub_zero.gemspec
158
+ - thoughts.md
56
159
  homepage: ''
57
160
  licenses:
58
161
  - MIT
@@ -73,8 +176,9 @@ required_rubygems_version: !ruby/object:Gem::Requirement
73
176
  version: '0'
74
177
  requirements: []
75
178
  rubyforge_project:
76
- rubygems_version: 2.0.3
179
+ rubygems_version: 2.0.7
77
180
  signing_key:
78
181
  specification_version: 4
79
182
  summary: ZeroMQ GREAT SOA solution
80
- test_files: []
183
+ test_files:
184
+ - spec/spec_helper.rb
data/LICENSE.txt DELETED
@@ -1,22 +0,0 @@
1
- Copyright (c) 2013 Victor Rodrigues
2
-
3
- MIT License
4
-
5
- Permission is hereby granted, free of charge, to any person obtaining
6
- a copy of this software and associated documentation files (the
7
- "Software"), to deal in the Software without restriction, including
8
- without limitation the rights to use, copy, modify, merge, publish,
9
- distribute, sublicense, and/or sell copies of the Software, and to
10
- permit persons to whom the Software is furnished to do so, subject to
11
- the following conditions:
12
-
13
- The above copyright notice and this permission notice shall be
14
- included in all copies or substantial portions of the Software.
15
-
16
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
- EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
- MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
- NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
- LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
- OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
- WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.