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.
@@ -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
@@ -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,2 @@
1
+ module Candycane::Serializer
2
+ end
@@ -0,0 +1,11 @@
1
+ require 'json'
2
+
3
+ class Candycane::Serializer::JSONSerializer
4
+ def self.encode(message)
5
+ JSON.generate message
6
+ end
7
+
8
+ def self.decode(message)
9
+ JSON.parse message
10
+ end
11
+ end
@@ -0,0 +1,2 @@
1
+ module Candycane::Transport
2
+ 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
@@ -0,0 +1,3 @@
1
+ module Candycane
2
+ VERSION = '0.1.0'
3
+ 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: []