backchat 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.
- data/.gitignore +18 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +22 -0
- data/README.md +72 -0
- data/Rakefile +8 -0
- data/backchat.gemspec +26 -0
- data/lib/backchat.rb +10 -0
- data/lib/backchat/connection_pool.rb +90 -0
- data/lib/backchat/version.rb +3 -0
- data/lib/java/smack.jar +0 -0
- data/lib/java/smackx.jar +0 -0
- data/test/lib/backchat/test_connection_pool.rb +124 -0
- data/test/test_helper.rb +10 -0
- metadata +145 -0
data/.gitignore
ADDED
data/Gemfile
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2013 Zach Pendleton
|
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,72 @@
|
|
1
|
+
# Backchat
|
2
|
+
|
3
|
+
Backchat is a JRuby-only gem that provides the
|
4
|
+
[Smack](http://www.igniterealtime.org/projects/smack/) XMPP libraries
|
5
|
+
and adds connection-pooling resources to them. It exists because there
|
6
|
+
are [no](https://github.com/ln/xmpp4r) [good](https://github.com/blaine/xmpp4r-simple)
|
7
|
+
[native](https://github.com/bryanwoods/babylon) XMPP libraries for Ruby.
|
8
|
+
|
9
|
+
## Installation
|
10
|
+
|
11
|
+
Add this line to your application's Gemfile:
|
12
|
+
|
13
|
+
gem 'backchat'
|
14
|
+
|
15
|
+
And then execute:
|
16
|
+
|
17
|
+
$ bundle
|
18
|
+
|
19
|
+
Or install it yourself as:
|
20
|
+
|
21
|
+
$ gem install backchat
|
22
|
+
|
23
|
+
## Usage
|
24
|
+
|
25
|
+
You'll need to require all of the Smack libraries you need inside your app with
|
26
|
+
the standard JRuby syntax:
|
27
|
+
|
28
|
+
```ruby
|
29
|
+
java_import 'org.jivesoftware.smacmx.muc.MultiUserChat'
|
30
|
+
java_import 'org.jivesoftware.smacmx.Form'
|
31
|
+
...
|
32
|
+
```
|
33
|
+
|
34
|
+
But you'll get connection pooling for free. Yay! Inside your app, configure
|
35
|
+
Backchat's pool in some kind of initializer:
|
36
|
+
|
37
|
+
```ruby
|
38
|
+
Backchat::ConnectionPool.configure do
|
39
|
+
host 'jabber.org'
|
40
|
+
username 'admin'
|
41
|
+
password 's3cr3t$@ren0fun'
|
42
|
+
pool_size: 5 # five connections is the default
|
43
|
+
end
|
44
|
+
|
45
|
+
# configure also accepts a hash
|
46
|
+
Backchat::ConnectionPool.configure(host: 'jabber.org', username: 'admin',
|
47
|
+
password: 's3cr3t$@ren0fun', pool_size: 5)
|
48
|
+
```
|
49
|
+
|
50
|
+
Once Backchat is configured, you can use the connection pool like magic:
|
51
|
+
|
52
|
+
```ruby
|
53
|
+
# connection_pool takes a block and passes it an XMPPConnection.
|
54
|
+
Backchat.connection_pool do |conn|
|
55
|
+
chat = MultiUserChat.new(conn, 'my-room@solonely.localhost')
|
56
|
+
chat.create('me')
|
57
|
+
end
|
58
|
+
```
|
59
|
+
|
60
|
+
The connection pool is created on the first call to `Backchat#connection_pool`,
|
61
|
+
provides authenticated connections, and blocks until a connection is available.
|
62
|
+
In the future it seems like it'd be nice to have a group of unauthenticated
|
63
|
+
connections so the pool could be used with multiple users, but my current use
|
64
|
+
case doesn't require it so it's missing in this version.
|
65
|
+
|
66
|
+
## Contributing
|
67
|
+
|
68
|
+
1. Fork it
|
69
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
70
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
71
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
72
|
+
5. Create new Pull Request
|
data/Rakefile
ADDED
data/backchat.gemspec
ADDED
@@ -0,0 +1,26 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'backchat/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = 'backchat'
|
8
|
+
spec.version = Backchat::VERSION
|
9
|
+
spec.authors = ['Zach Pendleton']
|
10
|
+
spec.email = ['zachpendleton@gmail.com']
|
11
|
+
spec.description = %q{Smack XMPP libraries for JRuby. With connection pooling!!}
|
12
|
+
spec.summary = %q{Include Smack XMPP libraries in JRuby and use them with connection pooling.}
|
13
|
+
spec.homepage = 'https://github.com/zachpendleton/backchat'
|
14
|
+
spec.license = 'MIT'
|
15
|
+
|
16
|
+
spec.files = `git ls-files`.split($/)
|
17
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
18
|
+
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
19
|
+
spec.require_paths = ['lib']
|
20
|
+
|
21
|
+
spec.add_development_dependency 'bundler', '~> 1.3'
|
22
|
+
spec.add_development_dependency 'minitest', '~> 4.6.2'
|
23
|
+
spec.add_development_dependency 'mocha', '~> 0.13.3'
|
24
|
+
spec.add_development_dependency 'pry'
|
25
|
+
spec.add_development_dependency 'rake', '>= 0.9.6'
|
26
|
+
end
|
data/lib/backchat.rb
ADDED
@@ -0,0 +1,10 @@
|
|
1
|
+
require 'java/smack'
|
2
|
+
require 'java/smackx'
|
3
|
+
java_import 'org.jivesoftware.smack.XMPPConnection'
|
4
|
+
java_import 'java.util.concurrent.ArrayBlockingQueue'
|
5
|
+
require 'backchat/connection_pool'
|
6
|
+
require 'backchat/version'
|
7
|
+
|
8
|
+
module Backchat
|
9
|
+
# Your code goes here...
|
10
|
+
end
|
@@ -0,0 +1,90 @@
|
|
1
|
+
module Backchat
|
2
|
+
class ConnectionPool
|
3
|
+
include Enumerable
|
4
|
+
|
5
|
+
DEFAULT_SETTINGS = {
|
6
|
+
host: 'localhost',
|
7
|
+
username: 'admin',
|
8
|
+
password: 'password',
|
9
|
+
pool_size: 5 }
|
10
|
+
|
11
|
+
@settings = DEFAULT_SETTINGS
|
12
|
+
|
13
|
+
def initialize(count = self.class.settings[:pool_size])
|
14
|
+
@queue = fill(ArrayBlockingQueue.new(count))
|
15
|
+
end
|
16
|
+
|
17
|
+
def each(&block)
|
18
|
+
queue.each(&block)
|
19
|
+
end
|
20
|
+
|
21
|
+
def take
|
22
|
+
queue.take
|
23
|
+
end
|
24
|
+
|
25
|
+
def add(connection)
|
26
|
+
queue.add(connection)
|
27
|
+
end
|
28
|
+
|
29
|
+
def with_connection
|
30
|
+
connection = take
|
31
|
+
yield connection
|
32
|
+
ensure
|
33
|
+
add(connection)
|
34
|
+
end
|
35
|
+
|
36
|
+
|
37
|
+
class << self
|
38
|
+
attr_reader :settings
|
39
|
+
|
40
|
+
def configure(settings = {}, &block)
|
41
|
+
if block_given?
|
42
|
+
instance_eval(&block)
|
43
|
+
else
|
44
|
+
@settings.merge!(settings)
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
def connection(credentials = {})
|
49
|
+
connection = XMPPConnection.new(settings[:host])
|
50
|
+
connection.connect
|
51
|
+
if (credentials.keys & [:username, :password]).count == 2
|
52
|
+
connection.login(*credentials.values_at(:username, :password))
|
53
|
+
end
|
54
|
+
|
55
|
+
yield connection
|
56
|
+
ensure
|
57
|
+
connection.disconnect
|
58
|
+
end
|
59
|
+
|
60
|
+
private
|
61
|
+
[:host, :username, :password, :pool_size].each do |key|
|
62
|
+
define_method("#{key}") do |val|
|
63
|
+
@settings ||= {}
|
64
|
+
@settings[key] = val
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
private
|
70
|
+
attr_reader :queue
|
71
|
+
|
72
|
+
def fill(queue)
|
73
|
+
while queue.remaining_capacity > 0
|
74
|
+
conn = XMPPConnection.new(self.class.settings[:host])
|
75
|
+
conn.connect
|
76
|
+
conn.login(self.class.settings[:username],
|
77
|
+
self.class.settings[:password], conn.connection_id)
|
78
|
+
|
79
|
+
queue.add(conn)
|
80
|
+
end
|
81
|
+
|
82
|
+
queue
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
def self.connection_pool(&block)
|
87
|
+
@connection_pool = ConnectionPool.new
|
88
|
+
block_given? ? @connection_pool.with_connection(&block) : @connection_pool
|
89
|
+
end
|
90
|
+
end
|
data/lib/java/smack.jar
ADDED
Binary file
|
data/lib/java/smackx.jar
ADDED
Binary file
|
@@ -0,0 +1,124 @@
|
|
1
|
+
require File.expand_path('../../test_helper', File.dirname(__FILE__))
|
2
|
+
|
3
|
+
class BackchatConnectionPoolTest < MiniTest::Unit::TestCase
|
4
|
+
def setup
|
5
|
+
XMPPConnection.any_instance.stubs(:connect).returns(nil)
|
6
|
+
XMPPConnection.any_instance.stubs(:login).returns(nil)
|
7
|
+
|
8
|
+
@pool = Backchat::ConnectionPool.new(5)
|
9
|
+
end
|
10
|
+
|
11
|
+
def test_configure_saves_settings_passed_in_a_block
|
12
|
+
Backchat::ConnectionPool.configure do
|
13
|
+
host 'example.com'
|
14
|
+
username 'don_draper'
|
15
|
+
password 'secret'
|
16
|
+
pool_size 1
|
17
|
+
end
|
18
|
+
|
19
|
+
assert_equal Backchat::ConnectionPool.settings, { host: 'example.com',
|
20
|
+
username: 'don_draper',
|
21
|
+
password: 'secret',
|
22
|
+
pool_size: 1 }
|
23
|
+
end
|
24
|
+
|
25
|
+
def test_configure_accepts_a_hash
|
26
|
+
Backchat::ConnectionPool.configure(host: 'example.com', username: 'don_draper',
|
27
|
+
password: 'secret', pool_size: 1)
|
28
|
+
|
29
|
+
assert_equal Backchat::ConnectionPool.settings, { host: 'example.com',
|
30
|
+
username: 'don_draper',
|
31
|
+
password: 'secret',
|
32
|
+
pool_size: 1 }
|
33
|
+
end
|
34
|
+
|
35
|
+
def test_configure_allows_partial_settings_in_a_block
|
36
|
+
Backchat::ConnectionPool.configure { host 'example.com' }
|
37
|
+
|
38
|
+
assert_equal Backchat::ConnectionPool.settings,
|
39
|
+
Backchat::ConnectionPool::DEFAULT_SETTINGS.merge(host: 'example.com')
|
40
|
+
end
|
41
|
+
|
42
|
+
def test_configure_allows_partial_settings_in_a_hash
|
43
|
+
Backchat::ConnectionPool.configure(host: 'example.com')
|
44
|
+
|
45
|
+
assert_equal Backchat::ConnectionPool.settings,
|
46
|
+
Backchat::ConnectionPool::DEFAULT_SETTINGS.merge(host: 'example.com')
|
47
|
+
end
|
48
|
+
|
49
|
+
def test_initialize_creates_a_queue
|
50
|
+
assert_includes @pool.instance_variables, :@queue
|
51
|
+
end
|
52
|
+
|
53
|
+
def test_queue_is_an_array_blocking_queue
|
54
|
+
assert_instance_of ArrayBlockingQueue, @pool.instance_variable_get(:@queue)
|
55
|
+
end
|
56
|
+
|
57
|
+
def test_initialize_fills_the_pool_with_connections
|
58
|
+
assert_equal 5, @pool.count
|
59
|
+
end
|
60
|
+
|
61
|
+
def test_initialize_fills_the_pool_with_the_number_of_connections_it_is_passed
|
62
|
+
assert_equal 1, Backchat::ConnectionPool.new(1).count
|
63
|
+
end
|
64
|
+
|
65
|
+
def test_initialize_connects_new_connections
|
66
|
+
XMPPConnection.any_instance.expects(:connect)
|
67
|
+
Backchat::ConnectionPool.new(1)
|
68
|
+
end
|
69
|
+
|
70
|
+
def test_initialize_authenticates_new_connections
|
71
|
+
XMPPConnection.any_instance.expects(:login)
|
72
|
+
Backchat::ConnectionPool.new(1)
|
73
|
+
end
|
74
|
+
|
75
|
+
def test_take_removes_a_connection_from_the_queue
|
76
|
+
@pool.take
|
77
|
+
assert_equal 4, @pool.count
|
78
|
+
end
|
79
|
+
|
80
|
+
def test_add_adds_a_connection_to_the_queue
|
81
|
+
conn = @pool.take
|
82
|
+
@pool.add(conn)
|
83
|
+
|
84
|
+
assert_equal 5, @pool.count
|
85
|
+
end
|
86
|
+
|
87
|
+
def test_with_connection_yields_a_block_with_a_connection
|
88
|
+
@pool.with_connection do |conn|
|
89
|
+
assert_instance_of XMPPConnection, conn
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
def test_with_connection_removes_a_connection_from_the_pool_and_returns_it
|
94
|
+
@pool.with_connection do |conn|
|
95
|
+
assert_equal 4, @pool.count
|
96
|
+
end
|
97
|
+
|
98
|
+
assert_equal 5, @pool.count
|
99
|
+
end
|
100
|
+
|
101
|
+
def test_with_connection_ensures_that_a_connection_is_returned_to_the_pool
|
102
|
+
@pool.with_connection { |conn| raise 'Error' }
|
103
|
+
rescue
|
104
|
+
assert_equal 5, @pool.count
|
105
|
+
end
|
106
|
+
|
107
|
+
def test_connection_yields_with_an_unauthenticated_connection
|
108
|
+
XMPPConnection.any_instance.expects(:login).never
|
109
|
+
|
110
|
+
Backchat::ConnectionPool.connection { |conn| }
|
111
|
+
end
|
112
|
+
|
113
|
+
def test_connection_accepts_credentials
|
114
|
+
XMPPConnection.any_instance.expects(:login)
|
115
|
+
|
116
|
+
Backchat::ConnectionPool.connection(username: 'don_draper',
|
117
|
+
password: 'secret') { |conn| }
|
118
|
+
end
|
119
|
+
|
120
|
+
def test_backchat_connection_pool_creates_a_pool
|
121
|
+
refute Backchat.instance_variable_get(:@connection_pool)
|
122
|
+
assert_instance_of Backchat::ConnectionPool, Backchat.connection_pool
|
123
|
+
end
|
124
|
+
end
|
data/test/test_helper.rb
ADDED
metadata
ADDED
@@ -0,0 +1,145 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: backchat
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
prerelease:
|
5
|
+
version: 0.0.1
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Zach Pendleton
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2013-03-14 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: bundler
|
16
|
+
version_requirements: !ruby/object:Gem::Requirement
|
17
|
+
requirements:
|
18
|
+
- - "~>"
|
19
|
+
- !ruby/object:Gem::Version
|
20
|
+
version: '1.3'
|
21
|
+
none: false
|
22
|
+
requirement: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '1.3'
|
27
|
+
none: false
|
28
|
+
prerelease: false
|
29
|
+
type: :development
|
30
|
+
- !ruby/object:Gem::Dependency
|
31
|
+
name: minitest
|
32
|
+
version_requirements: !ruby/object:Gem::Requirement
|
33
|
+
requirements:
|
34
|
+
- - "~>"
|
35
|
+
- !ruby/object:Gem::Version
|
36
|
+
version: 4.6.2
|
37
|
+
none: false
|
38
|
+
requirement: !ruby/object:Gem::Requirement
|
39
|
+
requirements:
|
40
|
+
- - "~>"
|
41
|
+
- !ruby/object:Gem::Version
|
42
|
+
version: 4.6.2
|
43
|
+
none: false
|
44
|
+
prerelease: false
|
45
|
+
type: :development
|
46
|
+
- !ruby/object:Gem::Dependency
|
47
|
+
name: mocha
|
48
|
+
version_requirements: !ruby/object:Gem::Requirement
|
49
|
+
requirements:
|
50
|
+
- - "~>"
|
51
|
+
- !ruby/object:Gem::Version
|
52
|
+
version: 0.13.3
|
53
|
+
none: false
|
54
|
+
requirement: !ruby/object:Gem::Requirement
|
55
|
+
requirements:
|
56
|
+
- - "~>"
|
57
|
+
- !ruby/object:Gem::Version
|
58
|
+
version: 0.13.3
|
59
|
+
none: false
|
60
|
+
prerelease: false
|
61
|
+
type: :development
|
62
|
+
- !ruby/object:Gem::Dependency
|
63
|
+
name: pry
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - ">="
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: !binary |-
|
69
|
+
MA==
|
70
|
+
none: false
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - ">="
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: !binary |-
|
76
|
+
MA==
|
77
|
+
none: false
|
78
|
+
prerelease: false
|
79
|
+
type: :development
|
80
|
+
- !ruby/object:Gem::Dependency
|
81
|
+
name: rake
|
82
|
+
version_requirements: !ruby/object:Gem::Requirement
|
83
|
+
requirements:
|
84
|
+
- - ">="
|
85
|
+
- !ruby/object:Gem::Version
|
86
|
+
version: 0.9.6
|
87
|
+
none: false
|
88
|
+
requirement: !ruby/object:Gem::Requirement
|
89
|
+
requirements:
|
90
|
+
- - ">="
|
91
|
+
- !ruby/object:Gem::Version
|
92
|
+
version: 0.9.6
|
93
|
+
none: false
|
94
|
+
prerelease: false
|
95
|
+
type: :development
|
96
|
+
description: Smack XMPP libraries for JRuby. With connection pooling!!
|
97
|
+
email:
|
98
|
+
- zachpendleton@gmail.com
|
99
|
+
executables: []
|
100
|
+
extensions: []
|
101
|
+
extra_rdoc_files: []
|
102
|
+
files:
|
103
|
+
- ".gitignore"
|
104
|
+
- Gemfile
|
105
|
+
- LICENSE.txt
|
106
|
+
- README.md
|
107
|
+
- Rakefile
|
108
|
+
- backchat.gemspec
|
109
|
+
- lib/backchat.rb
|
110
|
+
- lib/backchat/connection_pool.rb
|
111
|
+
- lib/backchat/version.rb
|
112
|
+
- lib/java/smack.jar
|
113
|
+
- lib/java/smackx.jar
|
114
|
+
- test/lib/backchat/test_connection_pool.rb
|
115
|
+
- test/test_helper.rb
|
116
|
+
homepage: https://github.com/zachpendleton/backchat
|
117
|
+
licenses:
|
118
|
+
- MIT
|
119
|
+
post_install_message:
|
120
|
+
rdoc_options: []
|
121
|
+
require_paths:
|
122
|
+
- lib
|
123
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
124
|
+
requirements:
|
125
|
+
- - ">="
|
126
|
+
- !ruby/object:Gem::Version
|
127
|
+
version: !binary |-
|
128
|
+
MA==
|
129
|
+
none: false
|
130
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
131
|
+
requirements:
|
132
|
+
- - ">="
|
133
|
+
- !ruby/object:Gem::Version
|
134
|
+
version: !binary |-
|
135
|
+
MA==
|
136
|
+
none: false
|
137
|
+
requirements: []
|
138
|
+
rubyforge_project:
|
139
|
+
rubygems_version: 1.8.24
|
140
|
+
signing_key:
|
141
|
+
specification_version: 3
|
142
|
+
summary: Include Smack XMPP libraries in JRuby and use them with connection pooling.
|
143
|
+
test_files:
|
144
|
+
- test/lib/backchat/test_connection_pool.rb
|
145
|
+
- test/test_helper.rb
|