candycane 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.
- checksums.yaml +7 -0
- data/lib/candycane.rb +25 -0
- data/lib/candycane/configuration.rb +42 -0
- data/lib/candycane/dsl.rb +34 -0
- data/lib/candycane/local_method_call.rb +19 -0
- data/lib/candycane/remote_method_call.rb +28 -0
- data/lib/candycane/serializer.rb +2 -0
- data/lib/candycane/serializer/json_serializer.rb +11 -0
- data/lib/candycane/transport.rb +2 -0
- data/lib/candycane/transport/wire.rb +53 -0
- data/lib/candycane/version.rb +3 -0
- metadata +96 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 8d0e5bb7da27c71ee591071daa408878b593c29e
|
4
|
+
data.tar.gz: 6bc747f42af0241708e1d83e35e6908237bc136e
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: c7363d275aa0d451214f36f7e5ec89a0221c0988912a8b3000b88b3047843a0e1d59704f1a9c9ca8303c1fe93f885c41885bf6fc9fe2276c53a2d2c03e77c57a
|
7
|
+
data.tar.gz: 2317a5fe33ef4d9166f7540d87477c8d6d646ee417754a9310472142e6421882292735268f5d0f295f9c719d37e4d37ce4472bb760d3eb1dc56385b97471256e
|
data/lib/candycane.rb
ADDED
@@ -0,0 +1,25 @@
|
|
1
|
+
module Candycane
|
2
|
+
def self.configure
|
3
|
+
yield configuration
|
4
|
+
end
|
5
|
+
|
6
|
+
def self.configuration
|
7
|
+
@@configuration ||= Candycane::Configuration.new
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
require 'active_model'
|
12
|
+
require 'active_support/core_ext'
|
13
|
+
|
14
|
+
require "candycane/configuration"
|
15
|
+
|
16
|
+
require "candycane/serializer"
|
17
|
+
require "candycane/serializer/json_serializer"
|
18
|
+
|
19
|
+
require "candycane/transport"
|
20
|
+
require "candycane/transport/wire"
|
21
|
+
|
22
|
+
require "candycane/local_method_call"
|
23
|
+
require "candycane/remote_method_call"
|
24
|
+
|
25
|
+
require "candycane/dsl"
|
@@ -0,0 +1,42 @@
|
|
1
|
+
class Candycane::Configuration
|
2
|
+
# THE THREE TENANTS OF CONFIGURATBILITY
|
3
|
+
# 1. DISCOVERY - how to find RPC servers
|
4
|
+
# 2. ENCODING - the transport protocol used encode a model
|
5
|
+
# 3. PROTOCOL - how an encoded message goes from point A to point B
|
6
|
+
#
|
7
|
+
# port is for servers to listen on
|
8
|
+
attr_writer :discover, :serializer, :transport, :port
|
9
|
+
|
10
|
+
def discover
|
11
|
+
@discover ||= ->(klass) do
|
12
|
+
# idk what to do here
|
13
|
+
# prolly yaml
|
14
|
+
#
|
15
|
+
# *sound of a beloved animal dying*
|
16
|
+
#
|
17
|
+
# yeah i can do better
|
18
|
+
#
|
19
|
+
# YAML, DNS and ZK
|
20
|
+
#
|
21
|
+
#
|
22
|
+
# hard coded to return local connection details:
|
23
|
+
{ host: "127.0.0.1", port: self.port }
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
def serializer
|
28
|
+
@serializer ||= Candycane::Serializer::JSONSerializer
|
29
|
+
end
|
30
|
+
|
31
|
+
def transport
|
32
|
+
@transport ||= Candycane::Transport::Wire
|
33
|
+
end
|
34
|
+
|
35
|
+
def port
|
36
|
+
@port ||= 6398
|
37
|
+
end
|
38
|
+
|
39
|
+
def discoveries
|
40
|
+
@discoveries ||= {}
|
41
|
+
end
|
42
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
class Candycane::DSL
|
2
|
+
|
3
|
+
def self.inherited(base)
|
4
|
+
base.send(:include, ActiveModel::Model)
|
5
|
+
base.send(:include, InstanceMethods)
|
6
|
+
end
|
7
|
+
|
8
|
+
module InstanceMethods
|
9
|
+
def attributes
|
10
|
+
self.class.candycane_attributes.inject({}) do |attrs, attr|
|
11
|
+
attrs.update(attr => self.send(attr))
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
class << self
|
17
|
+
def candycane_attributes
|
18
|
+
@@candycane_attributes ||= []
|
19
|
+
end
|
20
|
+
|
21
|
+
def attr(*attrs)
|
22
|
+
attr_accessor *attrs
|
23
|
+
(candycane_attributes << attrs).flatten!
|
24
|
+
end
|
25
|
+
|
26
|
+
def remote(method, &blk)
|
27
|
+
define_method(:"#{method}_locally", &blk)
|
28
|
+
|
29
|
+
define_method(method) do |*args|
|
30
|
+
Candycane::RemoteMethodCall.perform(self, method, args)
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
class Candycane::LocalMethodCall
|
2
|
+
def self.parse(message)
|
3
|
+
new Candycane.configuration.serializer.decode(message).symbolize_keys
|
4
|
+
end
|
5
|
+
|
6
|
+
attr_accessor :klass, :attributes, :method, :arguments
|
7
|
+
|
8
|
+
def initialize(klass:, attributes:, method:, arguments:)
|
9
|
+
@klass = klass.constantize
|
10
|
+
@attributes = attributes
|
11
|
+
@method = method
|
12
|
+
@arguments = arguments
|
13
|
+
end
|
14
|
+
|
15
|
+
def perform
|
16
|
+
result = klass.new(attributes).send(:"#{method}_locally", *arguments)
|
17
|
+
Candycane.configuration.serializer.encode success: true, result: result
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
class Candycane::RemoteMethodCall
|
2
|
+
def self.perform(instance, method, args)
|
3
|
+
new(instance, method, args).perform
|
4
|
+
end
|
5
|
+
|
6
|
+
def initialize(instance, method, args)
|
7
|
+
@instance = instance
|
8
|
+
@method = method
|
9
|
+
@args = args
|
10
|
+
end
|
11
|
+
|
12
|
+
def perform
|
13
|
+
remote_server = Candycane.configuration.discover.call klass
|
14
|
+
message = Candycane.configuration.serializer.encode \
|
15
|
+
klass: @instance.class.to_s,
|
16
|
+
attributes: @instance.attributes,
|
17
|
+
method: @method,
|
18
|
+
arguments: @args
|
19
|
+
|
20
|
+
response = Candycane.configuration.transport.client_for(remote_server).send message
|
21
|
+
result = Candycane.configuration.serializer.decode(response)
|
22
|
+
result["result"]
|
23
|
+
end
|
24
|
+
|
25
|
+
def klass
|
26
|
+
@instance.class
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,53 @@
|
|
1
|
+
class Candycane::Transport::Wire
|
2
|
+
# this is the simplest protocol going
|
3
|
+
# BUT
|
4
|
+
# you need to take into considerations
|
5
|
+
|
6
|
+
def self.client_for(remote_connection_details)
|
7
|
+
Client.new remote_connection_details
|
8
|
+
end
|
9
|
+
|
10
|
+
def self.server(port = Candycane.configuration.port)
|
11
|
+
Server.new(port)
|
12
|
+
end
|
13
|
+
|
14
|
+
class Client
|
15
|
+
attr_accessor :socket
|
16
|
+
|
17
|
+
def initialize(host:, port:)
|
18
|
+
@socket = TCPSocket.new host, port
|
19
|
+
end
|
20
|
+
|
21
|
+
def send(message)
|
22
|
+
socket.puts message
|
23
|
+
socket.gets
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
class Server
|
28
|
+
def initialize(port)
|
29
|
+
@server = TCPServer.new("0.0.0.0", port)
|
30
|
+
@quitting = false
|
31
|
+
end
|
32
|
+
|
33
|
+
def run
|
34
|
+
Signal.trap(:INT) { @quitting = true; }
|
35
|
+
|
36
|
+
loop do
|
37
|
+
accept
|
38
|
+
break if @quitting
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
def accept
|
43
|
+
socket = @server.accept
|
44
|
+
work socket
|
45
|
+
end
|
46
|
+
|
47
|
+
def work(socket)
|
48
|
+
message = socket.gets
|
49
|
+
socket.puts Candycane::LocalMethodCall.parse(message).perform
|
50
|
+
socket.close
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
metadata
ADDED
@@ -0,0 +1,96 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: candycane
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- "@rubynerd"
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2015-01-10 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: activesupport
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - '='
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: 4.2.0
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - '='
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: 4.2.0
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: activemodel
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - '='
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: 4.2.0
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - '='
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: 4.2.0
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: rspec
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - '='
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: 3.1.0
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - '='
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: 3.1.0
|
55
|
+
description: |
|
56
|
+
An incredibly basic RPC system for Ruby
|
57
|
+
email:
|
58
|
+
executables: []
|
59
|
+
extensions: []
|
60
|
+
extra_rdoc_files: []
|
61
|
+
files:
|
62
|
+
- "./lib/candycane.rb"
|
63
|
+
- "./lib/candycane/configuration.rb"
|
64
|
+
- "./lib/candycane/dsl.rb"
|
65
|
+
- "./lib/candycane/local_method_call.rb"
|
66
|
+
- "./lib/candycane/remote_method_call.rb"
|
67
|
+
- "./lib/candycane/serializer.rb"
|
68
|
+
- "./lib/candycane/serializer/json_serializer.rb"
|
69
|
+
- "./lib/candycane/transport.rb"
|
70
|
+
- "./lib/candycane/transport/wire.rb"
|
71
|
+
- "./lib/candycane/version.rb"
|
72
|
+
homepage:
|
73
|
+
licenses:
|
74
|
+
- MIT
|
75
|
+
metadata: {}
|
76
|
+
post_install_message:
|
77
|
+
rdoc_options: []
|
78
|
+
require_paths:
|
79
|
+
- lib
|
80
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
81
|
+
requirements:
|
82
|
+
- - ">="
|
83
|
+
- !ruby/object:Gem::Version
|
84
|
+
version: '0'
|
85
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - ">="
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '0'
|
90
|
+
requirements: []
|
91
|
+
rubyforge_project:
|
92
|
+
rubygems_version: 2.2.2
|
93
|
+
signing_key:
|
94
|
+
specification_version: 4
|
95
|
+
summary: Basic RPC
|
96
|
+
test_files: []
|