swarmclient 0.1.3 → 0.1.4

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 78b0081e269fca254447d15622cf08ecfa779e17
4
- data.tar.gz: '001971af13049e326c9c8bd9096bd5cb40b496a7'
3
+ metadata.gz: 99f80ba44aa24f9ee3eb4e9ce141e3ecf63e3f94
4
+ data.tar.gz: 4d428173cc0aa564f57f4022ad50d5f72308764b
5
5
  SHA512:
6
- metadata.gz: 8021ab7bb29ed5791e95d9850c79cd445a517fd63bdf7ad1673d5e2d8d2a79cf3ebab766098861ee5c51330a494a2242a96aa06714a0581b0f9dddb1e3952e72
7
- data.tar.gz: a6eea143378cfb711ad48c80e4d090e7f03788260fbf9959484a01c5f790272492ccd0f3b68abf4ea0b38ec454ea160d15b9786cdcd3710d69aae2541caf79e0
6
+ metadata.gz: b330011864610edf645f0f2694783726f0247b5f9a79b31ff18f742a434d0b0a9d1f85417330aa5e6e56d41945c6d3c67c9237943a52f943b39f76a68c7a3fbb
7
+ data.tar.gz: e42427944c2c2f0b88574efe20f07eb9edadd567e3e7918c65db318a46f819641ee323578bbe02f0e48cf3ad7f3aa5fcc475f19767abe297eaec432e6f49c4ca
data/.gitignore CHANGED
@@ -7,6 +7,7 @@
7
7
  /spec/reports/
8
8
  /tmp/
9
9
  *.gem
10
+ .idea
10
11
 
11
12
  # rspec failure tracking
12
13
  .rspec_status
data/.gitmodules ADDED
@@ -0,0 +1,4 @@
1
+ [submodule "proto"]
2
+ path = proto
3
+ url = https://github.com/bluzelle/swarmdb
4
+ branch = devel
data/.travis.yml CHANGED
@@ -1,7 +1,23 @@
1
1
  sudo: false
2
2
  language: ruby
3
+
4
+ addons:
5
+ apt:
6
+ sources:
7
+ - ubuntu-toolchain-r-test
8
+ - sourceline: 'deb http://ppa.launchpad.net/maarten-fonville/protobuf/ubuntu trusty main'
9
+ packages:
10
+ - protobuf-compiler
11
+
12
+ before_install:
13
+ # Uncommented until issue is resolved: https://github.com/google/protobuf/issues/4852
14
+ # - mkdir -p lib/swarmclient/protobuf
15
+ # - protoc --ruby_out=lib/swarmclient/protobuf --proto_path=proto/proto bluzelle.proto database.proto audit.proto
16
+ - gem install bundler -v 1.16.0
17
+
18
+
3
19
  rvm:
4
20
  - 2.4.2
21
+
5
22
  script:
6
- - bundle exec rake spec
7
- before_install: gem install bundler -v 1.16.0
23
+ - bundle exec rake spec
data/README.md CHANGED
@@ -2,6 +2,8 @@
2
2
 
