miu 0.0.6 → 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
data/lib/miu/cli.rb CHANGED
@@ -43,21 +43,32 @@ module Miu
43
43
  end
44
44
 
45
45
  desc 'start', 'Start miu'
46
- option 'pub-host', :type => :string, :default => '127.0.0.1', :desc => 'pub host address'
47
- option 'pub-port', :type => :numeric, :default => Miu.default_pub_port, :desc => 'pub listen port'
48
- option 'sub-host', :type => :string, :default => '127.0.0.1', :desc => 'sub host address'
49
- option 'sub-port', :type => :numeric, :default => Miu.default_sub_port, :desc => 'sub listen port'
46
+ option 'pub-host', :type => :string, :default => '127.0.0.1', :desc => 'pub host'
47
+ option 'pub-port', :type => :numeric, :default => Miu.default_pub_port, :desc => 'pub port'
48
+ option 'sub-host', :type => :string, :default => '127.0.0.1', :desc => 'sub host'
49
+ option 'sub-port', :type => :numeric, :default => Miu.default_sub_port, :desc => 'sub port'
50
+ option 'verbose', :type => :boolean, :default => false, :desc => 'verbose output', :aliases => '-V'
50
51
  def start
51
- opts = options.dup
52
- opts.keys.each { |k| opts[k.gsub('-', '_')] = opts.delete(k) if k.is_a?(::String) }
53
- server = Miu::Server.new opts
52
+ server = Miu::Server.new Miu::Utility.optionalize_keys(options)
54
53
  server.run
55
54
  end
56
55
 
56
+ desc 'cat tag [body]', 'Nyan'
57
+ option 'host', :type => :string, :default => '127.0.0.1', :desc => 'miu sub host'
58
+ option 'port', :type => :numeric, :default => Miu.default_sub_port, :desc => 'miu sub port'
59
+ def cat(tag, body = nil)
60
+ require 'json'
61
+ publisher = Miu::Publisher.new :host => options[:host], :port => options[:port]
62
+ publisher.connect
63
+ body = JSON.load(body) rescue body
64
+ publisher.send tag, body
65
+ end
66
+
57
67
  desc 'supervise', 'Supervise miu and plugins'
58
- def supervise
68
+ def supervise(*args)
59
69
  require 'god'
60
- run "bundle exec god -c #{Miu.default_god_config}"
70
+ args.unshift "bundle exec god -c #{Miu.default_god_config}"
71
+ run args.join(' ')
61
72
  end
62
73
 
63
74
  desc 'god', 'Miu is a god'
data/lib/miu/command.rb CHANGED
@@ -20,6 +20,16 @@ module Miu
20
20
  def banner(task, namespace = nil, subcommand = nil)
21
21
  super task, namespace, subcommand || options.fetch(:subcommand, true)
22
22
  end
23
+
24
+ def add_miu_pub_options!
25
+ option 'miu-pub-host', :type => :string, :default => '127.0.0.1', :desc => 'miu pub host'
26
+ option 'miu-pub-port', :type => :numeric, :default => Miu.default_sub_port, :desc => 'miu pub port'
27
+ end
28
+
29
+ def add_miu_sub_options!
30
+ option 'miu-sub-host', :type => :string, :default => '127.0.0.1', :desc => 'miu sub host'
31
+ option 'miu-sub-port', :type => :numeric, :default => Miu.default_pub_port, :desc => 'miu sub port'
32
+ end
23
33
  end
24
34
 
25
35
  namespace name
data/lib/miu/logger.rb ADDED
@@ -0,0 +1,34 @@
1
+ require 'logger'
2
+
3
+ module Miu
4
+ module Logger
5
+ module_function
6
+
7
+ %w(debug info warn error fatal).each do |name|
8
+ instance_eval <<-EOS
9
+ def #{name}(msg)
10
+ Miu.logger.#{name}(msg) if Miu.logger
11
+ end
12
+ EOS
13
+ end
14
+
15
+ def exception(msg, ex)
16
+ error %(#{msg}\n#{format_exception(ex)})
17
+ end
18
+
19
+ def format_exception(ex)
20
+ %(#{ex.class}: #{ex.to_s}\n#{ex.backtrace.join("\n")})
21
+ end
22
+
23
+ def formatter(severity, time, progname, msg)
24
+ "[#{time}] #{msg}\n"
25
+ end
26
+ end
27
+
28
+ class << self
29
+ attr_accessor :logger
30
+ end
31
+ self.logger = ::Logger.new(STDERR)
32
+ self.logger.level = ::Logger::INFO
33
+ self.logger.formatter = Miu::Logger.method(:formatter)
34
+ end
@@ -0,0 +1,26 @@
1
+ require 'miu/resources/network'
2
+ require 'msgpack'
3
+
4
+ module Miu
5
+ module Messages
6
+ class Base
7
+ attr_accessor :network, :type, :content
8
+
9
+ def initialize(options = {})
10
+ @network = options[:network] || Resources::Network.new(options[:network] || {})
11
+ @type = options[:type]
12
+ @type = [@type, *Array(options[:sub_type])].compact.join('.')
13
+ @content = options[:content]
14
+ yield self if block_given?
15
+ end
16
+
17
+ def to_hash
18
+ {:network => @network.to_hash, :type => @type, :content => @content.to_hash}
19
+ end
20
+
21
+ def to_msgpack(*args)
22
+ to_hash.to_msgpack(*args)
23
+ end
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,14 @@
1
+ require 'miu/messages/base'
2
+ require 'miu/resources/text_content'
3
+
4
+ module Miu
5
+ module Messages
6
+ class Text < Base
7
+ def initialize(options = {})
8
+ options[:type] ||= 'text'
9
+ options[:content] ||= Resources::TextContent.new(options[:content] || {})
10
+ super
11
+ end
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,6 @@
1
+ module Miu
2
+ module Messages
3
+ autoload :Base, 'miu/messages/base'
4
+ autoload :Text, 'miu/messages/text'
5
+ end
6
+ end
data/lib/miu/packet.rb ADDED
@@ -0,0 +1,39 @@
1
+ require 'miu'
2
+ require 'securerandom'
3
+ require 'msgpack'
4
+
5
+ module Miu
6
+ class Packet
7
+ attr_accessor :tag, :body, :id, :time
8
+
9
+ def initialize(tag, body, options = {})
10
+ @tag = tag
11
+ @body = body
12
+ @id = options[:id] || SecureRandom.uuid
13
+ @time = options[:time] || Time.now.to_i
14
+ end
15
+
16
+ def dump
17
+ data = {
18
+ 'body' => @body,
19
+ 'id' => @id,
20
+ 'time' => @time,
21
+ }
22
+ [@tag, data.to_msgpack]
23
+ end
24
+
25
+ def self.load(parts)
26
+ tag = parts.shift
27
+ data = MessagePack.unpack(parts.shift)
28
+ body = data.delete('body')
29
+ new tag, body, Miu::Utility.symbolized_keys(data)
30
+ end
31
+
32
+ def inspect
33
+ inspection = [:tag, :body, :id, :time].map do |name|
34
+ "#{name}: #{__send__(name).inspect}"
35
+ end.join(', ')
36
+ "#<#{self.class} #{inspection}>"
37
+ end
38
+ end
39
+ end
data/lib/miu/plugin.rb CHANGED
@@ -17,7 +17,7 @@ module Miu
17
17
  attr_accessor :called_from
18
18
 
19
19
  def register(*args, &block)
20
- options = args.last.is_a?(::Hash) ? args.pop : {}
20
+ options = Miu::Utility.extract_options!(args)
21
21
  name = args.shift
22
22
  plugin = args.shift || self
23
23
  Miu.register name, plugin, options, &block
data/lib/miu/publisher.rb CHANGED
@@ -1,7 +1,6 @@
1
1
  require 'miu'
2
2
  require 'miu/socket'
3
- require 'miu/message'
4
- require 'msgpack'
3
+ require 'miu/packet'
5
4
 
6
5
  module Miu
7
6
  class Publisher < Socket
@@ -14,8 +13,9 @@ module Miu
14
13
 
15
14
  # tag, time = nil, body
16
15
  def send(*args)
17
- message = Message.new *args
18
- @socket.send_strings message.dump
16
+ packet = Packet.new *args
17
+ @socket.send_strings packet.dump
18
+ packet.id
19
19
  end
20
20
 
21
21
  private
@@ -0,0 +1,15 @@
1
+ require 'msgpack'
2
+
3
+ module Miu
4
+ module Resources
5
+ class Base
6
+ def to_hash
7
+ {}
8
+ end
9
+
10
+ def to_msgpack
11
+ to_hash.to_msgpack
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,17 @@
1
+ require 'miu/resources/base'
2
+
3
+ module Miu
4
+ module Resources
5
+ class Content < Base
6
+ attr_accessor :meta
7
+
8
+ def initialize(options = {})
9
+ @meta = options[:meta] || {}
10
+ end
11
+
12
+ def to_hash
13
+ super.merge({:meta => @meta})
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,17 @@
1
+ require 'miu/resources/base'
2
+
3
+ module Miu
4
+ module Resources
5
+ class Network < Base
6
+ attr_accessor :name
7
+
8
+ def initialize(options = {})
9
+ @name = options[:name]
10
+ end
11
+
12
+ def to_hash
13
+ super.merge({:name => @name})
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,17 @@
1
+ require 'miu/resources/base'
2
+
3
+ module Miu
4
+ module Resources
5
+ class Room < Base
6
+ attr_accessor :name
7
+
8
+ def initialize(options = {})
9
+ @name = options[:name]
10
+ end
11
+
12
+ def to_hash
13
+ super.merge({:name => @name})
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,26 @@
1
+ require 'miu/resources/content'
2
+ require 'miu/resources/room'
3
+ require 'miu/resources/user'
4
+
5
+ module Miu
6
+ module Resources
7
+ class TextContent < Content
8
+ attr_accessor :room, :user, :text
9
+
10
+ def initialize(options = {})
11
+ @room = options[:room] || Room.new(options[:room] || {})
12
+ @user = options[:user] || User.new(options[:user] || {})
13
+ @text = options[:text]
14
+ super options
15
+ end
16
+
17
+ def to_hash
18
+ super.merge({
19
+ :room => @room.to_hash,
20
+ :user => @user.to_hash,
21
+ :text => @text
22
+ })
23
+ end
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,17 @@
1
+ require 'miu/resources/base'
2
+
3
+ module Miu
4
+ module Resources
5
+ class User < Base
6
+ attr_accessor :name
7
+
8
+ def initialize(options = {})
9
+ @name = options[:name]
10
+ end
11
+
12
+ def to_hash
13
+ super.merge({:name => @name})
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,10 @@
1
+ module Miu
2
+ module Resources
3
+ autoload :Base, 'miu/resources/base'
4
+ autoload :Network, 'miu/resources/network'
5
+ autoload :Room, 'miu/resources/room'
6
+ autoload :User, 'miu/resources/user'
7
+ autoload :Content, 'miu/resources/content'
8
+ autoload :TextContent, 'miu/resources/text_content'
9
+ end
10
+ end
data/lib/miu/server.rb CHANGED
@@ -1,55 +1,51 @@
1
1
  require 'miu'
2
- require 'miu/publisher'
3
- require 'miu/subscriber'
4
2
 
5
3
  module Miu
6
4
  class Server
7
5
  attr_reader :options
8
- attr_reader :context, :publisher, :subscriber
6
+ attr_reader :publisher, :subscriber
9
7
 
10
8
  def initialize(options = {})
11
9
  @options = options
10
+ if options[:verbose] && Miu.logger
11
+ Miu.logger.level = ::Logger::DEBUG
12
+ end
12
13
  end
13
14
 
14
15
  def run
15
16
  pub_address = "#{@options[:pub_host]}:#{@options[:pub_port]}"
16
17
  sub_address = "#{@options[:sub_host]}:#{@options[:sub_port]}"
17
18
 
18
- @context = ZMQ::Context.new
19
- @publisher = Publisher.new({
20
- :context => @context,
21
- :host => @options[:pub_host],
22
- :port => @options[:pub_port]
23
- })
24
- @subscriber = Subscriber.new({
25
- :context => @context,
26
- :host => @options[:sub_host],
27
- :port => @options[:sub_port]
28
- })
19
+ @publisher = Publisher.new({:host => @options[:pub_host], :port => @options[:pub_port]})
20
+ @subscriber = Subscriber.new({:host => @options[:sub_host], :port => @options[:sub_port]})
29
21
 
30
22
  @publisher.bind
31
23
  @subscriber.bind
32
24
 
33
- puts "Starting miu"
34
- puts "pub: #{@publisher.host}:#{@publisher.port}"
35
- puts "sub: #{@subscriber.host}:#{@subscriber.port}"
25
+ Logger.info "Starting miu"
26
+ Logger.info "pub: #{@publisher.host}:#{@publisher.port}"
27
+ Logger.info "sub: #{@subscriber.host}:#{@subscriber.port}"
36
28
 
37
- trap(:INT) do
38
- puts "Quit"
39
- close
40
- exit
29
+ [:INT, :TERM].each do |sig|
30
+ trap(sig) do
31
+ Logger.info "Quit"
32
+ close
33
+ exit
34
+ end
41
35
  end
42
36
 
43
37
  loop do
44
- @subscriber.forward @publisher
38
+ parts = @subscriber.forward @publisher
39
+ if @options[:verbose]
40
+ packet = Packet.load parts
41
+ Logger.debug packet.inspect
42
+ end
45
43
  end
46
44
  end
47
45
 
48
46
  def close
49
47
  @subscriber.close
50
48
  @publisher.close
51
- @context.terminate
52
49
  end
53
- alias_method :shutdown, :close
54
50
  end
55
51
  end
data/lib/miu/socket.rb CHANGED
@@ -9,15 +9,7 @@ module Miu
9
9
  def initialize(socket_type, options = {})
10
10
  @host = options[:host] || '127.0.0.1'
11
11
  @port = options[:port]
12
-
13
- if options[:context]
14
- @context = options[:context]
15
- @terminate_context = false
16
- else
17
- @context = ZMQ::Context.new(options[:io_threads] || 1)
18
- @terminate_context = true
19
- end
20
-
12
+ @context = Miu.context
21
13
  @socket = @context.socket socket_type
22
14
  end
23
15
 
@@ -33,19 +25,20 @@ module Miu
33
25
  self
34
26
  end
35
27
 
36
- def forward(forwarder)
28
+ def forward(to)
29
+ parts = []
37
30
  loop do
38
31
  message = ZMQ::Message.new
39
32
  @socket.recvmsg message
33
+ parts << message.copy_out_string
40
34
  more = @socket.more_parts?
41
- forwarder.socket.sendmsg message, (more ? ZMQ::SNDMORE : 0)
42
- break unless more
35
+ to.socket.sendmsg message, (more ? ZMQ::SNDMORE : 0)
36
+ return parts unless more
43
37
  end
44
38
  end
45
39
 
46
40
  def close
47
41
  @socket.close
48
- @context.terminate if @terminate_context
49
42
  end
50
43
 
51
44
  protected
@@ -1,5 +1,6 @@
1
1
  require 'miu'
2
2
  require 'miu/socket'
3
+ require 'miu/packet'
3
4
 
4
5
  module Miu
5
6
  class Subscriber < Socket
@@ -34,14 +35,14 @@ module Miu
34
35
  def recv
35
36
  parts = []
36
37
  @socket.recv_strings parts
37
- Message.load parts
38
+ Packet.load parts
38
39
  end
39
40
 
40
41
  def each
41
42
  if block_given?
42
43
  loop do
43
- message = recv rescue nil
44
- yield message if message
44
+ packet = recv rescue nil
45
+ yield packet if packet
45
46
  end
46
47
  end
47
48
  end
@@ -49,11 +50,7 @@ module Miu
49
50
  private
50
51
 
51
52
  def socket_type
52
- if ZMQ::LibZMQ.version3?
53
- ZMQ::XSUB
54
- else
55
- ZMQ::SUB
56
- end
53
+ ZMQ::SUB
57
54
  end
58
55
  end
59
56
  end
@@ -0,0 +1,47 @@
1
+ module Miu
2
+ module Utility
3
+ module_function
4
+
5
+ def extract_options!(args)
6
+ args.last.is_a?(::Hash) ? args.pop : {}
7
+ end
8
+
9
+ def modified_keys(hash, recursive = false, &block)
10
+ hash = hash.dup
11
+ if block
12
+ hash.keys.each do |key|
13
+ value = hash.delete(key)
14
+ if recursive
15
+ case value
16
+ when ::Hash
17
+ value = modified_keys(value, recursive, &block)
18
+ when ::Array
19
+ value = value.map { |v| v.is_a?(::Hash) ? modified_keys(v, recursive, &block) : v }
20
+ end
21
+ end
22
+ key = block.call key
23
+ hash[key] = value
24
+ end
25
+ end
26
+ hash
27
+ end
28
+
29
+ def symbolized_keys(hash, recursive = false)
30
+ modified_keys(hash, recursive) do |key|
31
+ key.to_sym rescue key
32
+ end
33
+ end
34
+
35
+ def underscorize_keys(hash, recursive = false)
36
+ modified_keys(hash, recursive) do |key|
37
+ key.gsub('-', '_') rescue key
38
+ end
39
+ end
40
+
41
+ def optionalize_keys(hash, recursive = false)
42
+ modified_keys(hash, recursive) do |key|
43
+ key.to_s.gsub('-', '_').to_sym rescue key
44
+ end
45
+ end
46
+ end
47
+ end
data/lib/miu/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Miu
2
- VERSION = '0.0.6'
2
+ VERSION = '0.1.0'
3
3
  end
data/lib/miu.rb CHANGED
@@ -1,13 +1,19 @@
1
1
  require 'miu/version'
2
+ require 'miu/logger'
2
3
 
3
4
  module Miu
4
5
  autoload :CLI, 'miu/cli'
5
- autoload :Command, 'miu/command'
6
+ autoload :Utility, 'miu/utility'
6
7
  autoload :Server, 'miu/server'
7
- autoload :Message, 'miu/message'
8
+ autoload :Packet, 'miu/packet'
8
9
  autoload :Socket, 'miu/socket'
9
10
  autoload :Publisher, 'miu/publisher'
10
11
  autoload :Subscriber, 'miu/subscriber'
12
+ autoload :Command, 'miu/command'
13
+ autoload :Plugin, 'miu/plugin'
14
+ autoload :Plugins, 'miu/plugins'
15
+ autoload :Resources, 'miu/resources'
16
+ autoload :Messages, 'miu/messages'
11
17
 
12
18
  class << self
13
19
  def root
@@ -45,6 +51,11 @@ module Miu
45
51
  Pathname.new File.realpath(path)
46
52
  end
47
53
 
54
+ def context
55
+ require 'ffi-rzmq'
56
+ @context ||= ZMQ::Context.new
57
+ end
58
+
48
59
  def plugins
49
60
  @plugins ||= {}
50
61
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: miu
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.6
4
+ version: 0.1.0
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2013-03-14 00:00:00.000000000 Z
12
+ date: 2013-03-18 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: bundler
@@ -108,14 +108,26 @@ files:
108
108
  - lib/miu.rb
109
109
  - lib/miu/cli.rb
110
110
  - lib/miu/command.rb
111
- - lib/miu/message.rb
111
+ - lib/miu/logger.rb
112
+ - lib/miu/messages.rb
113
+ - lib/miu/messages/base.rb
114
+ - lib/miu/messages/text.rb
115
+ - lib/miu/packet.rb
112
116
  - lib/miu/plugin.rb
113
117
  - lib/miu/plugins.rb
114
118
  - lib/miu/plugins/null.rb
115
119
  - lib/miu/publisher.rb
120
+ - lib/miu/resources.rb
121
+ - lib/miu/resources/base.rb
122
+ - lib/miu/resources/content.rb
123
+ - lib/miu/resources/network.rb
124
+ - lib/miu/resources/room.rb
125
+ - lib/miu/resources/text_content.rb
126
+ - lib/miu/resources/user.rb
116
127
  - lib/miu/server.rb
117
128
  - lib/miu/socket.rb
118
129
  - lib/miu/subscriber.rb
130
+ - lib/miu/utility.rb
119
131
  - lib/miu/version.rb
120
132
  - lib/templates/Gemfile
121
133
  - lib/templates/config/miu.god
@@ -134,7 +146,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
134
146
  version: '0'
135
147
  segments:
136
148
  - 0
137
- hash: -3968051150084221078
149
+ hash: 1420943406684194913
138
150
  required_rubygems_version: !ruby/object:Gem::Requirement
139
151
  none: false
140
152
  requirements:
@@ -143,7 +155,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
143
155
  version: '0'
144
156
  segments:
145
157
  - 0
146
- hash: -3968051150084221078
158
+ hash: 1420943406684194913
147
159
  requirements: []
148
160
  rubyforge_project:
149
161
  rubygems_version: 1.8.24
data/lib/miu/message.rb DELETED
@@ -1,24 +0,0 @@
1
- require 'msgpack'
2
-
3
- module Miu
4
- class Message
5
- attr_accessor :tag, :time, :body
6
-
7
- def initialize(*args)
8
- @tag = args.shift
9
- @body = args.pop
10
- @time = args.shift || Time.now.to_i
11
- end
12
-
13
- def dump
14
- [@tag, @time, @body.to_msgpack].map(&:to_s)
15
- end
16
-
17
- def self.load(parts)
18
- tag = parts.shift
19
- time = parts.shift
20
- body = MessagePack.unpack(parts.shift)
21
- new tag, time, body
22
- end
23
- end
24
- end