ddp-server-rethinkdb 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: e76f372523591456e078fd95a1b774137318b4a7
4
+ data.tar.gz: df3499b899d0cd315704883d9068642fd8b18363
5
+ SHA512:
6
+ metadata.gz: 2d52b581d92141b06b7925f8b9c326c9ebd3369754f4d3e83ad62a309ba756dc7459cb27e4e2a14fec2e2b3497f058f18ba31b8a51fb116d868defbd12a26e6d
7
+ data.tar.gz: 4d38b31aa154245f0088f765cf351944ce4c7214e0cb8b7cf0687c1d50ac883af7be5c8b3344f08dc6d650408e7e3e2ae882c47df5d0a168a6bf169ddcd15b0c
data/.gitignore ADDED
@@ -0,0 +1,22 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
18
+ *.bundle
19
+ *.so
20
+ *.o
21
+ *.a
22
+ mkmf.log
data/.rubocop.yml ADDED
@@ -0,0 +1,10 @@
1
+ Style/Tab:
2
+ Enabled: false
3
+ Style/IndentationWidth:
4
+ Width: 1
5
+ Metrics/LineLength:
6
+ Max: 120
7
+ Style/SignalException:
8
+ Enabled: false
9
+ Metrics/AbcSize:
10
+ Max: 18
data/Gemfile ADDED
@@ -0,0 +1,11 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gem 'guard'
4
+ gem 'guard-rspec'
5
+ gem 'guard-rubocop'
6
+ gem 'guard-cucumber'
7
+ gem 'rubocop'
8
+ gem 'rspec'
9
+
10
+ # Specify your gem's dependencies in ddp-server-rethinkdb.gemspec
11
+ gemspec
data/Guardfile ADDED
@@ -0,0 +1,30 @@
1
+ # A sample Guardfile
2
+ # More info at https://github.com/guard/guard#readme
3
+
4
+ # Note: The cmd option is now required due to the increasing number of ways
5
+ # rspec may be run, below are examples of the most common uses.
6
+ # * bundler: 'bundle exec rspec'
7
+ # * bundler binstubs: 'bin/rspec'
8
+ # * spring: 'bin/rsspec' (This will use spring if running and you have
9
+ # installed the spring binstubs per the docs)
10
+ # * zeus: 'zeus rspec' (requires the server to be started separetly)
11
+ # * 'just' rspec: 'rspec'
12
+ guard :rspec, cmd: 'bundle exec rspec -c' do
13
+ watch(/^spec\/.+_spec\.rb$/) { 'spec' }
14
+ watch(/^lib\/.+\.rb$/) { 'spec' }
15
+ watch('spec/spec_helper.rb') { 'spec' }
16
+ end
17
+
18
+ guard :rubocop do
19
+ watch(/.+\.rb$/)
20
+ watch(/(?:.+\/)?\.rubocop\.yml$/) { |m| File.dirname(m[0]) }
21
+ end
22
+
23
+ guard 'cucumber' do
24
+ watch(/^features\/.+\.feature$/)
25
+ watch(%r{^features\/support\/.+$}) { 'features' }
26
+
27
+ watch(%r{^features/step_definitions/(.+)_steps\.rb$}) do |m|
28
+ Dir[File.join("**/#{m[1]}.feature")][0] || 'features'
29
+ end
30
+ end
data/LICENSE.txt ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2015 Tinco Andringa
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,65 @@
1
+ # DDP::Server::RethinkDB
2
+
3
+ So the idea of this is that you can create a class that exposes an interface to your RethinkDB collections and have it be served over DDP.
4
+
5
+ Ideally it would look something like this:
6
+
7
+ ```
8
+ require 'ddp/server/rethinkdb'
9
+
10
+ class Messager < DDP::Server::RethinkDB::API
11
+ include Celluloid::Logger
12
+
13
+ module Collections
14
+ def messages
15
+ table('messages')
16
+ end
17
+ end
18
+
19
+ def name
20
+ @name ||= "Guest#{rand(10..100)}"
21
+ end
22
+
23
+ def send_message(message)
24
+ with_connection do |conn|
25
+ table('messages').insert(from: name, message: message).run(conn)
26
+ end
27
+ end
28
+ end
29
+
30
+ config = {
31
+ connection_pool_size: 8,
32
+ connection_pool_timeout: 5,
33
+ host: 'localhost',
34
+ port: 28_015,
35
+ database: 'message'
36
+ }
37
+
38
+ run DDP::Server::RethinkDB::WebSocket.rack(Messager, config)
39
+ ```
40
+
41
+ ## Installation
42
+
43
+ Add this line to your application's Gemfile:
44
+
45
+ gem 'ddp-server-rethinkdb'
46
+
47
+ And then execute:
48
+
49
+ $ bundle
50
+
51
+ Or install it yourself as:
52
+
53
+ $ gem install ddp-server-rethinkdb
54
+
55
+ ## Usage
56
+
57
+ TODO: Write usage instructions here
58
+
59
+ ## Contributing
60
+
61
+ 1. Fork it ( https://github.com/[my-github-username]/ddp-server-rethinkdb/fork )
62
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
63
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
64
+ 4. Push to the branch (`git push origin my-new-feature`)
65
+ 5. Create a new Pull Request
data/Rakefile ADDED
@@ -0,0 +1 @@
1
+ require 'bundler/gem_tasks'
@@ -0,0 +1,27 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'ddp/server/rethinkdb/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = 'ddp-server-rethinkdb'
8
+ spec.version = DDP::Server::RethinkDB::VERSION
9
+ spec.authors = ['Tinco Andringa']
10
+ spec.email = ['mail@tinco.nl']
11
+ spec.summary = 'Write a DDP RethinkDB service using Ruby.'
12
+ spec.description = 'Write a DDP RethinkDB service using Ruby.'
13
+ spec.homepage = 'https://github.com/d-snp/ruby-ddp-server-rethinkdb'
14
+ spec.license = 'MIT'
15
+
16
+ spec.files = `git ls-files -z`.split("\x0")
17
+ spec.executables = spec.files.grep(/^bin\//) { |f| File.basename(f) }
18
+ spec.test_files = spec.files.grep(/^(test|spec|features)\//)
19
+ spec.require_paths = ['lib']
20
+
21
+ spec.add_development_dependency 'bundler', '~> 1.6'
22
+ spec.add_development_dependency 'rake'
23
+
24
+ spec.add_dependency 'ddp-server', '>= 0.0.3'
25
+ spec.add_dependency 'rethinkdb'
26
+ spec.add_dependency 'connection_pool'
27
+ end
@@ -0,0 +1,31 @@
1
+ require 'ddp/server/rethinkdb'
2
+
3
+ class Messager < DDP::Server::RethinkDB::API
4
+ include Celluloid::Logger
5
+
6
+ module Collections
7
+ def messages
8
+ table('messages')
9
+ end
10
+ end
11
+
12
+ def name
13
+ @name ||= "Guest#{rand(10..100)}"
14
+ end
15
+
16
+ def send_message(message)
17
+ with_connection do |conn|
18
+ table('messages').insert(from: name, message: message).run(conn)
19
+ end
20
+ end
21
+ end
22
+
23
+ config = {
24
+ connection_pool_size: 8,
25
+ connection_pool_timeout: 5,
26
+ host: 'localhost',
27
+ port: 28_015,
28
+ database: 'message'
29
+ }
30
+
31
+ run DDP::Server::RethinkDB::WebSocket.rack(Messager, config)
@@ -0,0 +1,8 @@
1
+ module DDP
2
+ module Server
3
+ # Include the version
4
+ module RethinkDB
5
+ VERSION = '0.0.1'
6
+ end
7
+ end
8
+ end
@@ -0,0 +1,125 @@
1
+ require 'ddp/server'
2
+ require 'ddp/server/rethinkdb/version'
3
+ require 'rethinkdb'
4
+ require 'connection_pool'
5
+
6
+ module DDP
7
+ module Server
8
+ # A RethinkDB DDP Server
9
+ module RethinkDB
10
+ # Implementation of the WebSocket DDP::Server
11
+ class WebSocket < DDP::Server::WebSocket
12
+ include Celluloid::Logger
13
+
14
+ attr_reader :api
15
+
16
+ def self.rack(api, config, pool_config={})
17
+ super(pool_config.merge(args: [api, config]))
18
+ end
19
+
20
+ def initialize(api_class, config)
21
+ collections_module = api_class.const_get :Collections
22
+ @collections = collections_module.instance_methods.map(&:to_s)
23
+ @api = api_class.new(config)
24
+ @api.singleton_class.include collections_module
25
+ @subscriptions = {}
26
+ end
27
+
28
+ def handle_sub(id, name, params)
29
+ params ||= []
30
+ return send_nosub(id, error: 'No such collection') unless @collections.include? name
31
+ query = api.send(name, *params)
32
+ @subscriptions[id] = Subscription.new(self, id, name, query)
33
+ end
34
+
35
+ def subscription_update(id, change)
36
+ subscription_name = @subscriptions[id].name
37
+ old_value = change['old_val']
38
+ new_value = change['new_val']
39
+
40
+ return send_added(subscription_name, new_value['id'], new_value) if old_value.nil?
41
+ return send_removed(subscription_name, old_value['id']) if new_value.nil?
42
+
43
+ cleared = old_value.keys.reject { |key| new_value.include? key }
44
+ send_changed(subscription.name, old_value['id'], new_value, cleared)
45
+ end
46
+
47
+ def handle_unsub(id)
48
+ subscription = @subscriptions.delete(id)
49
+ subscription.stop unless subscription.nil?
50
+ send_nosub(id)
51
+ end
52
+
53
+ def handle_method(id, method, params)
54
+ params ||= []
55
+ result = @api.send(method, *params)
56
+ send_result(id, result)
57
+ rescue => e
58
+ send_error_result(id, e)
59
+ end
60
+ end
61
+
62
+ # Helper class that users can extend to implement an API that can be passed
63
+ # as the RPC API parameter to the RethinkDB DDP protocol
64
+ class API
65
+ def initialize(config)
66
+ @connection_pool = ConnectionPool.new(
67
+ size: config[:connection_pool_size],
68
+ timeout: config[:connection_pool_timeout]
69
+ ) do
70
+ ::RethinkDB::Connection.new(
71
+ host: config[:host],
72
+ port: config[:port]
73
+ )
74
+ end
75
+ @database_name = config[:database]
76
+ end
77
+
78
+ def database
79
+ ::RethinkDB::RQL.new.db(@database_name)
80
+ end
81
+
82
+ def table(name)
83
+ database.table(name)
84
+ end
85
+
86
+ def with_connection
87
+ @connection_pool.with do |conn|
88
+ yield conn
89
+ end
90
+ end
91
+ end
92
+
93
+ # Actor that asynchronously monitors a collection
94
+ class Subscription
95
+ include Celluloid
96
+ include Celluloid::Logger
97
+
98
+ attr_reader :name, :stopped
99
+
100
+ def initialize(listener, id, name, query)
101
+ @stopped = false
102
+ @name = name
103
+ async.read_loop(listener, query, id)
104
+ end
105
+
106
+ def read_loop(listener, query, id)
107
+ listener.api.with_connection do |conn|
108
+ query.changes.run(conn).each do |change|
109
+ listener.subscription_update(id, change)
110
+ break if stopped?
111
+ end
112
+ end
113
+ end
114
+
115
+ def stop
116
+ @stopped = true
117
+ end
118
+
119
+ def stopped?
120
+ @stopped
121
+ end
122
+ end
123
+ end
124
+ end
125
+ end
metadata ADDED
@@ -0,0 +1,125 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: ddp-server-rethinkdb
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Tinco Andringa
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2015-02-19 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '1.6'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '1.6'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: ddp-server
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: 0.0.3
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: 0.0.3
55
+ - !ruby/object:Gem::Dependency
56
+ name: rethinkdb
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :runtime
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: connection_pool
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :runtime
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
83
+ description: Write a DDP RethinkDB service using Ruby.
84
+ email:
85
+ - mail@tinco.nl
86
+ executables: []
87
+ extensions: []
88
+ extra_rdoc_files: []
89
+ files:
90
+ - ".gitignore"
91
+ - ".rubocop.yml"
92
+ - Gemfile
93
+ - Guardfile
94
+ - LICENSE.txt
95
+ - README.md
96
+ - Rakefile
97
+ - ddp-server-rethinkdb.gemspec
98
+ - examples/messages.rb
99
+ - lib/ddp/server/rethinkdb.rb
100
+ - lib/ddp/server/rethinkdb/version.rb
101
+ homepage: https://github.com/d-snp/ruby-ddp-server-rethinkdb
102
+ licenses:
103
+ - MIT
104
+ metadata: {}
105
+ post_install_message:
106
+ rdoc_options: []
107
+ require_paths:
108
+ - lib
109
+ required_ruby_version: !ruby/object:Gem::Requirement
110
+ requirements:
111
+ - - ">="
112
+ - !ruby/object:Gem::Version
113
+ version: '0'
114
+ required_rubygems_version: !ruby/object:Gem::Requirement
115
+ requirements:
116
+ - - ">="
117
+ - !ruby/object:Gem::Version
118
+ version: '0'
119
+ requirements: []
120
+ rubyforge_project:
121
+ rubygems_version: 2.2.2
122
+ signing_key:
123
+ specification_version: 4
124
+ summary: Write a DDP RethinkDB service using Ruby.
125
+ test_files: []