3
3
  [![Build Status](https://api.travis-ci.org/wlwanpan/swarmclient-rb.png?branch=master)](https://travis-ci.org/wlwanpan/swarmclient-rb)
4
4
  [![License](https://img.shields.io/badge/License-Apache%202.0-blue.svg)](https://opensource.org/licenses/Apache-2.0)
5
+ [![Twitter](https://img.shields.io/badge/twitter-@bluzelle-blue.svg?style=flat-square)](https://twitter.com/BluzelleHQ)
6
+ [![Gitter chat](https://img.shields.io/gitter/room/nwjs/nw.js.svg?style=flat-square)](https://gitter.im/bluzelle)
5
7
 
6
8
  ## Installation
7
9
 
@@ -25,68 +27,83 @@ Or build and install from src:
25
27
  ## Communication API (Swarmclient::Communication)
26
28
 
27
29
  Require and Initialize
28
- ```
30
+ ```ruby
29
31
  require 'swarmclient'
30
32
 
31
33
  bluzelle = Swarmclient::Communication.new endpoint: '127.0.0.1', port: 51010, uuid: '80174b53-2dda-49f1-9d6a-6a780d4'
32
34
  ```
33
35
 
34
36
  Note: The uuid is the unique id of a referenced db hosted in the swarm.
35
- Generate a new one to generate a new store. The gem will default to:
36
- '8c073d96-7291-11e8-adc0-fa7ae01bbebc' if none is provided.
37
- Refer to https://bluzelle.github.io/api/ for more info.
37
+ Generate a new one to generate a new database. The gem will default to:
38
+ "8c073d96-7291-11e8-adc0-fa7ae01bbebc" if none is provided.
38
39
 
39
40
  Create New Entry (key-value)
40
- ```
41
+ ```ruby
41
42
  bluzelle.create 'myKey', 'Your Value'
42
43
  ```
44
+ - Result
45
+ ```ruby
46
+ => true
47
+ ```
43
48
 
44
49
  Read Key
45
- ```
50
+ ```ruby
46
51
  bluzelle.read 'myKey'
47
52
  ```
48
53
  - Result
49
- ```
54
+ ```ruby
50
55
  => "Your Value"
51
56
  ```
52
57
 
53
58
  Update Key value
54
- ```
59
+ ```ruby
55
60
  bluzelle.update 'myKey', 'New Value'
56
61
  ```
62
+ - Result
63
+ ```ruby
64
+ => true
65
+ ```
57
66
 
58
67
  Remove Key
59
- ```
68
+ ```ruby
60
69
  bluzelle.remove 'myKey'
61
70
  ```
71
+ - Result
72
+ ```ruby
73
+ => true
74
+ ```
62
75
 
63
76
  Check if key exist
64
- ```
77
+ ```ruby
65
78
  bluzelle.has 'myKey'
66
79
  ```
67
80
  - Result
68
- ```
81
+ ```ruby
69
82
  => true
70
83
  ```
71
84
 
72
85
  Read all keys stored
73
- ```
86
+ ```ruby
74
87
  bluzelle.keys
75
88
  ```
76
89
  - Result
77
- ```
78
- => ["myKey1"]
90
+ ```ruby
91
+ => ["myKey"]
79
92
  ```
80
93
 
81
94
  Get size of database
82
- ```
95
+ ```ruby
83
96
  bluzelle.size
84
97
  ```
85
98
  - Result
86
- ```
99
+ ```ruby
87
100
  => 1
88
101
  ```
89
102
 
103
+ ## Reference
104
+
105
+ Visit the official bluzelle [documentation](https://bluzelle.github.io/api/)
106
+
90
107
  ## Development
91
108
 
92
109
  After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
@@ -1,23 +1,15 @@
1
- require 'google/protobuf'
2
1
  require 'base64'
3
- require 'websocket-client-simple'
4
- require 'eventmachine'
5
2
  require 'json'
6
3
 
7
- require_relative './protobuf/bluzelle_pb'
8
- require_relative './protobuf/database_pb'
9
-
10
- DEFAULT_UUID = '8c073d96-7291-11e8-adc0-fa7ae01bbebc'
11
- DEFAULT_IP = '13.78.131.94' # '127.0.0.1'
12
- DEFAULT_PORT = 51010 # 8100
4
+ require_relative './constants'
5
+ require_relative './proto_serializer'
6
+ require_relative './connection'
13
7
 
14
8
  module Swarmclient
15
9
  class Communication
16
-
17
- attr_accessor :transaction_id_limit, :ws_set_timeout
18
-
19
- @transaction_id_limit = 100
20
- @ws_set_timeout = 5
10
+ include Constants
11
+ include ProtoSerializer
12
+ include Connection
21
13
 
22
14
  def initialize endpoint: DEFAULT_IP, port: DEFAULT_PORT, uuid: DEFAULT_UUID, secure: false
23
15
 
@@ -25,138 +17,88 @@ module Swarmclient
25
17
  @_port = port
26
18
  @_uuid = uuid
27
19
  @_protocol_prefix = secure ? 'wss://' : 'ws://'
20
+ @_redirect_attempt = 0
28
21
 
29
22
  end
30
23
 
31
24
  def create key, value
32
- send cmd: 'create', data: { key: key, value: value.to_s }
25
+ send_request cmd: 'create', data: { key: key, value: value.to_s }
33
26
  end
34
27
 
35
28
  def read key
36
- send cmd: 'read', data: { key: key }
29
+ send_request cmd: 'read', data: { key: key }
37
30
  end
38
31
 
39
32
  def update key, value
40
- send cmd: 'update', data: { key: key, value: value.to_s }
33
+ send_request cmd: 'update', data: { key: key, value: value.to_s }
41
34
  end
42
35
 
43
36
  def remove key
44
- send cmd: 'delete', data: { key: key }
37
+ send_request cmd: 'delete', data: { key: key }
45
38
  end
46
39
 
47
40
  def has key
48
- send cmd: 'has', data: { key: key }
41
+ send_request cmd: 'has', data: { key: key }
49
42
  end
50
43
 
51
44
  def keys
52
- send cmd: 'keys', data: nil
45
+ send_request cmd: 'keys', data: nil
53
46
  end
54
47
 
55
48
  def size
56
- send cmd: 'size', data: nil
49
+ send_request cmd: 'size', data: nil
57
50
  end
58
51
 
59
52
  private
60
53
 
61
- def encoded_protobuf_msg cmd:, protobuf_cmd_data:
62
- db_msg = Database_msg.new
63
- db_msg.header = Database_header.new db_uuid: @_uuid, transaction_id: rand(@transaction_id_limit).to_i
64
- db_msg[cmd] = protobuf_cmd_data
65
- bzn_msg = Bzn_msg.new db: db_msg
66
- Bzn_msg.encode bzn_msg
67
- end
68
-
69
- def generate_req cmd:, data:
70
- protobuf_cmd = cmd_to_protobuf cmd
71
- protobuf_cmd_msg = data.nil? ? protobuf_cmd.new : protobuf_cmd.new(data)
72
-
73
- encoded_msg = encoded_protobuf_msg cmd: cmd, protobuf_cmd_data: protobuf_cmd_msg
54
+ def generate_req **options
55
+ db_msg = generate_db_msg options.merge db_uuid: @_uuid
56
+ encoded_msg = encode_msg db_msg
74
57
  encoded64_msg = Base64.strict_encode64 encoded_msg
75
58
 
76
59
  {"bzn-api": "database","msg": encoded64_msg}.to_json
77
60
  end
78
61
 
79
- def cmd_to_protobuf cmd
80
- processed_cmd =
81
- case cmd
82
- when 'keys', 'size' then 'empty'
83
- else cmd
84
- end
85
-
86
- Object.const_get "Database_#{processed_cmd}"
87
- end
88
-
89
62
  def generate_endpoint
90
63
  [@_protocol_prefix, @_endpoint, ':', @_port.to_s].join('')
91
64
  end
92
65
 
93
- def send cmd:, data:
94
- endpoint, req = [
95
- generate_endpoint,
96
- generate_req({ cmd: cmd, data: data })
97
- ]
66
+ def send_request **options
67
+ raise StandardError.new "Max Leader redirect attempt reached" if @_redirect_attempt >= MAX_REDIRECT_ATTEMPT
98
68
 
99
- err, res = get req: req, endpoint: endpoint
100
- return err if err
101
- raise 'No Response' if res.nil?
69
+ endpoint = generate_endpoint
70
+ req = generate_req options
102
71
 
103
- db_response = Database_response.decode res
72
+ err, res = connect_and_send req: req, endpoint: endpoint
73
+ raise err unless err.nil?
74
+
75
+ db_response = decode_res res
104
76
 
105
77
  if db_response.redirect
106
78
  puts 'Switching leader_host: ' + db_response.redirect.leader_name
79
+ @_redirect_attempt += 1
107
80
  @_endpoint, @_port = [
108
81
  db_response.redirect.leader_host,
109
- db_response.redirect.leader_port
82
+ db_response.redirect.leader_port,
110
83
  ]
111
84
 
112
- return send cmd: cmd, data: data
85
+ return send_request options
113
86
 
114
- elsif !db_response.resp.nil? && !db_response.resp.error.empty?
115
- return db_response.resp.error
87
+ elsif !(db_response.resp.nil? || db_response.resp.error.empty?)
88
+ raise db_response.resp.error
116
89
 
117
90
  else
118
- case cmd
119
- when 'create', 'update', 'delete' then nil
120
- when 'read' then db_response.resp.value
121
- else db_response.resp[cmd]
122
- end
123
-
124
- end
125
-
126
- end
127
-
128
- def get req:, endpoint:
129
- res, err = [nil, nil]
130
-
131
- begin
132
- EventMachine.run do
133
- ws = WebSocket::Client::Simple.connect endpoint
134
-
135
- ws.on :message do |msg|
136
- res = msg.data
137
- EventMachine::stop_event_loop
138
- end
139
-
140
- ws.on :open do
141
- ws.send req
142
- end
143
-
144
- ws.on :close do |e|
145
- EventMachine::stop_event_loop
146
- end
147
-
148
- ws.on :error do |e|
149
- err ||= e
150
- EventMachine::stop_event_loop
151
- end
152
-
153
- EventMachine::Timer.new(5) { ws.close }
91
+ @_redirect_attempt = 0
92
+ case options[:cmd]
93
+ when 'create', 'update', 'delete' then true
94
+ when 'read' then db_response.resp.value
95
+ else db_response.resp[options[:cmd]]
154
96
  end
155
- rescue => e
156
- err = e
157
97
  end
158
98
 
159
- return [err, res]
99
+ rescue => e
100
+ @_redirect_attempt = 0
101
+ e.message
160
102
  end
161
103
 
162
104
  end
@@ -0,0 +1,46 @@
1
+ require 'websocket-client-simple'
2
+ require 'eventmachine'
3
+
4
+ require_relative './constants'
5
+
6
+ module Swarmclient
7
+ module Connection
8
+ include Constants
9
+
10
+ private
11
+
12
+ def connect_and_send req:, endpoint:
13
+ res, err = [nil, nil]
14
+
15
+ begin
16
+ EventMachine.run do
17
+ ws = WebSocket::Client::Simple.connect endpoint
18
+
19
+ ws.on :message do |msg|
20
+ res = msg.data
21
+ EventMachine::stop_event_loop
22
+ end
23
+
24
+ ws.on :open do
25
+ ws.send req
26
+ end
27
+
28
+ ws.on :close do |e|
29
+ EventMachine::stop_event_loop
30
+ end
31
+
32
+ ws.on :error do |e|
33
+ err ||= e
34
+ EventMachine::stop_event_loop
35
+ end
36
+
37
+ EventMachine::Timer.new(CONNECTION_TIMEOUT_LIMIT) { ws.close }
38
+ end
39
+ rescue => e
40
+ err = e
41
+ end
42
+
43
+ return [err, res]
44
+ end
45
+ end
46
+ end
@@ -0,0 +1,32 @@
1
+ module Swarmclient
2
+ module Constants
3
+
4
+ ##
5
+ # Randomly generated uuid, will add validation if not initialize in the future.
6
+ DEFAULT_UUID = '8c073d96-7291-11e8-adc0-fa7ae01bbebc'
7
+
8
+ ##
9
+ # Points default ip to localhost.
10
+ DEFAULT_IP = '127.0.0.1'
11
+
12
+ ##
13
+ # Points to default swarmDB port
14
+ # For more details: https://github.com/bluzelle/swarmDB
15
+ DEFAULT_PORT = 51010
16
+
17
+ ##
18
+ # Set limit in seconds per socket before raising a Timeout Error
19
+ CONNECTION_TIMEOUT_LIMIT = 3
20
+
21
+ ##
22
+ # Temporary redirect attempt limit.
23
+ # Track discussion on: https://gitter.im/bluzelle/opensource
24
+ MAX_REDIRECT_ATTEMPT = 3
25
+
26
+ ##
27
+ # Not yet confirmed the randomness of db_msg.header.transaction_id
28
+ # https://github.com/wlwanpan/swarmclient-rb/issues/4
29
+ TRANSATION_ID_UPPER_LIMIT = 1000
30
+
31
+ end
32
+ end
@@ -0,0 +1,45 @@
1
+ require 'google/protobuf'
2
+
3
+ require_relative './constants'
4
+ require_relative './protobuf/bluzelle_pb'
5
+ require_relative './protobuf/database_pb'
6
+
7
+ module Swarmclient
8
+ module ProtoSerializer
9
+ include Constants
10
+
11
+ private
12
+
13
+ def decode_res res
14
+ Database_response.decode res
15
+ end
16
+
17
+ def encode_msg msg
18
+ bzn_msg = Bzn_msg.new db: msg
19
+ Bzn_msg.encode bzn_msg
20
+ end
21
+
22
+ def generate_db_msg cmd:, data:, db_uuid:
23
+ protobuf_cmd = cmd_to_protobuf cmd
24
+ protobuf_cmd_msg = data.nil? ? protobuf_cmd.new : protobuf_cmd.new(data)
25
+
26
+ proto_header_msg = Database_header.new db_uuid: db_uuid, transaction_id: rand(TRANSATION_ID_UPPER_LIMIT).to_i
27
+
28
+ db_msg = Database_msg.new
29
+ db_msg.header = proto_header_msg
30
+ db_msg[cmd] = protobuf_cmd_msg
31
+ db_msg
32
+ end
33
+
34
+ def cmd_to_protobuf cmd
35
+ processed_cmd =
36
+ case cmd
37
+ when 'keys', 'size' then 'empty'
38
+ else cmd
39
+ end
40
+
41
+ Object.const_get "Database_#{processed_cmd}"
42
+ end
43
+
44
+ end
45
+ end
@@ -0,0 +1,28 @@
1
+ # Generated by the protocol buffer compiler. DO NOT EDIT!
2
+ # source: audit.proto
3
+
4
+ require 'google/protobuf'
5
+
6
+ Google::Protobuf::DescriptorPool.generated_pool.build do
7
+ add_message "audit_message" do
8
+ oneof :msg do
9
+ optional :commit, :message, 1, "commit_notification"
10
+ optional :leader_status, :message, 2, "leader_status"
11
+ end
12
+ end
13
+ add_message "leader_status" do
14
+ optional :term, :uint64, 1
15
+ optional :leader, :string, 2
16
+ optional :current_log_index, :uint64, 3
17
+ optional :current_commit_index, :uint64, 4
18
+ end
19
+ add_message "commit_notification" do
20
+ optional :sender_uuid, :string, 1
21
+ optional :log_index, :uint64, 2
22
+ optional :operation, :string, 3
23
+ end
24
+ end
25
+
26
+ Audit_message = Google::Protobuf::DescriptorPool.generated_pool.lookup("audit_message").msgclass
27
+ Leader_status = Google::Protobuf::DescriptorPool.generated_pool.lookup("leader_status").msgclass
28
+ Commit_notification = Google::Protobuf::DescriptorPool.generated_pool.lookup("commit_notification").msgclass
@@ -4,12 +4,13 @@
4
4
  require 'google/protobuf'
5
5
 
6
6
  require_relative './database_pb'
7
-
7
+ require_relative './audit_pb'
8
8
  Google::Protobuf::DescriptorPool.generated_pool.build do
9
9
  add_message "bzn_msg" do
10
10
  oneof :msg do
11
11
  optional :db, :message, 10, "database_msg"
12
12
  optional :json, :string, 11
13
+ optional :audit_message, :message, 12, "audit_message"
13
14
  end
14
15
  end
15
16
  end
@@ -1,3 +1,3 @@
1
1
  module Swarmclient
2
- VERSION = "0.1.3"
2
+ VERSION = "0.1.4"
3
3
  end
data/swarmclient.gemspec CHANGED
@@ -9,7 +9,7 @@ Gem::Specification.new do |spec|
9
9
  spec.authors = ["Warren"]
10
10
  spec.email = ["wlwanpan@uwaterloo.ca"]
11
11
 
12
- spec.summary = %q{A gem for the bluzele SwarmDB}
12
+ spec.summary = %q{A gem for the CRUD operations on the bluzelle SwarmDB}
13
13
  # spec.description = %q{TODO: Write a longer description or delete this line.}
14
14
  spec.homepage = "https://github.com/wlwanpan/swarmclient-rb"
15
15
  spec.license = "MIT"
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: swarmclient
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.3
4
+ version: 0.1.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - Warren
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2018-06-29 00:00:00.000000000 Z
11
+ date: 2018-07-02 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -116,6 +116,7 @@ extensions: []
116
116
  extra_rdoc_files: []
117
117
  files:
118
118
  - ".gitignore"
119
+ - ".gitmodules"
119
120
  - ".rspec"
120
121
  - ".travis.yml"
121
122
  - CODE_OF_CONDUCT.md
@@ -127,12 +128,14 @@ files:
127
128
  - bin/setup
128
129
  - lib/swarmclient.rb
129
130
  - lib/swarmclient/communication.rb
131
+ - lib/swarmclient/connection.rb
132
+ - lib/swarmclient/constants.rb
133
+ - lib/swarmclient/proto_serializer.rb
134
+ - lib/swarmclient/protobuf/audit_pb.rb
130
135
  - lib/swarmclient/protobuf/bluzelle_pb.rb
131
136
  - lib/swarmclient/protobuf/database_pb.rb
132
137
  - lib/swarmclient/pubsub.rb
133
138
  - lib/swarmclient/version.rb
134
- - proto/bluzelle.proto
135
- - proto/database.proto
136
139
  - swarmclient.gemspec
137
140
  homepage: https://github.com/wlwanpan/swarmclient-rb
138
141
  licenses:
@@ -157,5 +160,5 @@ rubyforge_project:
157
160
  rubygems_version: 2.6.14
158
161
  signing_key:
159
162
  specification_version: 4
160
- summary: A gem for the bluzele SwarmDB
163
+ summary: A gem for the CRUD operations on the bluzelle SwarmDB
161
164
  test_files: []
data/proto/bluzelle.proto DELETED
@@ -1,14 +0,0 @@
1
- syntax = "proto3";
2
-
3
- // Bluzelle message definition from:
4
- // https://github.com/bluzelle/swarmDB/blob/devel/proto/bluzelle.proto
5
-
6
- import "database.proto";
7
-
8
- message bzn_msg
9
- {
10
- oneof msg {
11
- database_msg db = 10;
12
- string json = 11;
13
- }
14
- }
data/proto/database.proto DELETED
@@ -1,83 +0,0 @@
1
- syntax = "proto3";
2
-
3
- // Database message definition from:
4
- // https://github.com/bluzelle/swarmDB/blob/devel/proto/database.proto
5
-
6
- message database_msg
7
- {
8
- database_header header = 2;
9
-
10
- oneof msg {
11
- database_create create = 10;
12
- database_read read = 11;
13
- database_update update = 12;
14
- database_delete delete = 13;
15
- database_has has = 14;
16
- database_empty keys = 15;
17
- database_empty size = 16;
18
- }
19
- }
20
-
21
- message database_redirect_response
22
- {
23
- string leader_id = 1;
24
- string leader_name = 2;
25
- string leader_host = 3;
26
- uint32 leader_port = 4;
27
- uint32 leader_http_port = 5;
28
- }
29
-
30
- message database_header
31
- {
32
- string db_uuid = 1;
33
- uint64 transaction_id = 2;
34
- }
35
-
36
- message database_create
37
- {
38
- string key = 2;
39
- bytes value = 3;
40
- }
41
-
42
- message database_read
43
- {
44
- string key = 2;
45
- }
46
-
47
- message database_update
48
- {
49
- string key = 2;
50
- bytes value = 3;
51
- }
52
-
53
- message database_delete
54
- {
55
- string key = 2;
56
- }
57
-
58
- message database_has
59
- {
60
- string key = 2;
61
- }
62
-
63
- message database_empty {}
64
-
65
- message database_response
66
- {
67
- database_header header = 1;
68
-
69
- oneof success
70
- {
71
- database_redirect_response redirect = 2;
72
- response resp = 3;
73
- }
74
-
75
- message response
76
- {
77
- bytes value = 4;
78
- bool has = 5;
79
- int32 size = 6;
80
- string error = 7;
81
- repeated string keys = 8;
82
- }
83
- }