stargate 0.1.2 → 0.1.3
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/CHANGELOG.md +4 -0
- data/README.md +5 -3
- data/examples/server/config.ru +3 -2
- data/lib/stargate/client/core_ext/kernel.rb +8 -0
- data/lib/stargate/client/injector.rb +2 -0
- data/lib/stargate/client/protocol.rb +21 -0
- data/lib/stargate/client/protocol/http.rb +1 -0
- data/lib/stargate/client/protocol/inproc.rb +1 -0
- data/lib/stargate/client/proxy.rb +13 -1
- data/lib/stargate/codec.rb +4 -0
- data/lib/stargate/metadata.rb +13 -11
- data/lib/stargate/server/caller.rb +2 -0
- data/lib/stargate/server/engine/inproc.rb +1 -0
- data/lib/stargate/server/engine/sinatra.rb +2 -0
- data/lib/stargate/server/registry.rb +17 -0
- data/lib/stargate/server/registry_version.rb +18 -0
- data/lib/stargate/version.rb +1 -1
- data/stargate.gemspec +1 -2
- metadata +5 -26
- data/lib/stargate/errors.rb +0 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 5bd3b300a1db02cdc5888f43fcbb12898f39e757
|
4
|
+
data.tar.gz: aa03a1e5779f1b3d8bf6baa089a04008d13ab975
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 81aa058faf53aff8833a8151889e2f54cbab0c995f63c7064737e5d1e2911c4be64f287d1f9cb48608020460d95809a62b38d3ef481d186307b0e29048400ccd
|
7
|
+
data.tar.gz: 826bfb7249126d66fe8b4d87189c96a68758288ca4ee0a30968b7da1e7554fe4257de534f417064b88077d171eafcda84a199b22bbfa92ccd73776b23bfd2009
|
data/CHANGELOG.md
CHANGED
data/README.md
CHANGED
@@ -1,6 +1,8 @@
|
|
1
1
|
# Stargate
|
2
2
|
|
3
|
-
[](https://codeship.com/projects/128080)
|
4
|
+
|
5
|
+

|
4
6
|
|
5
7
|
Stargate is a portal between ruby (and in the future not any) apps. It facilitates creating internal micro-services
|
6
8
|
and allows to scale your logic pretty much infinitely.
|
@@ -34,7 +36,7 @@ class are executed locally or remotely. Fire, get results, forget. No thinking o
|
|
34
36
|
Add this line to your application's Gemfile:
|
35
37
|
|
36
38
|
```ruby
|
37
|
-
gem 'stargate', '0.1.
|
39
|
+
gem 'stargate', '0.1.3'
|
38
40
|
```
|
39
41
|
|
40
42
|
And then execute:
|
@@ -43,7 +45,7 @@ And then execute:
|
|
43
45
|
|
44
46
|
Or install it yourself as:
|
45
47
|
|
46
|
-
$ gem install stargate --version 0.1.
|
48
|
+
$ gem install stargate --version 0.1.3
|
47
49
|
|
48
50
|
## Usage
|
49
51
|
|
data/examples/server/config.ru
CHANGED
@@ -1,5 +1,3 @@
|
|
1
|
-
require 'stargate/server/engine/sinatra'
|
2
|
-
|
3
1
|
module NightsWatch
|
4
2
|
class NewBrother
|
5
3
|
def self.oath
|
@@ -28,6 +26,9 @@ module NightsWatch
|
|
28
26
|
end
|
29
27
|
end
|
30
28
|
|
29
|
+
require 'stargate'
|
30
|
+
require 'stargate/server/engine/sinatra'
|
31
|
+
|
31
32
|
registry = Stargate::Server::Registry.new do
|
32
33
|
version 1 do
|
33
34
|
serve NightsWatch::NewBrother do
|
@@ -1,8 +1,16 @@
|
|
1
1
|
module Kernel
|
2
|
+
# Public: Loads remote definitions from given URL and injects them in local namespace.
|
3
|
+
#
|
4
|
+
# Example:
|
5
|
+
#
|
6
|
+
# require_remote('http+json://example.com/v1#timeout=0.3')
|
7
|
+
#
|
8
|
+
# Returns nothing.
|
2
9
|
def require_remote(url)
|
3
10
|
@required_remotes ||= []
|
4
11
|
return if @required_remotes.include?(url)
|
5
12
|
injector = Stargate::Client::Injector.new(url)
|
6
13
|
@required_remotes << url
|
14
|
+
nil
|
7
15
|
end
|
8
16
|
end
|
@@ -1,5 +1,7 @@
|
|
1
1
|
module Stargate
|
2
2
|
module Client
|
3
|
+
# Internal: The job of Injector is to inject remote definitions to local namespace. It does it by
|
4
|
+
# creating new namespaces dynamically and injecting Proxy classes to remote objects.
|
3
5
|
class Injector
|
4
6
|
include Logging
|
5
7
|
include Stargate::Client
|
@@ -10,23 +10,37 @@ module Stargate
|
|
10
10
|
|
11
11
|
@@transports = {}
|
12
12
|
|
13
|
+
# Public: List of registered transports (protocol implementations).
|
13
14
|
def self.transports
|
14
15
|
@@transports
|
15
16
|
end
|
16
17
|
|
18
|
+
# Public: Registers new implementation for given protocols.
|
17
19
|
def self.register(protocols, transport)
|
18
20
|
protocols.each { |protocol| transports[protocol] = transport }
|
19
21
|
end
|
20
22
|
|
23
|
+
# Public: Finds implementation for given protocol.
|
24
|
+
#
|
25
|
+
# Returns transport if found.
|
26
|
+
# Raises UnsupportedProtocolError if not found.
|
21
27
|
def self.[](protocol)
|
22
28
|
transports[protocol.downcase] or raise UnsupportedProtocolError, "Unsupported protocol: #{protocol}"
|
23
29
|
end
|
24
30
|
|
31
|
+
# Public: Codec used to serialize/deserialize payload.
|
25
32
|
attr_reader :codec
|
33
|
+
|
34
|
+
# Public: Remote URL of the endpoint.
|
26
35
|
attr_reader :uri
|
36
|
+
|
37
|
+
# Public: URL without credentials part.
|
27
38
|
attr_reader :safe_uri
|
39
|
+
|
40
|
+
# Public: Transport configuration.
|
28
41
|
attr_reader :options
|
29
42
|
|
43
|
+
# Public: Constructor.
|
30
44
|
def initialize(codec, uri)
|
31
45
|
@codec = codec
|
32
46
|
@uri = uri
|
@@ -35,10 +49,12 @@ module Stargate
|
|
35
49
|
@unmarshaller = Unmarshaller.new
|
36
50
|
end
|
37
51
|
|
52
|
+
# Public: Shall load all definitions from remote server.
|
38
53
|
def fetch_definitions
|
39
54
|
raise NotImplementedError
|
40
55
|
end
|
41
56
|
|
57
|
+
# Public: Shall execute class method with given arguments. Executes method remotely of course.
|
42
58
|
def call(klass, method, *args)
|
43
59
|
raise NotImplementedError
|
44
60
|
end
|
@@ -49,14 +65,19 @@ module Stargate
|
|
49
65
|
{ timeout: DEFAULT_TIMEOUT }
|
50
66
|
end
|
51
67
|
|
68
|
+
# Internal: A helper to unpack loaded data.
|
52
69
|
def unpack_payload(data)
|
53
70
|
@unmarshaller.unmarshal(data)
|
54
71
|
end
|
55
72
|
|
73
|
+
# Internal: A helper to unpack remote definitions.
|
56
74
|
def unpack_definitions(definitions)
|
57
75
|
definitions.map { |metadata| ::Stargate::Metadata.from_hash(metadata) }
|
58
76
|
end
|
59
77
|
|
78
|
+
# Internal: Parses options from URI fragment. Example http+json://example.com/v1#timeout=0.3
|
79
|
+
#
|
80
|
+
# Returns hash with options.
|
60
81
|
def parse_options_from_uri_fragment
|
61
82
|
uri.fragment.to_s.split(';').inject({}) do |options, entry|
|
62
83
|
k, v = entry.split('=')
|
@@ -2,6 +2,7 @@ require 'rest-client'
|
|
2
2
|
|
3
3
|
module Stargate
|
4
4
|
module Client
|
5
|
+
# Internal:: HTTP protocol implementation based on Sinatra engine implemented on the Server side.
|
5
6
|
class Protocol::HTTP < Protocol
|
6
7
|
def fetch_definitions
|
7
8
|
log.debug("Loading remote definitions", url: safe_uri.to_s)
|
@@ -1,10 +1,17 @@
|
|
1
1
|
module Stargate
|
2
2
|
module Client
|
3
|
+
# Internal: Here's where the magic happens. The proxy class connects local method calls with
|
4
|
+
# remote endpoints. Basically whenever any of registered (provided by remote definitions) methods
|
5
|
+
# is called, proxy forwards this call to remote location and returns obtained results adapted
|
6
|
+
# to local context.
|
3
7
|
class Proxy
|
8
|
+
# Internal: Magic for metaprogramming tricks.
|
4
9
|
def self.metaclass
|
5
10
|
class << self; self; end
|
6
11
|
end
|
7
12
|
|
13
|
+
# Internal: Configures portal for given protocol. Takes class metadata to define all entry
|
14
|
+
# point class methods, object attributes and readers.
|
8
15
|
def self.configure_stargate_portal(protocol, metadata)
|
9
16
|
metaclass.instance_eval do
|
10
17
|
metadata.class_methods.each do |method|
|
@@ -22,10 +29,12 @@ module Stargate
|
|
22
29
|
define_readers(*metadata.readers)
|
23
30
|
end
|
24
31
|
|
32
|
+
# Internal: Helper to define all attributres (accessors).
|
25
33
|
def self.define_attributes(*names)
|
26
|
-
|
34
|
+
attr_accessor(*names)
|
27
35
|
end
|
28
36
|
|
37
|
+
# Internal: Helper to define reader methods.
|
29
38
|
def self.define_readers(*names)
|
30
39
|
names.each do |name|
|
31
40
|
name = name.to_s
|
@@ -35,6 +44,9 @@ module Stargate
|
|
35
44
|
end
|
36
45
|
end
|
37
46
|
|
47
|
+
# Public: Constructor. Proxy class ignores remote constructor definition. Local proxy is always
|
48
|
+
# treaded as a data structure only and thus it's convenient to initialize it with attributes
|
49
|
+
# to set.
|
38
50
|
def initialize(attributes = {})
|
39
51
|
attributes.each do |name,value|
|
40
52
|
instance_variable_set("@#{name}", value)
|
data/lib/stargate/codec.rb
CHANGED
@@ -11,18 +11,22 @@ module Stargate
|
|
11
11
|
|
12
12
|
@@codecs = {}
|
13
13
|
|
14
|
+
# Internal: Returns all registered codecs.
|
14
15
|
def self.codecs
|
15
16
|
@@codecs
|
16
17
|
end
|
17
18
|
|
19
|
+
# Public: Register new codec.
|
18
20
|
def self.register(codec)
|
19
21
|
codecs[codec.content_type.to_s] = codec
|
20
22
|
end
|
21
23
|
|
24
|
+
# Public: Find codec by given identifier.
|
22
25
|
def self.find_by_id(id)
|
23
26
|
codecs.values.find { |codec| codec.id == id.to_sym } or raise UndefinedCodecError, "No such codec: #{id}"
|
24
27
|
end
|
25
28
|
|
29
|
+
# Public: Find codec for given content type.
|
26
30
|
def self.[](content_type)
|
27
31
|
codecs[content_type.to_s] or raise UndefinedCodecError, "No codec for type: #{content_type}"
|
28
32
|
end
|
data/lib/stargate/metadata.rb
CHANGED
@@ -1,7 +1,16 @@
|
|
1
1
|
module Stargate
|
2
|
+
# Internal: We need a way to store information about registered classes. Each served class
|
3
|
+
# defines itself with the following information:
|
4
|
+
#
|
5
|
+
# * Class name (eventually serving alias)
|
6
|
+
# * List of exposed class methods
|
7
|
+
# * List of instance attributes (accessors)
|
8
|
+
# * List of instance methods (cacheable reader methods)
|
9
|
+
#
|
2
10
|
class Metadata
|
3
11
|
include Serialization
|
4
12
|
|
13
|
+
# Internal: Loads metadata information from hash.
|
5
14
|
def self.from_hash(hash)
|
6
15
|
hash.symbolize_keys!
|
7
16
|
|
@@ -12,10 +21,10 @@ module Stargate
|
|
12
21
|
end
|
13
22
|
end
|
14
23
|
|
15
|
-
|
16
|
-
|
17
|
-
attr_reader :name
|
24
|
+
# The class to be served and it's serving alias.
|
25
|
+
attr_reader :klass, :name
|
18
26
|
|
27
|
+
# Public: Constructor.
|
19
28
|
def initialize(klass, name, &block)
|
20
29
|
@klass, @name = klass, name
|
21
30
|
@class_methods = []
|
@@ -25,10 +34,6 @@ module Stargate
|
|
25
34
|
instance_eval(&block) if block_given?
|
26
35
|
end
|
27
36
|
|
28
|
-
def active_record?
|
29
|
-
@active_record
|
30
|
-
end
|
31
|
-
|
32
37
|
def class_methods(*names)
|
33
38
|
load_or_add(:class_methods, *names)
|
34
39
|
end
|
@@ -56,10 +61,7 @@ module Stargate
|
|
56
61
|
|
57
62
|
private
|
58
63
|
|
59
|
-
|
60
|
-
defined?(::ActiveRecord) && klass && klass < ::ActiveRecord::Base
|
61
|
-
end
|
62
|
-
|
64
|
+
# Internal: A helper to define single access methods (getter/setter DSL methods).
|
63
65
|
def load_or_add(method, *args)
|
64
66
|
value = instance_variable_get("@#{method}")
|
65
67
|
args.empty? ? value : value.concat(args.flatten.map(&:to_sym))
|
@@ -3,6 +3,7 @@ require 'stargate/server'
|
|
3
3
|
module Stargate
|
4
4
|
module Server
|
5
5
|
module Engine
|
6
|
+
# Public: Testing, in-process (more accurately in-app) engine to interchange information.
|
6
7
|
class Inproc
|
7
8
|
def self.register(name, registry)
|
8
9
|
registry.each do |version_number, actual_registry|
|
@@ -3,6 +3,8 @@ require 'stargate/server'
|
|
3
3
|
module Stargate
|
4
4
|
module Server
|
5
5
|
module Engine
|
6
|
+
# Public: Sinatra transport. Very simple implementation of a transport that speaks non-REST interface.
|
7
|
+
# Sorta RPC transport over HTTP implemented with Sinatra.
|
6
8
|
class Sinatra
|
7
9
|
include Logging
|
8
10
|
|
@@ -1,19 +1,36 @@
|
|
1
1
|
module Stargate
|
2
2
|
module Server
|
3
|
+
# Internal: Registry contains list of versions, each with defined served classes.
|
4
|
+
#
|
5
|
+
# Example:
|
6
|
+
#
|
7
|
+
# Stargate::Server::Registry.new do
|
8
|
+
# version 1 do
|
9
|
+
# serve MyClass do
|
10
|
+
# class_methods :foo, :bar
|
11
|
+
# attributes :foo, :bar, :baz
|
12
|
+
# end
|
13
|
+
# end
|
14
|
+
# end
|
15
|
+
#
|
3
16
|
class Registry
|
4
17
|
include Enumerable
|
5
18
|
|
19
|
+
# Public: List of registry versions.
|
6
20
|
attr_reader :versions
|
7
21
|
|
22
|
+
# Public: Constructor.
|
8
23
|
def initialize(&block)
|
9
24
|
@versions = {}
|
10
25
|
instance_eval(&block) if block_given?
|
11
26
|
end
|
12
27
|
|
28
|
+
# Public: Defines new version. Executes with internal DSL.
|
13
29
|
def version(number, &block)
|
14
30
|
@versions[number] ||= RegistryVersion.new(number, &block)
|
15
31
|
end
|
16
32
|
|
33
|
+
# Public: Returns given registry version.
|
17
34
|
def [](version)
|
18
35
|
versions[version] or raise RegistryVersionUndefinedError, "No such registry version: #{version}"
|
19
36
|
end
|
@@ -2,15 +2,20 @@ require 'forwardable'
|
|
2
2
|
|
3
3
|
module Stargate
|
4
4
|
module Server
|
5
|
+
# Internal: Here's where all information about served classes are stored. Registered classes information
|
6
|
+
# is stored in form of Stargate::Metadata.
|
5
7
|
class RegistryVersion
|
6
8
|
include Logging
|
7
9
|
include Enumerable
|
8
10
|
include Serialization
|
9
11
|
|
12
|
+
# Public: Registry version number.
|
10
13
|
attr_reader :version
|
11
14
|
|
15
|
+
# Public: Registered definitions (list of metadata).
|
12
16
|
attr_reader :definitions
|
13
17
|
|
18
|
+
# Public: Constructor.
|
14
19
|
def initialize(version = 1, &block)
|
15
20
|
@version = version
|
16
21
|
@definitions = []
|
@@ -18,6 +23,10 @@ module Stargate
|
|
18
23
|
instance_eval(&block) if block_given?
|
19
24
|
end
|
20
25
|
|
26
|
+
# Public: Registers given class in this registry. A class can be registered with different name using
|
27
|
+
# the `:as` params key.
|
28
|
+
#
|
29
|
+
# Raises ClassAlreadyRegisteredError if class is already registered.
|
21
30
|
def serve(klass, params = {}, &block)
|
22
31
|
raise ClassAlreadyRegisteredError, "Class already registered: #{klass.name}" if registered?(klass)
|
23
32
|
|
@@ -29,15 +38,24 @@ module Stargate
|
|
29
38
|
self
|
30
39
|
end
|
31
40
|
|
41
|
+
# Internal: Returns true when given class is already registered.
|
32
42
|
def registered?(klass)
|
33
43
|
@definitions.find { |metadata| metadata.klass == klass }
|
34
44
|
end
|
35
45
|
|
46
|
+
# Internal: Finds metadata information for given object (namely for the class of given object).
|
47
|
+
#
|
48
|
+
# Returns Stargate::Metadata if found.
|
49
|
+
# Raises ClassNotExposedError if not found.
|
36
50
|
def metadata_for(obj)
|
37
51
|
metadata = @definitions.find { |metadata| metadata.klass == obj.class }
|
38
52
|
metadata or raise ClassNotExposedError, "Class not registered: #{obj.class.name}"
|
39
53
|
end
|
40
54
|
|
55
|
+
# Internal: Finds metadata information for given class.
|
56
|
+
#
|
57
|
+
# Returns Stargate::Metadata if found.
|
58
|
+
# Raises ClassNotExposedError if not found.
|
41
59
|
def [](klass_name)
|
42
60
|
metadata = @definitions.find { |metadata| metadata.name == klass_name }
|
43
61
|
metadata or raise ClassNotExposedError, "Class not registered under name: #{klass_name}"
|
data/lib/stargate/version.rb
CHANGED
data/stargate.gemspec
CHANGED
@@ -37,6 +37,5 @@ Gem::Specification.new do |spec|
|
|
37
37
|
spec.add_dependency "activesupport", "~> 4.0", ">= 3.0"
|
38
38
|
spec.add_dependency "sinatra", "~> 1.4"
|
39
39
|
spec.add_dependency "rest-client", "~> 1.8"
|
40
|
-
spec.add_dependency "
|
41
|
-
spec.add_dependency "perfume", "~> 0.3", ">= 0.3.1"
|
40
|
+
spec.add_dependency "gallus"
|
42
41
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: stargate
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- jobandtalent
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: exe
|
11
11
|
cert_chain: []
|
12
|
-
date: 2016-01-
|
12
|
+
date: 2016-01-18 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: bundler
|
@@ -268,39 +268,19 @@ dependencies:
|
|
268
268
|
- !ruby/object:Gem::Version
|
269
269
|
version: '1.8'
|
270
270
|
- !ruby/object:Gem::Dependency
|
271
|
-
name:
|
271
|
+
name: gallus
|
272
272
|
requirement: !ruby/object:Gem::Requirement
|
273
273
|
requirements:
|
274
|
-
- - "~>"
|
275
|
-
- !ruby/object:Gem::Version
|
276
|
-
version: '1.1'
|
277
|
-
type: :runtime
|
278
|
-
prerelease: false
|
279
|
-
version_requirements: !ruby/object:Gem::Requirement
|
280
|
-
requirements:
|
281
|
-
- - "~>"
|
282
|
-
- !ruby/object:Gem::Version
|
283
|
-
version: '1.1'
|
284
|
-
- !ruby/object:Gem::Dependency
|
285
|
-
name: perfume
|
286
|
-
requirement: !ruby/object:Gem::Requirement
|
287
|
-
requirements:
|
288
|
-
- - "~>"
|
289
|
-
- !ruby/object:Gem::Version
|
290
|
-
version: '0.3'
|
291
274
|
- - ">="
|
292
275
|
- !ruby/object:Gem::Version
|
293
|
-
version: 0
|
276
|
+
version: '0'
|
294
277
|
type: :runtime
|
295
278
|
prerelease: false
|
296
279
|
version_requirements: !ruby/object:Gem::Requirement
|
297
280
|
requirements:
|
298
|
-
- - "~>"
|
299
|
-
- !ruby/object:Gem::Version
|
300
|
-
version: '0.3'
|
301
281
|
- - ">="
|
302
282
|
- !ruby/object:Gem::Version
|
303
|
-
version: 0
|
283
|
+
version: '0'
|
304
284
|
description: Stargate opens a portal to call remote methods via simple and reliable
|
305
285
|
RPC protocols.
|
306
286
|
email:
|
@@ -337,7 +317,6 @@ files:
|
|
337
317
|
- lib/stargate/codec/bencode.rb
|
338
318
|
- lib/stargate/codec/json.rb
|
339
319
|
- lib/stargate/codec/message_pack.rb
|
340
|
-
- lib/stargate/errors.rb
|
341
320
|
- lib/stargate/marshal.rb
|
342
321
|
- lib/stargate/marshal/marshaller.rb
|
343
322
|
- lib/stargate/marshal/payload.rb
|
data/lib/stargate/errors.rb
DELETED