ruby_skynet 0.4.0 → 0.5.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.
- checksums.yaml +4 -4
- data/README.md +13 -18
- data/Rakefile +1 -0
- data/lib/rails/generators/ruby_skynet/config/config_generator.rb +20 -0
- data/lib/rails/generators/ruby_skynet/config/templates/ruby_skynet.yml +86 -0
- data/lib/ruby_skynet/base.rb +65 -0
- data/lib/ruby_skynet/client.rb +7 -7
- data/lib/ruby_skynet/connection.rb +3 -3
- data/lib/ruby_skynet/doozer/client.rb +3 -3
- data/lib/ruby_skynet/exceptions.rb +1 -0
- data/lib/ruby_skynet/railtie.rb +30 -0
- data/lib/ruby_skynet/railties/ruby_skynet.rake +28 -0
- data/lib/ruby_skynet/registry.rb +20 -20
- data/lib/ruby_skynet/ruby_skynet.rb +69 -0
- data/lib/ruby_skynet/server.rb +67 -41
- data/lib/ruby_skynet/service.rb +3 -31
- data/lib/ruby_skynet/version.rb +1 -1
- data/lib/ruby_skynet.rb +6 -0
- data/test/base_test.rb +89 -0
- data/test/client_test.rb +2 -1
- data/test/registry_test.rb +1 -1
- data/test/service_test.rb +2 -1
- metadata +23 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: f15ead62305cae332e890c1ad63a3f11e9085ffe
|
4
|
+
data.tar.gz: aa3243ae8229d4cd7a5f82ac673fd3e7cc700b17
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 363ed46b3ee9182fa572fb00724031f01d077600a304ac3d38ccbbb023b3c33ff25872c72b9eeb7c130e4784ce9c6c2ff807a9c522d391ef31a8de9564fdd7e3
|
7
|
+
data.tar.gz: 4eeb6d97725af7fb087e40afbc8b8d459c8889b84c1d4b1756885eedc3322adbf22a5afd89d44c97ad456e7441e0dd09fb90007c1a28204835638ab1e9404faf
|
data/README.md
CHANGED
@@ -24,9 +24,6 @@ For details on installing and running the GoLang Tutorial Service: https://githu
|
|
24
24
|
require 'rubygems'
|
25
25
|
require 'ruby_skynet'
|
26
26
|
|
27
|
-
RubySkynet::Server.port = 2000
|
28
|
-
RubySkynet::Server.hostname = '127.0.0.1'
|
29
|
-
|
30
27
|
# Just echo back any parameters received when the echo method is called
|
31
28
|
class EchoService
|
32
29
|
include RubySkynet::Service
|
@@ -48,8 +45,12 @@ Client to call the above Service
|
|
48
45
|
require 'rubygems'
|
49
46
|
require 'ruby_skynet'
|
50
47
|
|
51
|
-
|
52
|
-
|
48
|
+
class EchoService
|
49
|
+
include RubySkynet::Base
|
50
|
+
end
|
51
|
+
|
52
|
+
client = EchoService.new
|
53
|
+
p client.echo(:hello => 'world')
|
53
54
|
```
|
54
55
|
|
55
56
|
### Logging
|
@@ -64,8 +65,12 @@ require 'ruby_skynet'
|
|
64
65
|
SemanticLogger::Logger.default_level = :trace
|
65
66
|
SemanticLogger::Logger.appenders << SemanticLogger::Appender::File.new('skynet.log')
|
66
67
|
|
67
|
-
|
68
|
-
|
68
|
+
class EchoService
|
69
|
+
include RubySkynet::Base
|
70
|
+
end
|
71
|
+
|
72
|
+
client = EchoService.new
|
73
|
+
p client.echo(:hello => 'world')
|
69
74
|
```
|
70
75
|
|
71
76
|
### Architecture
|
@@ -83,20 +88,10 @@ project for marshaling data for communicating with doozer
|
|
83
88
|
- [ruby_protobuf](https://github.com/macks/ruby-protobuf)
|
84
89
|
- [multi_json](https://github.com/intridea/multi_json)
|
85
90
|
|
86
|
-
The server to host services in Ruby also requires:
|
87
|
-
- [Celluloid::io](https://github.com/celluloid/celluloid-io)
|
88
|
-
|
89
91
|
### Install
|
90
92
|
|
91
93
|
gem install ruby_skynet
|
92
94
|
|
93
|
-
### Future
|
94
|
-
|
95
|
-
* Immediately drop connections to a service on a host when that instance
|
96
|
-
shuts down or stops. ( Doozer::Wait )
|
97
|
-
* More intelligent selection of available Skynet services. For example
|
98
|
-
nearest, or looking at load etc.
|
99
|
-
|
100
95
|
Development
|
101
96
|
-----------
|
102
97
|
|
@@ -139,7 +134,7 @@ Reid Morrison :: reidmo@gmail.com :: @reidmorrison
|
|
139
134
|
License
|
140
135
|
-------
|
141
136
|
|
142
|
-
Copyright 2012 Clarity Services, Inc.
|
137
|
+
Copyright 2012,2013 Clarity Services, Inc.
|
143
138
|
|
144
139
|
Licensed under the Apache License, Version 2.0 (the "License");
|
145
140
|
you may not use this file except in compliance with the License.
|
data/Rakefile
CHANGED
@@ -0,0 +1,20 @@
|
|
1
|
+
module RubySkynet
|
2
|
+
module Generators
|
3
|
+
class ConfigGenerator < Rails::Generators::Base
|
4
|
+
desc "Creates a Ruby Skynet configuration file at config/ruby_skynet.yml"
|
5
|
+
|
6
|
+
def self.source_root
|
7
|
+
@_ruby_skynet_source_root ||= File.expand_path("../templates", __FILE__)
|
8
|
+
end
|
9
|
+
|
10
|
+
def app_name
|
11
|
+
Rails::Application.subclasses.first.parent.to_s.underscore
|
12
|
+
end
|
13
|
+
|
14
|
+
def create_config_file
|
15
|
+
template 'ruby_skynet.yml', File.join('config', "ruby_skynet.yml")
|
16
|
+
end
|
17
|
+
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,86 @@
|
|
1
|
+
# Ruby Skynet Client & Server Configuration Parameters
|
2
|
+
# :region [String]
|
3
|
+
# Region name to use for service lookup
|
4
|
+
# Default: Rails.env
|
5
|
+
#
|
6
|
+
# :services_path [String]
|
7
|
+
# Path within to look for service implementations that will be loaded
|
8
|
+
# when RubySkynet::Server.load_services is called
|
9
|
+
#
|
10
|
+
# :server_port [Integer]
|
11
|
+
# Optional: Only required when running a server locally
|
12
|
+
# Starting port for server to listen on
|
13
|
+
# If this port is in use the next available port will be used
|
14
|
+
# upto 999 above the server_port value
|
15
|
+
#
|
16
|
+
# :local_ip_address [String]
|
17
|
+
# Optional: The ip address at which this server instance can be reached
|
18
|
+
# by remote Skynet clients
|
19
|
+
# Note: Must be an IP address, not the hostname
|
20
|
+
#
|
21
|
+
# Doozer Configuration Parameters
|
22
|
+
# :doozer
|
23
|
+
# :servers [Array of String]
|
24
|
+
# Array of URL's of doozer servers to connect to with port numbers
|
25
|
+
# ['server1:2000', 'server2:2000']
|
26
|
+
#
|
27
|
+
# The second server will only be attempted once the first server
|
28
|
+
# cannot be connected to or has timed out on connect
|
29
|
+
# A read failure or timeout will not result in switching to the second
|
30
|
+
# server, only a connection failure or during an automatic reconnect
|
31
|
+
#
|
32
|
+
# :read_timeout [Float]
|
33
|
+
# Time in seconds to timeout on read
|
34
|
+
# Can be overridden by supplying a timeout in the read call
|
35
|
+
#
|
36
|
+
# :connect_timeout [Float]
|
37
|
+
# Time in seconds to timeout when trying to connect to the server
|
38
|
+
#
|
39
|
+
# :connect_retry_count [Fixnum]
|
40
|
+
# Number of times to retry connecting when a connection fails
|
41
|
+
#
|
42
|
+
# :connect_retry_interval [Float]
|
43
|
+
# Number of seconds between connection retry attempts after the first failed attempt
|
44
|
+
#
|
45
|
+
# :server_selector [Symbol]
|
46
|
+
# When multiple doozer servers are supplied using :servers, this option will
|
47
|
+
# determine which server is selected from the list
|
48
|
+
# :ordered
|
49
|
+
# Select a server in the order supplied in the array, with the first
|
50
|
+
# having the highest priority. The second server will only be connected
|
51
|
+
# to if the first server is unreachable
|
52
|
+
# :random
|
53
|
+
# Randomly select a server from the list every time a connection
|
54
|
+
# is established, including during automatic connection recovery.
|
55
|
+
# Default: :ordered
|
56
|
+
defaults: &defaults
|
57
|
+
:services_path: app/services
|
58
|
+
:server_port: 2000
|
59
|
+
:doozer:
|
60
|
+
:servers:
|
61
|
+
- 127.0.0.1:8046
|
62
|
+
:read_timeout: 5
|
63
|
+
:connect_timeout: 3
|
64
|
+
:connect_retry_count: 10
|
65
|
+
:connect_retry_interval: 0.5
|
66
|
+
:server_selector: :random
|
67
|
+
|
68
|
+
development:
|
69
|
+
<<: *defaults
|
70
|
+
:region: Development
|
71
|
+
|
72
|
+
test:
|
73
|
+
<<: *defaults
|
74
|
+
:region: Test
|
75
|
+
|
76
|
+
release:
|
77
|
+
<<: *defaults
|
78
|
+
:region: Release
|
79
|
+
|
80
|
+
hotfix:
|
81
|
+
<<: *defaults
|
82
|
+
:region: Hotfix
|
83
|
+
|
84
|
+
production:
|
85
|
+
<<: *defaults
|
86
|
+
:region: Production
|
@@ -0,0 +1,65 @@
|
|
1
|
+
require 'semantic_logger'
|
2
|
+
|
3
|
+
# Base class for RubySkynet Clients and Services
|
4
|
+
module RubySkynet
|
5
|
+
module Base
|
6
|
+
def self.included(base)
|
7
|
+
base.extend ClassMethods
|
8
|
+
base.class_eval do
|
9
|
+
include SemanticLogger::Loggable
|
10
|
+
include InstanceMethods
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
module InstanceMethods
|
15
|
+
# Implement methods that call the remote Service
|
16
|
+
def method_missing(method, *args, &block)
|
17
|
+
result = ruby_skynet_client.call(method, *args)
|
18
|
+
# Define the method if the call was successful and no-one else already
|
19
|
+
# created the method
|
20
|
+
if result[:exception].nil? && !self.class.method_defined?(method)
|
21
|
+
self.class.send(:define_method, method) {|*args| ruby_skynet_client.call(method, *args)}
|
22
|
+
end
|
23
|
+
result
|
24
|
+
end
|
25
|
+
|
26
|
+
def ruby_skynet_client
|
27
|
+
@ruby_skynet_client ||= RubySkynet::Client.new(self.class.skynet_name, self.class.skynet_version || '*', self.class.skynet_region)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
module ClassMethods
|
32
|
+
# Name of this service to Register with Skynet
|
33
|
+
# Default: class name
|
34
|
+
def skynet_name
|
35
|
+
@skynet_name ||= name.gsub('::', '.')
|
36
|
+
end
|
37
|
+
|
38
|
+
def skynet_name=(skynet_name)
|
39
|
+
@skynet_name = skynet_name
|
40
|
+
end
|
41
|
+
|
42
|
+
# Version of this service to register with Skynet
|
43
|
+
# Default: nil
|
44
|
+
def skynet_version
|
45
|
+
@skynet_version ||= nil
|
46
|
+
end
|
47
|
+
|
48
|
+
def skynet_version=(skynet_version)
|
49
|
+
@skynet_version = skynet_version
|
50
|
+
end
|
51
|
+
|
52
|
+
# Region within which this service is defined
|
53
|
+
# Default: RubySkynet.region
|
54
|
+
def skynet_region
|
55
|
+
@skynet_region || ::RubySkynet.region
|
56
|
+
end
|
57
|
+
|
58
|
+
def skynet_region=(skynet_region)
|
59
|
+
@skynet_region = skynet_region
|
60
|
+
end
|
61
|
+
|
62
|
+
end
|
63
|
+
|
64
|
+
end
|
65
|
+
end
|
data/lib/ruby_skynet/client.rb
CHANGED
@@ -14,7 +14,7 @@ module RubySkynet
|
|
14
14
|
# concurrently from multiple threads at the same time
|
15
15
|
#
|
16
16
|
# Parameters:
|
17
|
-
# :
|
17
|
+
# :skynet_name
|
18
18
|
# Name of the service to look for and connect to on Skynet
|
19
19
|
#
|
20
20
|
# :version
|
@@ -33,9 +33,9 @@ module RubySkynet
|
|
33
33
|
#
|
34
34
|
# tutorial_service = RubySkynet::Client.new('TutorialService')
|
35
35
|
# p tutorial_service.call('Add', :value => 5)
|
36
|
-
def initialize(
|
37
|
-
@
|
38
|
-
@logger = SemanticLogger::Logger.new("#{self.class.name}: #{
|
36
|
+
def initialize(skynet_name, version='*', region='Development')
|
37
|
+
@skynet_name = skynet_name
|
38
|
+
@logger = SemanticLogger::Logger.new("#{self.class.name}: #{skynet_name}/#{version}/#{region}")
|
39
39
|
@version = version
|
40
40
|
@region = region
|
41
41
|
end
|
@@ -57,12 +57,12 @@ module RubySkynet
|
|
57
57
|
# https://github.com/skynetservices/skynet/blob/master/protocol.md
|
58
58
|
request_id = BSON::ObjectId.new.to_s
|
59
59
|
@logger.tagged request_id do
|
60
|
-
@logger.benchmark_info "Called Skynet Service: #{@
|
60
|
+
@logger.benchmark_info "Called Skynet Service: #{@skynet_name}.#{method_name}" do
|
61
61
|
retries = 0
|
62
62
|
# If it cannot connect to a server, try a different server
|
63
63
|
begin
|
64
|
-
Connection.with_connection(Registry.server_for(@
|
65
|
-
connection.rpc_call(request_id, @
|
64
|
+
Connection.with_connection(Registry.server_for(@skynet_name, @version, @region), connection_params) do |connection|
|
65
|
+
connection.rpc_call(request_id, @skynet_name, method_name, parameters)
|
66
66
|
end
|
67
67
|
rescue ResilientSocket::ConnectionFailure => exc
|
68
68
|
if (retries < 3) && exc.cause.is_a?(Errno::ECONNREFUSED)
|
@@ -108,7 +108,7 @@ module RubySkynet
|
|
108
108
|
# Performs a synchronous call to a Skynet server
|
109
109
|
#
|
110
110
|
# Parameters:
|
111
|
-
#
|
111
|
+
# skynet_name [String|Symbol]:
|
112
112
|
# Name of the method to pass in the request
|
113
113
|
# method_name [String|Symbol]:
|
114
114
|
# Name of the method to pass in the request
|
@@ -122,14 +122,14 @@ module RubySkynet
|
|
122
122
|
#
|
123
123
|
# Raises RubySkynet::ProtocolError
|
124
124
|
# Raises RubySkynet::SkynetException
|
125
|
-
def rpc_call(request_id,
|
125
|
+
def rpc_call(request_id, skynet_name, method_name, parameters, idempotent=false)
|
126
126
|
retry_count = 0
|
127
127
|
header = nil
|
128
128
|
response = nil
|
129
129
|
|
130
130
|
socket.retry_on_connection_failure do |socket|
|
131
131
|
header = {
|
132
|
-
'servicemethod' => "#{
|
132
|
+
'servicemethod' => "#{skynet_name}.Forward",
|
133
133
|
'seq' => socket.user_data[:seq]
|
134
134
|
}
|
135
135
|
|
@@ -8,10 +8,10 @@ module RubySkynet
|
|
8
8
|
module Doozer
|
9
9
|
class Client
|
10
10
|
|
11
|
+
include SemanticLogger::Loggable
|
12
|
+
|
11
13
|
# Create a resilient client connection to a Doozer server
|
12
14
|
def initialize(params={})
|
13
|
-
@logger = SemanticLogger::Logger.new(self.class)
|
14
|
-
|
15
15
|
# User configurable options
|
16
16
|
params[:read_timeout] ||= 5
|
17
17
|
params[:connect_timeout] ||= 3
|
@@ -25,7 +25,7 @@ module RubySkynet
|
|
25
25
|
# Disable buffering the send since it is a RPC call
|
26
26
|
params[:buffered] = false
|
27
27
|
|
28
|
-
|
28
|
+
logger.trace "Socket Connection parameters", params.dup
|
29
29
|
|
30
30
|
# For each new connection
|
31
31
|
params[:on_connect] = Proc.new do |socket|
|
@@ -3,6 +3,7 @@ module RubySkynet
|
|
3
3
|
class ProtocolError < Exception; end
|
4
4
|
class ServiceException < Exception; end
|
5
5
|
class InvalidServiceException < ServiceException; end
|
6
|
+
class InvalidConfigurationException < ServiceException; end
|
6
7
|
class SkynetException < Exception; end
|
7
8
|
class ServiceUnavailable < SkynetException; end
|
8
9
|
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
module RubySkynet #:nodoc:
|
2
|
+
class Railtie < Rails::Railtie #:nodoc:
|
3
|
+
|
4
|
+
# Exposes RubySkynet configuration to the Rails application configuration.
|
5
|
+
#
|
6
|
+
# @example Set up configuration in the Rails app.
|
7
|
+
# module MyApplication
|
8
|
+
# class Application < Rails::Application
|
9
|
+
# config.ruby_skynet.region = "Development"
|
10
|
+
# end
|
11
|
+
# end
|
12
|
+
config.ruby_skynet = ::RubySkynet
|
13
|
+
|
14
|
+
rake_tasks do
|
15
|
+
load "ruby_skynet/railties/ruby_skynet.rake"
|
16
|
+
end
|
17
|
+
|
18
|
+
# Load RubySkynet Configuration
|
19
|
+
config.before_configuration do
|
20
|
+
config_file = Rails.root.join("config", "ruby_skynet.yml")
|
21
|
+
if config_file.file?
|
22
|
+
::RubySkynet.configure!(config_file, Rails.env)
|
23
|
+
else
|
24
|
+
puts "\nRuby Skynet config not found."
|
25
|
+
puts "To generate one for the first time: rails generate ruby_skynet:config\n\n"
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
namespace :ruby_skynet do
|
2
|
+
|
3
|
+
desc "Start the Ruby Skynet Server.\n Rails Example: rake ruby_skynet:server\n Without Rails: SKYNET_ENV=production SKYNET_CONFIG=config/ruby_skynet rake ruby_skynet:server"
|
4
|
+
task :server => :environment do
|
5
|
+
# Configuration is automatically loaded when running under Rails
|
6
|
+
# so skip it here under Rails
|
7
|
+
unless defined?(Rails)
|
8
|
+
# Environment to use in config file
|
9
|
+
environment = ENV['SKYNET_ENV']
|
10
|
+
|
11
|
+
# Environment to use in config file
|
12
|
+
cfg_file = ENV['SKYNET_CONFIG']
|
13
|
+
|
14
|
+
# Load the configuration file
|
15
|
+
RubySkynet.configure!(cfg_file, environment)
|
16
|
+
end
|
17
|
+
|
18
|
+
# Connect to doozer
|
19
|
+
RubySkynet::Registry.service_registry
|
20
|
+
|
21
|
+
RubySkynet::Server.load_services
|
22
|
+
|
23
|
+
# Start the server
|
24
|
+
RubySkynet::Server.start
|
25
|
+
RubySkynet::Server.wait_until_server_stops
|
26
|
+
end
|
27
|
+
|
28
|
+
end
|
data/lib/ruby_skynet/registry.rb
CHANGED
@@ -16,10 +16,12 @@ module RubySkynet
|
|
16
16
|
include SyncAttr
|
17
17
|
|
18
18
|
# Service Registry has the following format
|
19
|
-
# Key: [String] '
|
19
|
+
# Key: [String] 'name/version/region'
|
20
20
|
# Value: [Array<String>] 'host:port', 'host:port'
|
21
21
|
sync_cattr_reader :service_registry do
|
22
|
-
|
22
|
+
logger.benchmark_info "Connected to Doozer" do
|
23
|
+
start
|
24
|
+
end
|
23
25
|
end
|
24
26
|
|
25
27
|
@@on_server_removed_callbacks = ThreadSafe::Hash.new
|
@@ -91,12 +93,12 @@ module RubySkynet
|
|
91
93
|
end
|
92
94
|
|
93
95
|
# Return a server that implements the specified service
|
94
|
-
def self.server_for(
|
95
|
-
if servers = servers_for(
|
96
|
+
def self.server_for(name, version='*', region='Development')
|
97
|
+
if servers = servers_for(name, version, region)
|
96
98
|
# Randomly select one of the servers offering the service
|
97
99
|
servers[rand(servers.size)]
|
98
100
|
else
|
99
|
-
msg = "No servers available for service: #{
|
101
|
+
msg = "No servers available for service: #{name} with version: #{version} in region: #{region}"
|
100
102
|
logger.warn msg
|
101
103
|
raise ServiceUnavailable.new(msg)
|
102
104
|
end
|
@@ -105,17 +107,17 @@ module RubySkynet
|
|
105
107
|
# Returns [Array] of the hostname and port pair [String] that implements a particular service
|
106
108
|
# Performs a doozer lookup to find the servers
|
107
109
|
#
|
108
|
-
#
|
110
|
+
# name:
|
109
111
|
# Name of the service to lookup
|
110
112
|
# version:
|
111
113
|
# Version of service to locate
|
112
114
|
# Default: All versions
|
113
115
|
# region:
|
114
116
|
# Region to look for the service in
|
115
|
-
def self.registered_implementers(
|
117
|
+
def self.registered_implementers(name='*', version='*', region='Development')
|
116
118
|
hosts = []
|
117
119
|
doozer_pool.with_connection do |doozer|
|
118
|
-
doozer.walk("/services/#{
|
120
|
+
doozer.walk("/services/#{name}/#{version}/#{region}/*/*").each do |node|
|
119
121
|
entry = MultiJson.load(node.value)
|
120
122
|
hosts << entry if entry['Registered']
|
121
123
|
end
|
@@ -124,18 +126,18 @@ module RubySkynet
|
|
124
126
|
end
|
125
127
|
|
126
128
|
# Returns [Array<String>] a list of servers implementing the requested service
|
127
|
-
def self.servers_for(
|
129
|
+
def self.servers_for(name, version='*', region='Development')
|
128
130
|
if version == '*'
|
129
131
|
# Find the highest version for the named service in this region
|
130
132
|
version = -1
|
131
133
|
service_registry.keys.each do |key|
|
132
|
-
if match = key.match(/#{
|
134
|
+
if match = key.match(/#{name}\/(\d+)\/#{region}/)
|
133
135
|
ver = match[1].to_i
|
134
136
|
version = ver if ver > version
|
135
137
|
end
|
136
138
|
end
|
137
139
|
end
|
138
|
-
if server_infos = service_registry["#{
|
140
|
+
if server_infos = service_registry["#{name}/#{version}/#{region}"]
|
139
141
|
server_infos.first.servers
|
140
142
|
end
|
141
143
|
end
|
@@ -164,7 +166,7 @@ module RubySkynet
|
|
164
166
|
# 1
|
165
167
|
server_match = IPV4_REG_EXP.match(ip_address) || IPV4_REG_EXP.match(Resolv::DNS.new.getaddress(ip_address).to_s)
|
166
168
|
if server_match
|
167
|
-
@@local_match ||= IPV4_REG_EXP.match(
|
169
|
+
@@local_match ||= IPV4_REG_EXP.match(RubySkynet.local_ip_address)
|
168
170
|
score = 0
|
169
171
|
(1..4).each do |i|
|
170
172
|
break if @@local_match[i].to_i != server_match[i].to_i
|
@@ -178,9 +180,7 @@ module RubySkynet
|
|
178
180
|
protected
|
179
181
|
|
180
182
|
# Logging instance for this class
|
181
|
-
|
182
|
-
SemanticLogger::Logger.new(self, :debug)
|
183
|
-
end
|
183
|
+
include SemanticLogger::Loggable
|
184
184
|
|
185
185
|
# Lazy initialize Doozer Client Connection pool
|
186
186
|
sync_cattr_reader :doozer_pool do
|
@@ -250,7 +250,7 @@ module RubySkynet
|
|
250
250
|
# path from doozer: "/services/TutorialService/1/Development/127.0.0.1/9000"
|
251
251
|
e = path.split('/')
|
252
252
|
|
253
|
-
# Key: [String] '
|
253
|
+
# Key: [String] 'name/version/region'
|
254
254
|
key = "#{e[2]}/#{e[3]}/#{e[4]}"
|
255
255
|
hostname, port = e[5], e[6]
|
256
256
|
|
@@ -287,7 +287,7 @@ module RubySkynet
|
|
287
287
|
ServerInfo = Struct.new(:score, :servers )
|
288
288
|
|
289
289
|
# Format of the internal services registry
|
290
|
-
# key: [String] "<
|
290
|
+
# key: [String] "<name>/<version>/<region>"
|
291
291
|
# value: [ServiceInfo, ServiceInfo]
|
292
292
|
# Sorted by highest score first
|
293
293
|
|
@@ -353,16 +353,16 @@ module RubySkynet
|
|
353
353
|
|
354
354
|
# Check doozer for servers matching supplied criteria
|
355
355
|
# Code unused, consider deleting
|
356
|
-
def self.remote_servers_for(
|
356
|
+
def self.remote_servers_for(name, version='*', region='Development')
|
357
357
|
if version != '*'
|
358
|
-
registered_implementers(
|
358
|
+
registered_implementers(name, version, region).map do |host|
|
359
359
|
service = host['Config']['ServiceAddr']
|
360
360
|
"#{service['IPAddress']}:#{service['Port']}"
|
361
361
|
end
|
362
362
|
else
|
363
363
|
# Find the highest version of any particular service
|
364
364
|
versions = {}
|
365
|
-
registered_implementers(
|
365
|
+
registered_implementers(name, version, region).each do |host|
|
366
366
|
service = host['Config']['ServiceAddr']
|
367
367
|
(versions[version.to_i] ||= []) << "#{service['IPAddress']}:#{service['Port']}"
|
368
368
|
end
|
@@ -0,0 +1,69 @@
|
|
1
|
+
module RubySkynet
|
2
|
+
|
3
|
+
# Returns the default region for all Ruby Skynet Clients and Services
|
4
|
+
def self.region
|
5
|
+
@@region ||= 'Development'
|
6
|
+
end
|
7
|
+
|
8
|
+
# Sets the default region to use for Skynet Clients and Services
|
9
|
+
def self.region=(region)
|
10
|
+
@@region = region
|
11
|
+
end
|
12
|
+
|
13
|
+
# Returns the service_path where services are located
|
14
|
+
def self.services_path
|
15
|
+
@@services_path ||= 'app/services'
|
16
|
+
end
|
17
|
+
|
18
|
+
# Sets the service_path where services are located
|
19
|
+
def self.services_path=(services_path)
|
20
|
+
@@services_path = services_path
|
21
|
+
end
|
22
|
+
|
23
|
+
# Returns the starting port for the server to listen on
|
24
|
+
# If this port is in use the next available port will be used
|
25
|
+
# upto 999 above the server_port value
|
26
|
+
def self.server_port
|
27
|
+
@@server_port ||= 2000
|
28
|
+
end
|
29
|
+
|
30
|
+
def self.server_port=(server_port)
|
31
|
+
@@server_port = server_port
|
32
|
+
end
|
33
|
+
|
34
|
+
# The ip address at which this server instance can be reached
|
35
|
+
# by remote Skynet clients
|
36
|
+
# Note: Must be an IP address, not the hostname
|
37
|
+
def self.local_ip_address
|
38
|
+
@@local_ip_address ||= Common::local_ip_address
|
39
|
+
end
|
40
|
+
|
41
|
+
def self.local_ip_address=(local_ip_address)
|
42
|
+
@@local_ip_address = local_ip_address
|
43
|
+
end
|
44
|
+
|
45
|
+
# Load the Encryption Configuration from a YAML file
|
46
|
+
# filename:
|
47
|
+
# Name of file to read.
|
48
|
+
# Mandatory for non-Rails apps
|
49
|
+
# Default: Rails.root/config/ruby_skynet.yml
|
50
|
+
# environment:
|
51
|
+
# Which environment config to load. Usually: production, development, etc.
|
52
|
+
# Default: Rails.env
|
53
|
+
def self.configure!(filename=nil, environment=nil)
|
54
|
+
config_file = filename.nil? ? Rails.root.join('config', 'ruby_skynet.yml') : Pathname.new(filename)
|
55
|
+
raise "ruby_skynet config not found. Create a config file at: config/ruby_skynet.yml" unless config_file.file?
|
56
|
+
|
57
|
+
cfg = YAML.load(ERB.new(File.new(config_file).read).result)[environment || Rails.env]
|
58
|
+
raise("Environment #{Rails.env} not defined in config/ruby_skynet.yml") unless cfg
|
59
|
+
|
60
|
+
RubySkynet.region = cfg.delete(:region) if [:region]
|
61
|
+
RubySkynet.services_path = cfg.delete(:services_path) if [:services_path]
|
62
|
+
RubySkynet.server_port = cfg.delete(:server_port) if [:server_port]
|
63
|
+
RubySkynet.local_ip_address = cfg.delete(:local_ip_address) if [:local_ip_address]
|
64
|
+
RubySkynet::Registry.doozer_config = cfg.delete(:doozer) if [:doozer]
|
65
|
+
|
66
|
+
cfg.each_pair {|k,v| RubySkynet::Server.logger.warn "Ignoring unknown RubySkynet config option #{k} => #{v}"}
|
67
|
+
end
|
68
|
+
|
69
|
+
end
|
data/lib/ruby_skynet/server.rb
CHANGED
@@ -13,8 +13,14 @@ module RubySkynet
|
|
13
13
|
@@services = ThreadSafe::Hash.new
|
14
14
|
|
15
15
|
# Start a single instance of the server
|
16
|
-
def self.start(
|
17
|
-
@@server ||= new(
|
16
|
+
def self.start(start_port = nil, ip_address = nil)
|
17
|
+
@@server ||= new(start_port, ip_address)
|
18
|
+
|
19
|
+
# Stop the skynet server on shutdown
|
20
|
+
# To ensure services are de-registered in doozer
|
21
|
+
at_exit do
|
22
|
+
::RubySkynet::Server.stop
|
23
|
+
end
|
18
24
|
end
|
19
25
|
|
20
26
|
# Stop the single instance of the server
|
@@ -28,6 +34,11 @@ module RubySkynet
|
|
28
34
|
(@@server != nil) && @@server.running?
|
29
35
|
end
|
30
36
|
|
37
|
+
# Wait forever until the running server stops
|
38
|
+
def self.wait_until_server_stops
|
39
|
+
(@@server != nil) && @@server.wait_until_server_stops
|
40
|
+
end
|
41
|
+
|
31
42
|
# Services currently loaded and available at this server when running
|
32
43
|
def self.services
|
33
44
|
@@services
|
@@ -35,39 +46,49 @@ module RubySkynet
|
|
35
46
|
|
36
47
|
# Registers a Service Class as being available at this host and port
|
37
48
|
def self.register_service(klass)
|
38
|
-
raise InvalidServiceException.new("#{klass.inspect} is not a RubySkynet::Service") unless klass.respond_to?(:
|
49
|
+
raise InvalidServiceException.new("#{klass.inspect} is not a RubySkynet::Service") unless klass.respond_to?(:skynet_name) && klass.respond_to?(:skynet_version) && klass.respond_to?(:skynet_region)
|
39
50
|
|
40
|
-
if previous_klass = @@services[klass.
|
41
|
-
logger.warn("Service with name: #{klass.
|
51
|
+
if previous_klass = @@services[klass.skynet_name] && (previous_klass.name != klass.name)
|
52
|
+
logger.warn("Service with name: #{klass.skynet_name} is already registered to a different implementation:#{previous_klass.name}")
|
42
53
|
end
|
43
|
-
@@services[klass.
|
54
|
+
@@services[klass.skynet_name] = klass
|
44
55
|
@@server.register_service(klass) if @@server
|
45
56
|
end
|
46
57
|
|
47
58
|
# De-register service
|
48
59
|
def self.deregister_service(klass)
|
49
|
-
raise InvalidServiceException.new("#{klass.inspect} is not a RubySkynet::Service") unless klass.respond_to?(:
|
60
|
+
raise InvalidServiceException.new("#{klass.inspect} is not a RubySkynet::Service") unless klass.respond_to?(:skynet_name) && klass.respond_to?(:skynet_version) && klass.respond_to?(:skynet_region)
|
50
61
|
|
51
62
|
@@server.deregister_service(klass) if @@server
|
52
|
-
@@services.delete(klass.
|
63
|
+
@@services.delete(klass.skynet_name)
|
64
|
+
end
|
65
|
+
|
66
|
+
# Load and register all services found in the supplied path and it's sub-directories
|
67
|
+
def self.load_services
|
68
|
+
RubySkynet::Server.logger.benchmark_info "Loaded Skynet Services" do
|
69
|
+
# Load services
|
70
|
+
Dir.glob("#{RubySkynet.services_path}/**/*.rb").each do |path|
|
71
|
+
load path
|
72
|
+
end
|
73
|
+
end
|
53
74
|
end
|
54
75
|
|
55
|
-
# The actual port the server is running at
|
56
|
-
|
57
|
-
attr_reader :hostname, :port, :region
|
76
|
+
# The actual port the server is running at
|
77
|
+
attr_reader :hostname, :port
|
58
78
|
|
59
79
|
# Start the server so that it can start taking RPC calls
|
60
80
|
# Returns false if the server is already running
|
61
|
-
def initialize(
|
62
|
-
|
81
|
+
def initialize(start_port = nil, ip_address = nil)
|
82
|
+
ip_address ||= RubySkynet.local_ip_address
|
83
|
+
start_port = (start_port || RubySkynet.server_port).to_i
|
84
|
+
raise InvalidConfigurationException.new("Invalid Starting Port number: #{start_port}") unless start_port > 0
|
63
85
|
|
64
86
|
# If port is in use, try the next port in sequence
|
65
87
|
port_count = 0
|
66
88
|
begin
|
67
|
-
@server = ::TCPServer.new(
|
68
|
-
@hostname =
|
89
|
+
@server = ::TCPServer.new(ip_address, start_port + port_count)
|
90
|
+
@hostname = ip_address
|
69
91
|
@port = start_port + port_count
|
70
|
-
@region = region
|
71
92
|
rescue Errno::EADDRINUSE => exc
|
72
93
|
if port_count < 999
|
73
94
|
port_count += 1
|
@@ -77,7 +98,7 @@ module RubySkynet
|
|
77
98
|
end
|
78
99
|
|
79
100
|
# Start Server listener thread
|
80
|
-
Thread.new { run }
|
101
|
+
@listener_thread = Thread.new { run }
|
81
102
|
|
82
103
|
# Register services hosted by this server
|
83
104
|
self.class.services.each_value {|klass| register_service(klass)}
|
@@ -94,6 +115,19 @@ module RubySkynet
|
|
94
115
|
logger.info "Skynet Services De-registered"
|
95
116
|
end
|
96
117
|
|
118
|
+
# Returns whether the server is running
|
119
|
+
def running?
|
120
|
+
(@server != nil) && !@server.closed?
|
121
|
+
end
|
122
|
+
|
123
|
+
# Wait forever until the running server stops
|
124
|
+
def wait_until_server_stops
|
125
|
+
@listener_thread.join
|
126
|
+
end
|
127
|
+
|
128
|
+
############################################################################
|
129
|
+
protected
|
130
|
+
|
97
131
|
def run
|
98
132
|
logger.info("Starting listener on #{hostname}:#{port}")
|
99
133
|
loop do
|
@@ -129,22 +163,22 @@ module RubySkynet
|
|
129
163
|
logger.debug "Received Request"
|
130
164
|
logger.trace 'Header', header
|
131
165
|
|
132
|
-
|
133
|
-
raise "Invalid Skynet RPC Request, missing servicemethod" unless
|
134
|
-
match =
|
166
|
+
name = header['servicemethod']
|
167
|
+
raise "Invalid Skynet RPC Request, missing servicemethod" unless name
|
168
|
+
match = name.match /(.*)\.Forward$/
|
135
169
|
raise "Invalid Skynet RPC Request, servicemethod must end with '.Forward'" unless match
|
136
|
-
|
170
|
+
name = match[1]
|
137
171
|
|
138
172
|
request = Common.read_bson_document(client)
|
139
173
|
logger.trace 'Request', request
|
140
174
|
break unless request
|
141
175
|
params = BSON.deserialize(request['in'])
|
142
176
|
logger.trace 'Parameters', params
|
143
|
-
|
177
|
+
|
144
178
|
reply = begin
|
145
|
-
on_message(
|
179
|
+
on_message(name, request['method'].to_sym, params)
|
146
180
|
rescue ScriptError, NameError, StandardError, Exception => exc
|
147
|
-
logger.error "Exception while calling service: #{
|
181
|
+
logger.error "Exception while calling service: #{name}", exc
|
148
182
|
{ :exception => {:message => exc.message, :class => exc.class.name} }
|
149
183
|
end
|
150
184
|
|
@@ -169,36 +203,28 @@ module RubySkynet
|
|
169
203
|
logger.debug "Disconnected from the client"
|
170
204
|
end
|
171
205
|
|
172
|
-
# Returns whether the server is running
|
173
|
-
def running?
|
174
|
-
(@server != nil) && !@server.closed?
|
175
|
-
end
|
176
|
-
|
177
|
-
############################################################################
|
178
|
-
protected
|
179
|
-
|
180
206
|
# Registers a Service Class as being available at this server
|
181
207
|
def register_service(klass)
|
182
|
-
logger.debug "Registering Service: #{klass.name} with name: #{klass.
|
183
|
-
Registry.register_service(klass.
|
208
|
+
logger.debug "Registering Service: #{klass.name} with name: #{klass.skynet_name}"
|
209
|
+
Registry.register_service(klass.skynet_name, klass.skynet_version || 1, klass.skynet_region, @hostname, @port)
|
184
210
|
end
|
185
211
|
|
186
212
|
# De-register service from this server
|
187
213
|
def deregister_service(klass)
|
188
|
-
logger.debug "De-registering Service: #{klass.name} with name: #{klass.
|
189
|
-
Registry.deregister_service(klass.
|
214
|
+
logger.debug "De-registering Service: #{klass.name} with name: #{klass.skynet_name}"
|
215
|
+
Registry.deregister_service(klass.skynet_name, klass.skynet_version || 1, klass.skynet_region, @hostname, @port)
|
190
216
|
end
|
191
217
|
|
192
218
|
# Called for each message received from the client
|
193
219
|
# Returns a Hash that is sent back to the caller
|
194
|
-
def on_message(
|
195
|
-
logger.benchmark_info("Skynet Call: #{
|
220
|
+
def on_message(skynet_name, method, params)
|
221
|
+
logger.benchmark_info("Skynet Call: #{skynet_name}##{method}") do
|
196
222
|
logger.trace "Method Call: #{method} with parameters:", params
|
197
|
-
klass = Server.services[
|
198
|
-
raise "Invalid Skynet RPC call, service: #{
|
223
|
+
klass = Server.services[skynet_name]
|
224
|
+
raise "Invalid Skynet RPC call, service: #{skynet_name} is not available at this server" unless klass
|
199
225
|
# TODO Use pool of services
|
200
226
|
service = klass.new
|
201
|
-
raise "Invalid Skynet RPC call, method: #{method} does not exist for service: #{
|
227
|
+
raise "Invalid Skynet RPC call, method: #{method} does not exist for service: #{skynet_name}" unless service.respond_to?(method)
|
202
228
|
service.send(method, params)
|
203
229
|
end
|
204
230
|
end
|
data/lib/ruby_skynet/service.rb
CHANGED
@@ -1,6 +1,4 @@
|
|
1
|
-
|
2
|
-
require 'multi_json'
|
3
|
-
require 'thread_safe'
|
1
|
+
require 'semantic_logger'
|
4
2
|
|
5
3
|
#
|
6
4
|
# RubySkynet Service
|
@@ -11,43 +9,17 @@ require 'thread_safe'
|
|
11
9
|
#
|
12
10
|
module RubySkynet
|
13
11
|
module Service
|
12
|
+
|
14
13
|
def self.included(base)
|
15
|
-
base.extend ClassMethods
|
14
|
+
base.extend ::RubySkynet::Base::ClassMethods
|
16
15
|
base.class_eval do
|
17
16
|
include SemanticLogger::Loggable
|
18
|
-
|
19
|
-
sync_cattr_reader :logger do
|
20
|
-
SemanticLogger::Logger.new(self)
|
21
|
-
end
|
22
17
|
end
|
23
18
|
# Register the service with the Server
|
24
19
|
# The server will publish the server to Doozer when the server is running
|
25
20
|
Server.register_service(base)
|
26
21
|
end
|
27
22
|
|
28
|
-
module ClassMethods
|
29
|
-
# Name of this service to Register with Skynet
|
30
|
-
# Default: class name
|
31
|
-
def service_name
|
32
|
-
@service_name ||= name.gsub('::', '.')
|
33
|
-
end
|
34
|
-
|
35
|
-
def service_name=(service_name)
|
36
|
-
@service_name = service_name
|
37
|
-
end
|
38
|
-
|
39
|
-
# Version of this service to register with Skynet, defaults to 1
|
40
|
-
# Default: 1
|
41
|
-
def service_version
|
42
|
-
@service_version ||= 1
|
43
|
-
end
|
44
|
-
|
45
|
-
def service_version=(service_version)
|
46
|
-
@service_version = service_version
|
47
|
-
end
|
48
|
-
|
49
|
-
end
|
50
|
-
|
51
23
|
end
|
52
24
|
end
|
53
25
|
|
data/lib/ruby_skynet/version.rb
CHANGED
data/lib/ruby_skynet.rb
CHANGED
@@ -1,14 +1,20 @@
|
|
1
1
|
require 'semantic_logger'
|
2
2
|
require 'ruby_skynet/exceptions'
|
3
3
|
require 'ruby_skynet/version'
|
4
|
+
require 'ruby_skynet/ruby_skynet'
|
4
5
|
module RubySkynet
|
5
6
|
module Doozer
|
6
7
|
autoload :Client, 'ruby_skynet/doozer/client'
|
7
8
|
end
|
8
9
|
autoload :Registry, 'ruby_skynet/registry'
|
9
10
|
autoload :Connection, 'ruby_skynet/connection'
|
11
|
+
autoload :Base, 'ruby_skynet/base'
|
10
12
|
autoload :Common, 'ruby_skynet/common'
|
11
13
|
autoload :Client, 'ruby_skynet/client'
|
12
14
|
autoload :Service, 'ruby_skynet/service'
|
13
15
|
autoload :Server, 'ruby_skynet/server'
|
14
16
|
end
|
17
|
+
|
18
|
+
if defined?(Rails)
|
19
|
+
require 'ruby_skynet/railtie'
|
20
|
+
end
|
data/test/base_test.rb
ADDED
@@ -0,0 +1,89 @@
|
|
1
|
+
# Allow test to be run in-place without requiring a gem install
|
2
|
+
$LOAD_PATH.unshift File.dirname(__FILE__) + '/../lib'
|
3
|
+
$LOAD_PATH.unshift File.dirname(__FILE__)
|
4
|
+
|
5
|
+
require 'rubygems'
|
6
|
+
require 'test/unit'
|
7
|
+
require 'shoulda'
|
8
|
+
require 'ruby_skynet'
|
9
|
+
|
10
|
+
# Register an appender if one is not already registered
|
11
|
+
if SemanticLogger::Logger.appenders.size == 0
|
12
|
+
SemanticLogger::Logger.default_level = :debug
|
13
|
+
SemanticLogger::Logger.appenders << SemanticLogger::Appender::File.new('test.log')
|
14
|
+
end
|
15
|
+
|
16
|
+
# Service implementation
|
17
|
+
class BaseTestService
|
18
|
+
include RubySkynet::Service
|
19
|
+
|
20
|
+
# Methods implemented by this service
|
21
|
+
# Must take a Hash as input
|
22
|
+
# Must Return a Hash response or nil for no response
|
23
|
+
def test1(params)
|
24
|
+
{ 'result' => 'test1' }
|
25
|
+
end
|
26
|
+
|
27
|
+
def sleep(params)
|
28
|
+
Kernel.sleep params['duration'] || 1
|
29
|
+
{ 'result' => 'sleep' }
|
30
|
+
end
|
31
|
+
|
32
|
+
def fail(params)
|
33
|
+
if params['attempt'].to_i >= 2
|
34
|
+
{ 'result' => 'fail' }
|
35
|
+
else
|
36
|
+
nil
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
end
|
41
|
+
|
42
|
+
# Service Client
|
43
|
+
class BaseTestServiceClient
|
44
|
+
include RubySkynet::Base
|
45
|
+
|
46
|
+
# Override Name registered in skynet to match server above
|
47
|
+
self.skynet_name = 'BaseTestService'
|
48
|
+
end
|
49
|
+
|
50
|
+
# Unit Test
|
51
|
+
class BaseTest < Test::Unit::TestCase
|
52
|
+
context RubySkynet::Base do
|
53
|
+
|
54
|
+
context "with server" do
|
55
|
+
setup do
|
56
|
+
RubySkynet.region = @region
|
57
|
+
RubySkynet::Server.start
|
58
|
+
|
59
|
+
@read_timeout = 3.0
|
60
|
+
end
|
61
|
+
|
62
|
+
teardown do
|
63
|
+
RubySkynet::Server.stop
|
64
|
+
end
|
65
|
+
|
66
|
+
context "with client connection" do
|
67
|
+
setup do
|
68
|
+
@client = BaseTestServiceClient.new
|
69
|
+
end
|
70
|
+
|
71
|
+
should "successfully send and receive data" do
|
72
|
+
reply = @client.test1('some' => 'parameters')
|
73
|
+
assert_equal 'test1', reply['result']
|
74
|
+
end
|
75
|
+
|
76
|
+
should "timeout on receive" do
|
77
|
+
request = { 'duration' => @read_timeout + 0.5}
|
78
|
+
|
79
|
+
exception = assert_raise ResilientSocket::ReadTimeout do
|
80
|
+
# Read 4 bytes from server
|
81
|
+
@client.sleep(request, :read_timeout => @read_timeout)
|
82
|
+
end
|
83
|
+
assert_match /Timedout after #{@read_timeout} seconds trying to read/, exception.message
|
84
|
+
end
|
85
|
+
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
data/test/client_test.rb
CHANGED
@@ -56,7 +56,8 @@ class ClientTest < Test::Unit::TestCase
|
|
56
56
|
context "with server" do
|
57
57
|
setup do
|
58
58
|
@region = 'ClientTest'
|
59
|
-
RubySkynet
|
59
|
+
RubySkynet.region = @region
|
60
|
+
RubySkynet::Server.start
|
60
61
|
|
61
62
|
@service_name = 'ClientTestService'
|
62
63
|
@version = 1
|
data/test/registry_test.rb
CHANGED
@@ -89,7 +89,7 @@ class RegistryTest < Test::Unit::TestCase
|
|
89
89
|
['10.0.11.0', 0 ],
|
90
90
|
].each do |test|
|
91
91
|
should "handle score #{test[1]}" do
|
92
|
-
RubySkynet
|
92
|
+
RubySkynet.stubs(:local_ip_address).returns("192.168.11.0")
|
93
93
|
assert_equal test[1], RubySkynet::Registry.score_for_server(test[0]), "Local: #{RubySkynet::Common.local_ip_address} Server: #{test[0]} Score: #{test[1]}"
|
94
94
|
end
|
95
95
|
end
|
data/test/service_test.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: ruby_skynet
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.5.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Reid Morrison
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2013-03-
|
11
|
+
date: 2013-03-27 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: semantic_logger
|
@@ -80,6 +80,20 @@ dependencies:
|
|
80
80
|
- - '>='
|
81
81
|
- !ruby/object:Gem::Version
|
82
82
|
version: '0'
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: gene_pool
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - '>='
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '0'
|
90
|
+
type: :runtime
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - '>='
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: '0'
|
83
97
|
description: Ruby Client for invoking Skynet services
|
84
98
|
email:
|
85
99
|
- reidmo@gmail.com
|
@@ -95,7 +109,10 @@ files:
|
|
95
109
|
- examples/e.rb
|
96
110
|
- examples/echo_client.rb
|
97
111
|
- examples/echo_server.rb
|
112
|
+
- lib/rails/generators/ruby_skynet/config/config_generator.rb
|
113
|
+
- lib/rails/generators/ruby_skynet/config/templates/ruby_skynet.yml
|
98
114
|
- lib/ruby_skynet.rb
|
115
|
+
- lib/ruby_skynet/base.rb
|
99
116
|
- lib/ruby_skynet/client.rb
|
100
117
|
- lib/ruby_skynet/common.rb
|
101
118
|
- lib/ruby_skynet/connection.rb
|
@@ -103,11 +120,15 @@ files:
|
|
103
120
|
- lib/ruby_skynet/doozer/exceptions.rb
|
104
121
|
- lib/ruby_skynet/doozer/msg.pb.rb
|
105
122
|
- lib/ruby_skynet/exceptions.rb
|
123
|
+
- lib/ruby_skynet/railtie.rb
|
124
|
+
- lib/ruby_skynet/railties/ruby_skynet.rake
|
106
125
|
- lib/ruby_skynet/registry.rb
|
126
|
+
- lib/ruby_skynet/ruby_skynet.rb
|
107
127
|
- lib/ruby_skynet/server.rb
|
108
128
|
- lib/ruby_skynet/service.rb
|
109
129
|
- lib/ruby_skynet/version.rb
|
110
130
|
- test.sh
|
131
|
+
- test/base_test.rb
|
111
132
|
- test/client_test.rb
|
112
133
|
- test/doozer_client_test.rb
|
113
134
|
- test/registry_test.rb
|