zoo-service-discovery 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,15 @@
1
+ ---
2
+ !binary "U0hBMQ==":
3
+ metadata.gz: !binary |-
4
+ ZmFlYTU1NDM4ODZkZThmMzllMWQxODVmM2I4ZmQ2YjEzYjc2NzEzYQ==
5
+ data.tar.gz: !binary |-
6
+ MDNlNGVhYmZhOGMxZjk4NWZmNmVlNzIxMWMyODcwN2JmZTZjNDUwMg==
7
+ !binary "U0hBNTEy":
8
+ metadata.gz: !binary |-
9
+ Y2RjZTg3ZWNkMDBmYjc4M2Q4YjRiZTg0NzkzNGM1OGMxN2Y0OTY2ODViNDc3
10
+ ODUyYjI2YTViMDMwYzcyMTA0MzdhN2VlZDFlMmE0OTMxNGNmNTgyMmQxZDcw
11
+ ZWE4ZTgxYmJiNmMzOGEzN2Q3YWJjYWNjNzdiNjU0YzQxNzkwMDU=
12
+ data.tar.gz: !binary |-
13
+ ZmI4Nzc3MzBmNzdiZjg5OThkYTdhMjIwMjk3YmU2OTA3ZTlhNzczZDgzNDcy
14
+ MWZkYmVjMDNmMGU0YjE1NmY4YTRhNDE3YzAwZTZkMWJmNDlhN2NhNDliZGU5
15
+ ZWMwOGU0NzgxMTNkNjg2OWIyYTM1MzAwYzA0OTkzN2M3MjQzNmQ=
data/README.md ADDED
@@ -0,0 +1,30 @@
1
+ # ZooKeeper Service Discovery
2
+
3
+ ZooKeeper service discovery gem.
4
+
5
+ You can use it to publish and discover well-known service URL's within your
6
+ application infrastructure.
7
+
8
+ ## Service Publication by a Service Provider
9
+
10
+ ```ruby
11
+ require 'zoo-service-discovery'
12
+
13
+ ZooService::Publication.register_service('service_name', 'http://api.service.com/')
14
+ ```
15
+
16
+ ## Service Lookup by a Service Consumer
17
+
18
+ ```ruby
19
+ require 'zoo-service-discovery'
20
+
21
+ base_service_url = ZooService::Discovery.get_service_url('service_name')
22
+ ```
23
+
24
+ ## Specs
25
+
26
+ RSpecs were developed and ran on a Mac OS X machine. They require ZooKeeper to
27
+ be installed locally (e.g. via Brew) and be available in the path.
28
+
29
+ More details on how the Zookeeper instances are started and torn down are in
30
+ the ```zookeeper_runner.rb``` RSpec support file.
@@ -0,0 +1,2 @@
1
+ require_relative 'zoo_service/discovery'
2
+ require_relative 'zoo_service/publication'
@@ -0,0 +1,45 @@
1
+ require 'zk'
2
+
3
+ # Service discovery facilities namespace.
4
+ module ZooService
5
+
6
+ # Performs service discovery for a HTTP service consumer.
7
+ class Discovery
8
+ class << self
9
+ # :call-seq:
10
+ # get_service_url(name) => String
11
+ #
12
+ # Gets service URL by _name_.
13
+ #
14
+ # Returns service URL, if everything went OK, +nil+ otherwise.
15
+ def get_service_url(name)
16
+ get_published_urls(name).first
17
+ end
18
+
19
+ protected
20
+
21
+ # Gets published URLs of _service_name_.
22
+ def get_published_urls(service_name)
23
+ service_path = "/services/#{service_name}"
24
+ publications = zk.children(service_path, ignore: :no_node) || [ ]
25
+
26
+ unless publications.empty?
27
+ zk.get("#{service_path}/#{publications.last}", ignore: :no_node)
28
+ else
29
+ [ ]
30
+ end
31
+ end
32
+
33
+ # Returns a working instance of a ZooKeeper client.
34
+ def zk
35
+ if Thread.current[:service_discovery_zk_client]
36
+ return Thread.current[:service_discovery_zk_client]
37
+ end
38
+
39
+ Thread.current[:service_discovery_zk_client] ||= ZK.new(ENV['SERVICE_DISCOVERY_WELLKNOWN_ADDRESS'] || 'localhost:2181')
40
+ end
41
+
42
+ end
43
+ end
44
+
45
+ end
@@ -0,0 +1,59 @@
1
+ require 'zk'
2
+
3
+ # Service discovery facilities namespace.
4
+ module ZooService
5
+
6
+ # Performs service publication for a HTTP service provider.
7
+ class Publication
8
+ class << self
9
+ # :call-seq:
10
+ # register_service(name, url) => Boolean
11
+ #
12
+ # Registers a well-known service with _name_ at _url_.
13
+ #
14
+ # Returns +true+, if everything went OK, +false+ otherwise.
15
+ def register_service(name, url)
16
+ registration_block = create_registration_block(name, url)
17
+ service_registration_blocks << registration_block
18
+ registration_block.(zk)
19
+ end
20
+
21
+ protected
22
+
23
+ # Creates a lambda that once called registeres the service on the URL.
24
+ def create_registration_block(name, url)
25
+ -> zk {
26
+ service_path = "/services/#{name}"
27
+ zk.mkdir_p(service_path) unless zk.exists?(service_path)
28
+ zk.create("#{service_path}/node-", url, mode: :ephemeral_sequential)
29
+ }
30
+ end
31
+
32
+ # Stores the registration blocks that are rerun after reconnection to
33
+ # the ZooKeeper.
34
+ def service_registration_blocks
35
+ @service_registration_blocks ||= [ ]
36
+ end
37
+
38
+ # Returns a working instance of a ZooKeeper client.
39
+ def zk
40
+ if Thread.current[:service_publication_zk_client]
41
+ return Thread.current[:service_publication_zk_client]
42
+ end
43
+
44
+ zk_client = ZK.new(ENV['SERVICE_DISCOVERY_WELLKNOWN_ADDRESS'] || 'localhost:2181') do |zk|
45
+ zk.on_connected do
46
+ # Rerun all the registrations upon reconnection
47
+ service_registration_blocks.each do |registration_block|
48
+ registration_block.(zk)
49
+ end
50
+ end
51
+ end
52
+
53
+ Thread.current[:service_publication_zk_client] = zk_client
54
+ end
55
+
56
+ end
57
+ end
58
+
59
+ end
@@ -0,0 +1,69 @@
1
+ require 'spec_helper'
2
+
3
+ describe "Discovered service URL (registered in a separate process)" do
4
+
5
+ def kill_server_process
6
+ begin
7
+ Process.kill("HUP", server_process)
8
+ Process.wait(server_process)
9
+ rescue Errno::ESRCH
10
+ # ignore
11
+ end
12
+ end
13
+
14
+ before {
15
+ if Thread.current[:service_discovery_zk_client]
16
+ Thread.current[:service_discovery_zk_client].close
17
+ Thread.current[:service_discovery_zk_client] = nil
18
+ end
19
+
20
+ if Thread.current[:service_publication_zk_client]
21
+ Thread.current[:service_publication_zk_client].close
22
+ Thread.current[:service_publication_zk_client] = nil
23
+ end
24
+ }
25
+
26
+ subject {
27
+ ZooService::Discovery.get_service_url(service)
28
+ }
29
+
30
+ let(:real_service_url) {
31
+ "http://sample.dev/"
32
+ }
33
+
34
+ let(:service) {
35
+ "service"
36
+ }
37
+
38
+ let!(:server_process) {
39
+ pid = fork do |variable|
40
+ ZooService::Publication.register_service(service, real_service_url)
41
+ sleep 1 while true
42
+ end
43
+ sleep 0.5
44
+ return pid
45
+ }
46
+
47
+ after do
48
+ kill_server_process
49
+ end
50
+
51
+ it { should == real_service_url }
52
+
53
+ it "should be nil after service owner termination" do
54
+ kill_server_process
55
+ sleep 30
56
+ should == nil
57
+ end
58
+
59
+ it "retains value when ZooKeeper fails and restarts with an empty DB" do
60
+ should == real_service_url
61
+
62
+ ZookeeperRunner.clean
63
+ ZookeeperRunner.stop
64
+ ZookeeperRunner.start
65
+
66
+ should == real_service_url
67
+ end
68
+
69
+ end
@@ -0,0 +1,40 @@
1
+ require 'spec_helper'
2
+
3
+ describe "Discovered service URL" do
4
+
5
+ subject {
6
+ ZooService::Discovery.get_service_url(service)
7
+ }
8
+
9
+ let(:real_service_url) {
10
+ "http://sample.dev/"
11
+ }
12
+
13
+ context "when service is registered" do
14
+
15
+ let!(:service) {
16
+ ZooService::Publication.register_service("service", real_service_url)
17
+ "service"
18
+ }
19
+
20
+ it { should == real_service_url }
21
+
22
+ it "should be nil if ZooKeeper gets cleaned somehow" do
23
+ # eh, eh, negative case ;) just to be sure
24
+ ZookeeperRunner.clean # clean the ZooKeeper
25
+ should == nil # check that it cannot be discovered
26
+ end
27
+
28
+ end
29
+
30
+ context "when service is not registered" do
31
+
32
+ let(:service) {
33
+ "service"
34
+ }
35
+
36
+ it { should == nil }
37
+
38
+ end
39
+
40
+ end
@@ -0,0 +1,34 @@
1
+ require 'bundler'
2
+ Bundler.require(:test)
3
+
4
+ require_relative "../lib/zoo_service/discovery"
5
+ require_relative "../lib/zoo_service/publication"
6
+
7
+ Dir[File.expand_path("../../spec/support/**/*.rb", __FILE__)].each { |f| require f }
8
+
9
+ RSpec.configure do |config|
10
+ config.treat_symbols_as_metadata_keys_with_true_values = true
11
+ config.run_all_when_everything_filtered = true
12
+ config.filter_run :focus
13
+
14
+ # Run specs in random order to surface order dependencies. If you find an
15
+ # order dependency and want to debug it, you can fix the order by providing
16
+ # the seed, which is printed after each run.
17
+ # --seed 1234
18
+ config.order = 'random'
19
+
20
+ config.before(:all) do
21
+ ZookeeperRunner.stop # ensure it's stopped
22
+ ZookeeperRunner.start
23
+ ZookeeperRunner.clean
24
+ end
25
+
26
+ config.after(:all) do
27
+ ZookeeperRunner.clean
28
+ ZookeeperRunner.stop
29
+ end
30
+
31
+ config.before do
32
+ ZookeeperRunner.clean
33
+ end
34
+ end
@@ -0,0 +1,36 @@
1
+ class ZookeeperRunner
2
+ class << self
3
+
4
+ def start
5
+ system "zkServer start > /dev/null 2>&1"
6
+ wait_zookeeper_start
7
+ end
8
+
9
+ def stop
10
+ system "zkServer stop > /dev/null 2>&1"
11
+ wait_zookeeper_stop
12
+ end
13
+
14
+ def clean
15
+ ZK.open('localhost:2181') do |zk|
16
+ zk.rm_rf('/services')
17
+ end
18
+ end
19
+
20
+ protected
21
+
22
+ def wait_zookeeper_start
23
+ sleep 1 while zookeeper_pid == 0
24
+ end
25
+
26
+ def wait_zookeeper_stop
27
+ sleep 0.125 while zookeeper_pid > 0
28
+ end
29
+
30
+ def zookeeper_pid
31
+ `ps aux | grep zookeeper | grep java | grep -v grep | awk '{ print $2; }'`.to_i
32
+ end
33
+
34
+
35
+ end
36
+ end
metadata ADDED
@@ -0,0 +1,52 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: zoo-service-discovery
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.0
5
+ platform: ruby
6
+ authors:
7
+ - Andrew Druzhinin <andrey.druginin@gmail.com>
8
+ - Ivan Kasatenko <sky@uniqsystems.ru>
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2013-09-23 00:00:00.000000000 Z
13
+ dependencies: []
14
+ description: ZooKeeper service discovery gem for your SOA environment.
15
+ email: support@uniqsystems.ru
16
+ executables: []
17
+ extensions: []
18
+ extra_rdoc_files: []
19
+ files:
20
+ - lib/zoo-service-discovery.rb
21
+ - lib/zoo_service/discovery.rb
22
+ - lib/zoo_service/publication.rb
23
+ - spec/features/complex_discovery_spec.rb
24
+ - spec/features/discovery_spec.rb
25
+ - spec/spec_helper.rb
26
+ - spec/support/zookeeper_runner.rb
27
+ - README.md
28
+ homepage: http://uniqsystems.ru/
29
+ licenses: []
30
+ metadata: {}
31
+ post_install_message:
32
+ rdoc_options: []
33
+ require_paths:
34
+ - lib
35
+ required_ruby_version: !ruby/object:Gem::Requirement
36
+ requirements:
37
+ - - ! '>='
38
+ - !ruby/object:Gem::Version
39
+ version: '0'
40
+ required_rubygems_version: !ruby/object:Gem::Requirement
41
+ requirements:
42
+ - - ! '>='
43
+ - !ruby/object:Gem::Version
44
+ version: '0'
45
+ requirements: []
46
+ rubyforge_project:
47
+ rubygems_version: 2.0.7
48
+ signing_key:
49
+ specification_version: 4
50
+ summary: ZooKeeper service discovery gem
51
+ test_files: []
52
+ has_rdoc: