miu 0.0.6 → 0.1.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.
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