grenache-ruby-base 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 940e96c223f135df077f1e40ce1e9aa4e2aab82d
4
+ data.tar.gz: fdd57bdadb7de7783070736766730efdc183bc0b
5
+ SHA512:
6
+ metadata.gz: e0b91b5654d80d3ef65e50403b1baad9a4fe6d766706329f6b0bcc0f3fb562d14bee9fa8fd8de49786fd3d3019950b47bb37a54f9dfdcd31cd980776db21552b
7
+ data.tar.gz: 2f2ddd02c9aa8d0d0cd48482dcf20dfdca8243101d9b2d84d824afff2a5b1d330491d0cb8411d6b1b41a71611f5a35e11105cf35c33e1b207a9842bfd3e8740f
data/.gitignore ADDED
@@ -0,0 +1,9 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /Gemfile.lock
4
+ /_yardoc/
5
+ /coverage/
6
+ /doc/
7
+ /pkg/
8
+ /spec/reports/
9
+ /tmp/
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --format documentation
2
+ --color
data/Gemfile ADDED
@@ -0,0 +1,15 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gem "eventmachine", "~> 1.0.9"
4
+ gem "faye-websocket", "~> 0.10.3"
5
+ gem "oj", "~> 2.1.0"
6
+ gem "httpclient"
7
+ gem 'pry'
8
+
9
+
10
+ group :development do
11
+ gem "bundler", "~> 1.9"
12
+ gem "rake", "~> 10.0"
13
+ gem "rspec", "~> 3.1.0"
14
+ gem "simplecov", "~> 0.11.0"
15
+ end
data/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2011-2016 Twitter, Inc.
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,31 @@
1
+ # grenache-ruby-base
2
+
3
+ # Configuration
4
+
5
+ ```ruby
6
+ Grenache::Base.configure do |conf|
7
+ conf.grape_address = "ws://10.0.0.1:30002"
8
+ end
9
+ ```
10
+
11
+ # Usage
12
+
13
+ ## Announce a service
14
+
15
+ ```ruby
16
+ c = Grenache::Base.new
17
+
18
+ c.announce("test",30000) do |response|
19
+ #service code
20
+ puts "announce sent: #{response}"
21
+ end
22
+ ```
23
+
24
+
25
+ ## lookup for a service
26
+
27
+ ```ruby
28
+ c.lookup('test') do |response|
29
+ puts "services: #{response[1]}"
30
+ end
31
+ ```
@@ -0,0 +1,20 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'grenache/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "grenache-ruby-base"
8
+ spec.version = Grenache::VERSION
9
+ spec.email = ["info@bitfinex.com"]
10
+ spec.authors = "Bitfinex"
11
+
12
+ spec.summary = %q{Grenache Base Client implementation.}
13
+ spec.homepage = "https://github.com/bitfinexcom/grenache-ruby-base"
14
+ spec.license = "MIT"
15
+
16
+ spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
17
+ spec.require_paths = ["lib"]
18
+
19
+ # spec.add_bundler_dependencies
20
+ end
@@ -0,0 +1,48 @@
1
+ module Grenache
2
+ class Base
3
+ include Grenache::Configurable
4
+
5
+ # Lookup for a specific service `key`
6
+ # passed block is called with the result values
7
+ # in case of `http` backend it return the result directly
8
+ # @param key [string] identifier of the service
9
+ def lookup(key, opts={}, &block)
10
+ unless addr = cache.has?(key)
11
+ addr = link.send('lookup', key, opts, &block)
12
+ cache.save(key, addr)
13
+ end
14
+ addr
15
+ end
16
+
17
+ # Announce a specific service `key` available on specific `port`
18
+ # passed block is called when the announce is sent
19
+ # @param key [string] service identifier
20
+ # @param port [int] service port number
21
+ # @block callback
22
+ def announce(key, port, opts={}, &block)
23
+ payload = [key,port]
24
+ link.send 'announce', payload, opts, &block
25
+ if config.auto_announce
26
+ periodically(1) do
27
+ link.send 'announce', payload, opts, &block
28
+ end
29
+ end
30
+ end
31
+
32
+ private
33
+
34
+ def cache
35
+ @cache ||= Cache.new
36
+ end
37
+
38
+ def periodically(seconds)
39
+ EM.add_periodic_timer(seconds) do
40
+ yield
41
+ end
42
+ end
43
+
44
+ def link
45
+ @link ||= Link.new
46
+ end
47
+ end
48
+ end
@@ -0,0 +1,21 @@
1
+ module Grenache
2
+ class Cache
3
+
4
+ def initialize expiring=5
5
+ @cache = {}
6
+ @expiring = expiring
7
+ end
8
+
9
+ def has?(key)
10
+ if @cache.keys.include?(key) && @cache[key][:expire] >= Time.now
11
+ return @cache[key][:val]
12
+ end
13
+ end
14
+
15
+ def save(key, val)
16
+ @cache[key] = { val: val, expire: Time.now+@expiring }
17
+ val
18
+ end
19
+
20
+ end
21
+ end
@@ -0,0 +1,35 @@
1
+ module Grenache
2
+
3
+ # Encapsulate Configuration parameters
4
+ class Configuration
5
+ attr_accessor :grape_address, :auto_announce, :timeout
6
+
7
+ # Initialize default values
8
+ def initialize
9
+ self.grape_address = "ws://127.0.0.1:30001"
10
+ self.auto_announce = true
11
+ self.timeout = 5
12
+ end
13
+ end
14
+
15
+ # Configuration helpers
16
+ module Configurable
17
+ def self.included(base)
18
+ base.extend(ClassMethods)
19
+ end
20
+
21
+ def config
22
+ self.class.config
23
+ end
24
+
25
+ module ClassMethods
26
+ def configure
27
+ yield config
28
+ end
29
+
30
+ def config
31
+ @configuration ||= Configuration.new
32
+ end
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,93 @@
1
+ module Grenache
2
+ # Implement Grape connection helpers
3
+ class Link
4
+
5
+ # Connect to grape
6
+ def connect
7
+ unless connected?
8
+ ws_connect
9
+ end
10
+ end
11
+
12
+ # Return true if it's connected to Grape
13
+ def connected?
14
+ @connected
15
+ end
16
+
17
+ # Disconnect from grape
18
+ def disconnect
19
+ @ws.close
20
+ @ws = nil
21
+ end
22
+
23
+ # Send a message to grape
24
+ def send(type, payload, opts = {}, &block)
25
+ if http?
26
+ res = http_send type, Oj.dump({"rid" => 1234, "data" => payload})
27
+ block.call(res) if block
28
+ res
29
+ else
30
+ m = Message.new(type,payload,opts, &block)
31
+ messages[m.rid] = m
32
+ ws_send m.to_json
33
+ end
34
+ end
35
+
36
+ private
37
+
38
+ def messages
39
+ @messages ||= {}
40
+ end
41
+
42
+ def grape_url
43
+ @grape_url ||= Base.config.grape_address
44
+ end
45
+
46
+ def http?
47
+ grape_url.start_with? "http"
48
+ end
49
+
50
+ def ws_send(payload)
51
+ ws_connect unless connected?
52
+ @ws.send(payload)
53
+ end
54
+
55
+ def http_send(type, payload)
56
+ url = grape_url + type
57
+ res = http.post(url,payload).body
58
+ Oj.load(res)
59
+ end
60
+
61
+ def ws_connect
62
+ @ws = Faye::WebSocket::Client.new(grape_url)
63
+ @ws.on(:open, method(:on_open))
64
+ @ws.on(:message, method(:on_message))
65
+ @ws.on(:close, method(:on_close))
66
+ end
67
+
68
+ def on_open(ev)
69
+ @connected = true
70
+ end
71
+
72
+ def on_message(ev)
73
+ msg = Oj.load(ev.data)
74
+ if req = messages[msg[0]]
75
+ messages.delete(msg[0])
76
+ req.yield(msg[1]) if req.block_given?
77
+ end
78
+ end
79
+
80
+ def on_close(ev)
81
+ @connected = false
82
+ end
83
+
84
+ def http
85
+ @http |= HTTPClient.new do |c|
86
+ c.connect_timeout = Base.config.timeout
87
+ c.receive_timeout = Base.config.timeout
88
+ c.send_timeout = Base.config.timeout
89
+ c.keep_alive_timeout = Base.config.timeout
90
+ end
91
+ end
92
+ end
93
+ end
@@ -0,0 +1,40 @@
1
+
2
+ module Grenache
3
+
4
+ # Store a single request information
5
+ class Message
6
+ attr_accessor :payload, :type, :opts, :_ts
7
+
8
+ def initialize(type, payload, opts={}, &block)
9
+ @payload = payload
10
+ @type = type
11
+ @opts = opts
12
+ @_ts = Time.now
13
+ @block = block
14
+ end
15
+
16
+ def block_given?
17
+ !!@block
18
+ end
19
+
20
+ def yield(params={})
21
+ @block.call(params)
22
+ end
23
+
24
+ def rid
25
+ @rid ||= SecureRandom.uuid
26
+ end
27
+
28
+ def qhash
29
+ "#{type}#{dump_payload}"
30
+ end
31
+
32
+ def dump_payload
33
+ @dump_payload ||= Oj.dump(payload)
34
+ end
35
+
36
+ def to_json
37
+ Oj.dump([rid,type,payload])
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,47 @@
1
+ module Grenache
2
+
3
+ # Store a single request information
4
+ class Message
5
+ attr_accessor :payload, :type, :opts, :_ts
6
+
7
+ def initialize(type, payload, opts={}, &block)
8
+ @payload = payload
9
+ @type = type
10
+ @opts = opts
11
+ @_ts = Time.now
12
+ @block = block
13
+ end
14
+
15
+ def request?
16
+ @type == 'req'
17
+ end
18
+
19
+ def response?
20
+ @type == 'res'
21
+ end
22
+
23
+ def block_given?
24
+ !!@block
25
+ end
26
+
27
+ def yield(params={})
28
+ @block.call(params)
29
+ end
30
+
31
+ def rid
32
+ @rid ||= SecureRandom.uuid
33
+ end
34
+
35
+ def qhash
36
+ "#{type}#{dump_payload}"
37
+ end
38
+
39
+ def dump_payload
40
+ @dump_payload ||= Oj.dump(payload)
41
+ end
42
+
43
+ def to_json
44
+ Oj.dump([rid,type,payload])
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,3 @@
1
+ module Grenache
2
+ VERSION = '0.0.1'
3
+ end
@@ -0,0 +1,13 @@
1
+ require 'oj'
2
+ require 'eventmachine'
3
+ require 'faye/websocket'
4
+ require 'httpclient'
5
+ require 'pry'
6
+
7
+ require 'grenache/configurable'
8
+ require 'grenache/cache'
9
+ require 'grenache/base'
10
+ require 'grenache/version'
11
+ require 'grenache/link'
12
+ require 'grenache/request'
13
+
metadata ADDED
@@ -0,0 +1,59 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: grenache-ruby-base
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Bitfinex
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2016-07-28 00:00:00.000000000 Z
12
+ dependencies: []
13
+ description:
14
+ email:
15
+ - info@bitfinex.com
16
+ executables: []
17
+ extensions: []
18
+ extra_rdoc_files: []
19
+ files:
20
+ - ".gitignore"
21
+ - ".rspec"
22
+ - Gemfile
23
+ - LICENSE
24
+ - README.md
25
+ - grenache-ruby-base.gemspec
26
+ - lib/grenache-ruby-base.rb
27
+ - lib/grenache/base.rb
28
+ - lib/grenache/cache.rb
29
+ - lib/grenache/configurable.rb
30
+ - lib/grenache/link.rb
31
+ - lib/grenache/message.rb
32
+ - lib/grenache/request.rb
33
+ - lib/grenache/version.rb
34
+ homepage: https://github.com/bitfinexcom/grenache-ruby-base
35
+ licenses:
36
+ - MIT
37
+ metadata: {}
38
+ post_install_message:
39
+ rdoc_options: []
40
+ require_paths:
41
+ - lib
42
+ required_ruby_version: !ruby/object:Gem::Requirement
43
+ requirements:
44
+ - - ">="
45
+ - !ruby/object:Gem::Version
46
+ version: '0'
47
+ required_rubygems_version: !ruby/object:Gem::Requirement
48
+ requirements:
49
+ - - ">="
50
+ - !ruby/object:Gem::Version
51
+ version: '0'
52
+ requirements: []
53
+ rubyforge_project:
54
+ rubygems_version: 2.4.5
55
+ signing_key:
56
+ specification_version: 4
57
+ summary: Grenache Base Client implementation.
58
+ test_files: []
59
+ has_rdoc: