grenache-ruby-base 0.0.1

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 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: