protobuf 2.8.8 → 2.8.9
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 +4 -4
- data/CHANGES.md +7 -0
- data/README.md +16 -454
- data/Rakefile +7 -0
- data/bin/protoc-gen-ruby +1 -10
- data/lib/protobuf.rb +1 -0
- data/lib/protobuf/cli.rb +1 -2
- data/lib/protobuf/descriptors.rb +3 -0
- data/lib/protobuf/lifecycle.rb +20 -11
- data/lib/protobuf/rpc/service_directory.rb +1 -2
- data/lib/protobuf/tasks.rb +1 -0
- data/lib/protobuf/tasks/compile.rake +58 -0
- data/lib/protobuf/version.rb +1 -1
- data/spec/lib/protobuf/cli_spec.rb +2 -2
- data/spec/lib/protobuf/lifecycle_spec.rb +3 -14
- data/spec/lib/protobuf/rpc/service_directory_spec.rb +3 -4
- metadata +5 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 730f8de122b9b6b07a5fcf1be77f6af48647279a
|
4
|
+
data.tar.gz: 5a0a5aacf4099da045ea560e538f45030f6dee78
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 39211c5a2c882445549d99111dd4d50b3456221e752c5dfcffa2033e98e82b8564d543de452d0f9357efd941b22f846a6a6188e55b2129414d141faf4cf9058f
|
7
|
+
data.tar.gz: 38dd648c17492ffd2510c9cca5a96532d73f529271fe4e80f49605da652e9804f77c9594a6d5f8f3842091d27bc68c6ee80879822a89512f9ec6a0cd3de674c6
|
data/CHANGES.md
CHANGED
@@ -1,3 +1,10 @@
|
|
1
|
+
2.8.9
|
2
|
+
---------
|
3
|
+
|
4
|
+
- Deprecated Protobuf::Lifecycle module in favor of using ActiveSupport::Notifications. [#139, @devin-c]
|
5
|
+
- Modify `$LOAD_PATH` inside descriptors.rb to make it easier for other libraries to write their own compiler plugins using our pre-compiled descriptors. [#141, @localshred]
|
6
|
+
- Add protobuf:clean and protobuf:compile rake tasks for use in external libraries to compile source definitions to a destination. [#142, @localshred]
|
7
|
+
|
1
8
|
2.8.8
|
2
9
|
---------
|
3
10
|
|
data/README.md
CHANGED
@@ -2,468 +2,30 @@
|
|
2
2
|
|
3
3
|
[](http://badge.fury.io/rb/protobuf)
|
4
4
|
[](https://travis-ci.org/localshred/protobuf)
|
5
|
-
|
6
|
-
___See [CHANGES.md](https://github.com/localshred/protobuf/blob/master/CHANGES.md) or [Release Notes](https://github.com/localshred/protobuf/releases) for significant version changes.___
|
5
|
+
[](https://gitter.im/localshred/protobuf)
|
7
6
|
|
8
7
|
Protobuf is an implementation of [Google's protocol buffers][google-pb] in ruby, version 2.5.0 is currently supported.
|
9
8
|
|
10
|
-
---
|
11
|
-
|
12
9
|
## Install
|
13
10
|
|
14
|
-
|
15
|
-
or from source. This gem currently supports protobuf <= 2.5.0.
|
16
|
-
|
17
|
-
### OSX Install
|
18
|
-
|
19
|
-
```shell
|
20
|
-
$ brew install protobuf
|
21
|
-
```
|
22
|
-
|
23
|
-
### Ubuntu
|
24
|
-
```shell
|
25
|
-
$ sudo apt-get install -y protobuf
|
26
|
-
```
|
27
|
-
|
28
|
-
### Gem Install
|
29
|
-
|
30
|
-
Once the protobuf package is installed, install this gem with rubygems/bundler.
|
31
|
-
_Please note that this will void your warranty as it were. If you compiled with
|
32
|
-
a custom protobuf package and are having issues it may be difficult to troubleshoot._
|
33
|
-
|
34
|
-
```shell
|
35
|
-
$ gem install protobuf
|
36
|
-
```
|
37
|
-
|
38
|
-
------
|
39
|
-
|
40
|
-
## Generating ruby classes from `.proto` files
|
41
|
-
|
42
|
-
Protocol Buffers are great because they allow you to clearly define data storage
|
43
|
-
or data transfer packets. Google officially supports Java, C++, and Python for
|
44
|
-
compilation and usage. Let's make it ruby aware!
|
45
|
-
|
46
|
-
Let's say you have a `defs.proto` file that defines a User message.
|
47
|
-
|
48
|
-
```protobuf
|
49
|
-
package foo;
|
50
|
-
message User {
|
51
|
-
optional string first_name = 1;
|
52
|
-
optional string last_name = 2;
|
53
|
-
}
|
54
|
-
```
|
55
|
-
|
56
|
-
Now let's compile that definition to ruby:
|
57
|
-
|
58
|
-
```shell
|
59
|
-
$ protoc defs.proto --ruby_out ./lib
|
60
|
-
```
|
61
|
-
|
62
|
-
The previous line will take whatever is defined in `defs.proto` and
|
63
|
-
output ruby classes to the `./lib` directory, obeying the package
|
64
|
-
directive. Your `./lib` should now look like this:
|
65
|
-
|
66
|
-
```
|
67
|
-
- lib
|
68
|
-
|- foo
|
69
|
-
|- defs.pb.rb
|
70
|
-
```
|
71
|
-
|
72
|
-
The generated file `defs.pb.rb` should look something like this:
|
73
|
-
|
74
|
-
```ruby
|
75
|
-
module Foo
|
76
|
-
class User < ::Protobuf::Message; end
|
77
|
-
|
78
|
-
class User
|
79
|
-
optional ::Protobuf::Field::StringField, :first_name, 1
|
80
|
-
optional ::Protobuf::Field::StringField, :last_name, 2
|
81
|
-
end
|
82
|
-
end
|
83
|
-
```
|
84
|
-
|
85
|
-
__Note:__ The generator will pre-define all message/enum classes empty and then
|
86
|
-
re-open to apply the defined fields. This is to prevent field dependency errors.
|
87
|
-
|
88
|
-
The generated class is now just a plain old ruby object. You can use it however you wish.
|
89
|
-
|
90
|
-
```ruby
|
91
|
-
require 'lib/foo/user.pb'
|
92
|
-
|
93
|
-
# dot notation reading/writing fields
|
94
|
-
user = Foo::User.new
|
95
|
-
user.first_name = "Lloyd"
|
96
|
-
user.last_name = "Christmas"
|
97
|
-
user.first_name # => "Lloyd"
|
98
|
-
|
99
|
-
# or pass in the fields as a hash to the initializer
|
100
|
-
user = Foo::User.new :first_name => "Lloyd", :last_name => "Christmas"
|
101
|
-
user.first_name # => Lloyd
|
102
|
-
user.last_name # => Christmas
|
103
|
-
```
|
104
|
-
|
105
|
-
### Message (de)serialization
|
106
|
-
|
107
|
-
Every message object comes ready for serialization or deserialization.
|
108
|
-
Use `serialize_to_string` to write out the byte-string for the message.
|
109
|
-
Use `parse_from_string` on a new message instance to inflate the
|
110
|
-
byte-string back to a message in ruby.
|
111
|
-
|
112
|
-
```ruby
|
113
|
-
user = Foo::User.new(:first_name => 'Bob')
|
114
|
-
bytes = user.serialize_to_string
|
115
|
-
puts bytes #=> binary representation of this message object
|
116
|
-
|
117
|
-
inflated_user = Foo::User.new.parse_from_string(bytes)
|
118
|
-
inflated_user == user #=> true
|
119
|
-
```
|
120
|
-
|
121
|
-
## Callings Services with RPC
|
122
|
-
|
123
|
-
Google's Protocol Buffers provides support for Services with RPC.
|
124
|
-
|
125
|
-
For our purposes, we'll talk about a `Client` (process that is calling
|
126
|
-
the server/service), a `Service` (the remote procedure), and a `Server`
|
127
|
-
(the process that manages one or more services). We'll start with the Service first.
|
128
|
-
|
129
|
-
### Services
|
130
|
-
|
131
|
-
Services are simply classes that have endpoint methods defined. Here's what
|
132
|
-
one looks like in protobuf:
|
133
|
-
|
134
|
-
```protobuf
|
135
|
-
package foo;
|
136
|
-
message UserRequest {
|
137
|
-
optional string email = 1;
|
138
|
-
}
|
139
|
-
message UserList {
|
140
|
-
repeated User users = 1;
|
141
|
-
}
|
142
|
-
service UserService {
|
143
|
-
rpc Find (UserRequest) returns (UserList);
|
144
|
-
}
|
145
|
-
```
|
146
|
-
|
147
|
-
And the equivalent ruby stub for the service (generated with `rprotoc`):
|
148
|
-
|
149
|
-
```ruby
|
150
|
-
# lib/foo/user.pb.rb
|
151
|
-
module Foo
|
152
|
-
# UserRequest and UserList Class definitions not shown (see above for generated output of classes).
|
153
|
-
|
154
|
-
class UserService < ::Protobuf::Rpc::Service
|
155
|
-
rpc :find, UserRequest, UserList
|
156
|
-
end
|
157
|
-
end
|
158
|
-
```
|
159
|
-
|
160
|
-
__Important Note: The UserService class here is a *stub*. You should not
|
161
|
-
provide your implementation in this generated file as subsequent generations
|
162
|
-
will wipe out your implmentation. Read on to learn how to use this stub.__
|
163
|
-
|
164
|
-
Now that you have a generated service stub, you'll want to require it
|
165
|
-
from `lib` and provide the implementation. Create a service implementation file
|
166
|
-
in your project. In rails I'd put this in `app/services/foo/user_service.rb`.
|
167
|
-
|
168
|
-
```ruby
|
169
|
-
# app/services/foo/user_service.rb
|
170
|
-
require 'lib/foo/user.pb'
|
171
|
-
|
172
|
-
# Reopen the class and provide the implementation for each rpc method defined.
|
173
|
-
module Foo
|
174
|
-
class UserService
|
175
|
-
|
176
|
-
# request -> Foo::UserRequest
|
177
|
-
# response -> Foo::UserResponse
|
178
|
-
def find
|
179
|
-
# request.email will be the unpacked string that was sent by the client request
|
180
|
-
users = []
|
181
|
-
User.find_by_email(request.email).each do |user|
|
182
|
-
users << user.to_proto
|
183
|
-
end
|
184
|
-
|
185
|
-
respond_with(:users => users)
|
186
|
-
end
|
187
|
-
|
188
|
-
end
|
189
|
-
end
|
190
|
-
```
|
191
|
-
|
192
|
-
Simply implement the instance method for the defined rpc. You can provide
|
193
|
-
any other methods in this class as helpers, but only those defined in the
|
194
|
-
proto file will be callable by remote clients. Every request made by a client
|
195
|
-
will provide a non-empty request of the defined type. The server creates a new
|
196
|
-
service instance for every request, so you should not be constrained to just
|
197
|
-
the endpoint method. This is similar to rails controllers where only methods
|
198
|
-
defined by the routes file are hooked up to HTTP requests, but it's very common
|
199
|
-
to implement private methods to aid in code quality and simpilicity.
|
200
|
-
|
201
|
-
Every instance has a `request` and `response` object used for fulfilling the call,
|
202
|
-
again, similar to a rails controller action. You should never attempt to modify the
|
203
|
-
`request` object. The `response` object however should be modified or replaced
|
204
|
-
entirely. If you need to create your own response object (a valid case), simply use
|
205
|
-
`respond_with(new_response)`. The returned object should conform to one of three properties:
|
206
|
-
|
207
|
-
1. Response should be of same type as defined by the rpc definition (in this case, `Foo::UserList`), or
|
208
|
-
2. Response should be a hash, respond to `to_hash`, or respond to `to_proto_hash`. The hash will be used to construct an instance of the defined type and should therefore conform to the appropriate fields for that type.
|
209
|
-
3. Response should respond to the `to_proto` method. The object returned by `to_proto` should be an instance of the defined response type.
|
210
|
-
|
211
|
-
If at any time the implementation encounters an error, the client can be
|
212
|
-
instructed of the error using `rpc_failed`:
|
213
|
-
|
214
|
-
```ruby
|
215
|
-
#...
|
216
|
-
def find
|
217
|
-
if request.email.blank?
|
218
|
-
rpc_failed 'Unable to find user without an email'
|
219
|
-
else
|
220
|
-
# query/populate response
|
221
|
-
end
|
222
|
-
end
|
223
|
-
#...
|
224
|
-
```
|
225
|
-
|
226
|
-
This means that the client's `on_failure` callback will be invoked instead
|
227
|
-
of the `on_success` callback. Read more below on client callbacks. One drawback
|
228
|
-
to the `rpc_failed` approach is that it does not short-circuit the rest of
|
229
|
-
the method. This means that you must explicitly return from the method if
|
230
|
-
you do not wish the remainder to be executed.
|
231
|
-
|
232
|
-
### Service Filters
|
233
|
-
|
234
|
-
Service Filters provides ActionController-style filter support to service
|
235
|
-
instances, specifically adding `before_filter`, `after_filter`, and `around_filter`.
|
236
|
-
|
237
|
-
```ruby
|
238
|
-
require 'lib/foo/user.pb'
|
239
|
-
|
240
|
-
class Foo::UserService
|
241
|
-
before_filter :start_request_timer
|
242
|
-
after_filter :end_request_timer
|
243
|
-
around_filter :benchmark_request
|
244
|
-
|
245
|
-
# Provide a list of rpc methods to call (or exclude calling) for the given filter(s).
|
246
|
-
# The following two filters are essentially equivalent.
|
247
|
-
before_filter :verify_user_present, :only => [ :update, :delete ]
|
248
|
-
before_filter :verify_user_present, :except => [ :find, :create ]
|
249
|
-
|
250
|
-
# Using if/unless filters options to achieve the same goal, reporting a login after the login has been processed.
|
251
|
-
# Note that you can provide a method name or lambda, but you must return a boolean value.
|
252
|
-
after_filter :report_login, :only => :login, :if => :user_found?
|
253
|
-
after_filter :report_login, :only => :login, :if => lambda { |service| service.response.user_guid.present? }
|
254
|
-
after_filter :report_login, :only => :login, :unless => :user_missing?
|
255
|
-
after_filter :report_login, :only => :login, :unless => lambda { |service| service.response.user_guid.empty? }
|
256
|
-
|
257
|
-
#... rpc instance methods
|
258
|
-
|
259
|
-
private
|
260
|
-
|
261
|
-
def start_request_timer
|
262
|
-
@time_start = Time.now
|
263
|
-
end
|
264
|
-
|
265
|
-
def end_request_timer
|
266
|
-
@time_end = Time.now
|
267
|
-
log_info { ... }
|
268
|
-
end
|
269
|
-
|
270
|
-
def benchmark_request
|
271
|
-
Benchmark.benchmark do
|
272
|
-
yield
|
273
|
-
end
|
274
|
-
end
|
275
|
-
end
|
276
|
-
```
|
277
|
-
|
278
|
-
#### Halting execution of rpc request inside a filter
|
279
|
-
|
280
|
-
__Around Filters__ – Inside of an around filter, if you wish to halt
|
281
|
-
request processing and return, simply do not `yield` the block. Since the
|
282
|
-
filter is implemented as an instance method, you can use `rpc_failed`
|
283
|
-
or `respond_with` just like you can in the endpoint methods.
|
284
|
-
|
285
|
-
__Before Filters__ – Returning `false` from a before filter will cancel
|
286
|
-
any other filter calls which would run afterwards, as well as canceling
|
287
|
-
invocation of the service method. _Note: You must actually return `false`,
|
288
|
-
not just a "falsey" value such as `nil`._
|
289
|
-
|
290
|
-
__After Filters__ – No request shortcutting.
|
291
|
-
|
292
|
-
#### Filter options
|
293
|
-
|
294
|
-
The following options can be applied to any of the filters as the final
|
295
|
-
argument in the filter configuration. (See example above).
|
296
|
-
|
297
|
-
__:if__ – The object supplied to `:if` can either be a symbol/string
|
298
|
-
indicating the instance method to call, or, an object that responds to `call`.
|
299
|
-
The method or callable should return true or false indicating if the
|
300
|
-
filter should be invoked or not. Akin to the `if` keyword.
|
301
|
-
|
302
|
-
__:unless__ – The opposite of the `:if` option is `:unless`. Accepts
|
303
|
-
the same object types. The method or callable should return true or
|
304
|
-
false indicating if the filter should be invoked or not. Akin to the
|
305
|
-
`unless` keyword.
|
306
|
-
|
307
|
-
__:only__ – A string/symbol or Array of strings/symbols values that
|
308
|
-
reference instance methods. The names of these methods should be the
|
309
|
-
rpc method you wish to invoke the filter for. Methods not identified
|
310
|
-
in this list would not have the filter applied.
|
311
|
-
|
312
|
-
__:except__ – The opposite of the `:only` option. A string/symbol or
|
313
|
-
Array of strings/symbols values that reference instance methods. The
|
314
|
-
names of these methods should be the rpc method you wish to skip
|
315
|
-
invokation of the given filter. Methods not identified in this list
|
316
|
-
would have the filter applied.
|
317
|
-
|
318
|
-
### Servers
|
319
|
-
|
320
|
-
Services need to be hooked up to a socket to be called by clients.
|
321
|
-
Use the provided program `rpc_server`:
|
322
|
-
|
323
|
-
```
|
324
|
-
$ rpc_server -o myserver.com -p 9399 -l ./log/protobuf.log ./config/environment.rb
|
325
|
-
```
|
326
|
-
|
327
|
-
The previous call will start a Socket server running on the given
|
328
|
-
host and port which will load your application into memory. You
|
329
|
-
certainly don't have to run rails or any other framework, just
|
330
|
-
make sure you have some kind of file that will load your services
|
331
|
-
all into memory. The server doesn't know where you put your code,
|
332
|
-
so tell it.
|
333
|
-
|
334
|
-
Be aware that the server needs to be able to translate the socket
|
335
|
-
stream of bytes into an actual protobuf request object. If the
|
336
|
-
definition for that request object aren't known to the server,
|
337
|
-
you're going to have a long day getting this going. It's necessary
|
338
|
-
to store all your definitions and their generated classes in a
|
339
|
-
shared repository (read: gem) so that both client and server have
|
340
|
-
access to the ruby classes in their respective load paths.
|
341
|
-
|
342
|
-
Once the server starts, you should see it as a running process
|
343
|
-
with `ps`. Sending a KILL, QUIT, or TERM signal to the pid will
|
344
|
-
result in shutting the server down gracefully.
|
345
|
-
|
346
|
-
```
|
347
|
-
$ ps aux | grep rpc_server
|
348
|
-
1234 ... rpc_server myserver.com:9399
|
349
|
-
|
350
|
-
$ kill -QUIT 1234
|
351
|
-
rpc_server shutdown
|
352
|
-
```
|
353
|
-
|
354
|
-
### Clients
|
355
|
-
|
356
|
-
Calling a service with a clients feels very ajaxy. If you prefer
|
357
|
-
a simpler syntax I highly recommend using [ActiveRemote](https://github.com/liveh2o/active_remote)
|
358
|
-
which was developed in conjunction with this library to make
|
359
|
-
interacting with a remote service feel identical to using an
|
360
|
-
ActiveRecord model. Seriously, it's wicked cool.
|
361
|
-
|
362
|
-
```ruby
|
363
|
-
# require the defs from the shared gem/repo
|
364
|
-
require 'sharedgem/foo/user.pb'
|
365
|
-
|
366
|
-
# Create a request object for the method we are invoking
|
367
|
-
req = Foo::UserRequest.new(:email => 'jeff@gmail.com')
|
368
|
-
|
369
|
-
# Use the UserService class to generate a client, invoke the rpc method
|
370
|
-
# while passing the request object.
|
371
|
-
# We could also simply pass a hash to find.
|
372
|
-
Foo::UserService.client.find(req) do |client|
|
373
|
-
# This block will be executed (registering the callbacks)
|
374
|
-
# before the request actualy occurs.
|
375
|
-
# the `client` param in this block is the object
|
376
|
-
# that is created by `Foo::UserService.client`.
|
377
|
-
|
378
|
-
# Register a block for execution when the response
|
379
|
-
# is deemed successful from the service. Accepts
|
380
|
-
# the unpacked response as its only parameter.
|
381
|
-
c.on_success do |response|
|
382
|
-
response.users.each do |user|
|
383
|
-
puts user.inspect
|
384
|
-
end
|
385
|
-
end
|
386
|
-
|
387
|
-
# Register a block for execution when the response
|
388
|
-
# is deemed a failure. This can be either a client-side
|
389
|
-
# or server-side failure. The object passed to the
|
390
|
-
# block has a `message` and a `code` attribute
|
391
|
-
# to aid in logging/diagnosing the failure.
|
392
|
-
c.on_failure do |error|
|
393
|
-
puts 'It failed: ' + error.message
|
394
|
-
end
|
395
|
-
end
|
396
|
-
```
|
397
|
-
|
398
|
-
Many different options can be passed to the `.client` call above
|
399
|
-
(such as `:timeout => 600`). See the `lib/protobuf/rpc/client.rb`
|
400
|
-
and `lib/protobuf/rpc/service.rb` files for more documentation.
|
401
|
-
|
402
|
-
### Dynamic Service Discovery (ZMQ Only)
|
403
|
-
It is possible to setup the RPC server and client in a way that
|
404
|
-
allows servers/services to be dynamically discovered by client processes.
|
405
|
-
|
406
|
-
#### In the client
|
407
|
-
```ruby
|
408
|
-
ServiceDirectory.start do |config|
|
409
|
-
config.port = 53000
|
410
|
-
end
|
411
|
-
|
412
|
-
# If your server also runs this code, it will default to the
|
413
|
-
# given port when sending beacons and have its own service
|
414
|
-
# directory. You can prevent this code from running on the
|
415
|
-
# server if needed:
|
416
|
-
unless defined?(::Protobuf::CLI)
|
417
|
-
ServiceDirectory.start do |config|
|
418
|
-
config.port = 53000
|
419
|
-
end
|
420
|
-
end
|
421
|
-
```
|
422
|
-
|
423
|
-
#### Starting the server with dynamic discovery enabled
|
424
|
-
```
|
425
|
-
$ rpc_server --broadcast-beacons --beacon-port 53000 ...
|
426
|
-
```
|
427
|
-
|
428
|
-
The client will listen on the specified port for beacons broadcast
|
429
|
-
by servers. Each beacon includes a list of services provided by the
|
430
|
-
broadcasting server. The client randomly selects a server for the
|
431
|
-
desired service each time a request is made.
|
432
|
-
|
433
|
-
__CAUTION:__ When running multiple environments on a single network,
|
434
|
-
e.g., qa and staging, be sure that each environment is setup with
|
435
|
-
a unique beacon port; otherwise, clients in one environment ___will___
|
436
|
-
make requests to servers in the other environment.
|
437
|
-
|
438
|
-
Check out the source for Protobuf::ServiceDirectory for more details.
|
439
|
-
|
440
|
-
## 3. RPC Interop
|
441
|
-
|
442
|
-
The main reason I wrote this gem was to provide a ruby implementation
|
443
|
-
to google's protobuf that worked on the RPC layer with a Java Service
|
444
|
-
layer that was already running [protobuf-socket-rpc][], the supported
|
445
|
-
socket rpc library for protobuf from Google. Other ruby protobuf
|
446
|
-
implementations I've used did not provide this kind of support.
|
11
|
+
See our [Installation Guide][] on the [wiki][].
|
447
12
|
|
448
|
-
##
|
13
|
+
## Usage
|
449
14
|
|
450
|
-
|
451
|
-
|
452
|
-
|
453
|
-
in with their master. Unfortunately I just simply couldn't use their
|
454
|
-
RPC code and so I forked the code. Myself and others have significantly
|
455
|
-
changed the internals of the gem, including the rpc implementation, the
|
456
|
-
message/field implementation, and the compiler implementation. These
|
457
|
-
changes were made to address glaring performance and quality issues
|
458
|
-
in the code. The code was initially diverged at their 0.4.0 version.
|
15
|
+
The [wiki][] contains in-depth guides on the various ways to use this gem
|
16
|
+
including [compiling defintions][], [object APIs][], [services][], [clients][], and even
|
17
|
+
an [API roadmap][].
|
459
18
|
|
460
|
-
|
461
|
-
really shown here, so please let me know if you have any questions
|
462
|
-
on usage or support for various features. Happy protobufing.
|
19
|
+
## Changelog
|
463
20
|
|
464
|
-
|
21
|
+
See recent changes in the [release notes][] or the [changelog][].
|
465
22
|
|
466
23
|
[google-pb]: http://code.google.com/p/protobuf "Google Protocol Buffers"
|
467
|
-
[
|
468
|
-
[
|
469
|
-
[
|
24
|
+
[wiki]: https://github.com/localshred/protobuf/wiki/Protobuf-Wiki "Protobuf Wiki"
|
25
|
+
[compiling definitions]: https://github.com/localshred/protobuf/wiki/Compiling-Definitions "Compiling definitions"
|
26
|
+
[object APIs]: https://github.com/localshred/protobuf/wiki/Messages-&-Enums "Message & Enum object APIs"
|
27
|
+
[services]: https://github.com/localshred/protobuf/wiki/Services "Services object API"
|
28
|
+
[clients]: https://github.com/localshred/protobuf/wiki/Clients "Client object API"
|
29
|
+
[API roadmap]: https://github.com/localshred/protobuf/wiki/API-Roadmap "API Roadmap"
|
30
|
+
[release notes]: https://github.com/localshred/protobuf/releases "CHANGES.md"
|
31
|
+
[changelog]: https://github.com/localshred/protobuf/blob/master/CHANGES.md "CHANGES.md"
|
data/Rakefile
CHANGED
data/bin/protoc-gen-ruby
CHANGED
@@ -7,16 +7,7 @@ ENV['PB_NO_NETWORKING'] = '1'
|
|
7
7
|
|
8
8
|
$LOAD_PATH << ::File.expand_path("../../lib", __FILE__)
|
9
9
|
require 'protobuf'
|
10
|
-
|
11
|
-
# Setup the loadpath so that plugin.pb will
|
12
|
-
# be able to require the descriptor.pb file.
|
13
|
-
#
|
14
|
-
$LOAD_PATH << ::File.expand_path("../../lib/protobuf/descriptors", __FILE__)
|
15
|
-
require 'google/protobuf/compiler/plugin.pb'
|
16
|
-
|
17
|
-
# Read the request bytes from STDIN, pass to the CodeGenerator, and
|
18
|
-
# write to STDOUT the generated response_bytes.
|
19
|
-
#
|
10
|
+
require 'protobuf/descriptors'
|
20
11
|
require 'protobuf/code_generator'
|
21
12
|
|
22
13
|
request_bytes = STDIN.read
|
data/lib/protobuf.rb
CHANGED
data/lib/protobuf/cli.rb
CHANGED
@@ -1,6 +1,5 @@
|
|
1
1
|
require 'thor'
|
2
2
|
require 'protobuf/version'
|
3
|
-
require 'protobuf/lifecycle'
|
4
3
|
require 'protobuf/logger'
|
5
4
|
require 'protobuf/rpc/servers/evented_runner'
|
6
5
|
require 'protobuf/rpc/servers/socket_runner'
|
@@ -244,7 +243,7 @@ module Protobuf
|
|
244
243
|
"pid #{::Process.pid} -- #{@runner_mode} RPC Server listening at #{options.host}:#{options.port}"
|
245
244
|
}
|
246
245
|
|
247
|
-
::
|
246
|
+
::ActiveSupport::Notifications.instrument("after_server_bind")
|
248
247
|
end
|
249
248
|
end
|
250
249
|
end
|
data/lib/protobuf/lifecycle.rb
CHANGED
@@ -1,26 +1,35 @@
|
|
1
1
|
module Protobuf
|
2
2
|
class Lifecycle
|
3
|
+
include ::Protobuf::Logger::LogMethods
|
3
4
|
|
4
5
|
def self.register( event_name, &blk )
|
5
6
|
raise "Lifecycle register must have a block" unless block_given?
|
7
|
+
|
6
8
|
event_name = normalized_event_name( event_name )
|
7
9
|
|
8
|
-
|
9
|
-
|
10
|
+
if ::Protobuf.print_deprecation_warnings?
|
11
|
+
$stderr.puts <<-ERROR
|
12
|
+
[DEPRECATED] ::Protobuf::Lifecycle has been deprecated and will be removed in a future version.
|
13
|
+
Use ::ActiveSupport::Notifications.subscribe('#{event_name}')
|
14
|
+
ERROR
|
15
|
+
end
|
16
|
+
|
17
|
+
::ActiveSupport::Notifications.subscribe(event_name) do |name, start, finish, id, args|
|
18
|
+
blk.call(*args)
|
19
|
+
end
|
10
20
|
end
|
11
21
|
|
12
22
|
def self.trigger( event_name, *args )
|
23
|
+
if ::Protobuf.print_deprecation_warnings?
|
24
|
+
$stderr.puts <<-ERROR
|
25
|
+
[DEPRECATED] ::Protobuf::Lifecycle has been deprecated and will be removed in a future version.
|
26
|
+
Use ::ActiveSupport::Notifications.instrument(...)
|
27
|
+
ERROR
|
28
|
+
end
|
29
|
+
|
13
30
|
event_name = normalized_event_name( event_name )
|
14
31
|
|
15
|
-
|
16
|
-
lifecycle_events[ event_name ].each do |block|
|
17
|
-
if ! args.empty? && block.arity != 0
|
18
|
-
block.call(*args)
|
19
|
-
else
|
20
|
-
block.call
|
21
|
-
end
|
22
|
-
end
|
23
|
-
end
|
32
|
+
::ActiveSupport::Notifications.instrument(event_name, args)
|
24
33
|
end
|
25
34
|
|
26
35
|
def self.normalized_event_name( event_name )
|
@@ -5,7 +5,6 @@ require 'set'
|
|
5
5
|
require 'thread'
|
6
6
|
require 'timeout'
|
7
7
|
|
8
|
-
require 'protobuf/lifecycle'
|
9
8
|
require 'protobuf/rpc/dynamic_discovery.pb'
|
10
9
|
|
11
10
|
module Protobuf
|
@@ -239,7 +238,7 @@ module Protobuf
|
|
239
238
|
end
|
240
239
|
|
241
240
|
def trigger(action, listing)
|
242
|
-
::
|
241
|
+
::ActiveSupport::Notifications.instrument("directory.listing.#{action}", :listing => listing)
|
243
242
|
end
|
244
243
|
end
|
245
244
|
end
|
@@ -0,0 +1 @@
|
|
1
|
+
load 'protobuf/tasks/compile.rake'
|
@@ -0,0 +1,58 @@
|
|
1
|
+
require 'fileutils'
|
2
|
+
|
3
|
+
namespace :protobuf do
|
4
|
+
|
5
|
+
desc 'Clean & Compile the protobuf source to ruby classes. Pass PB_NO_CLEAN=1 if you do not want to force-clean first.'
|
6
|
+
task :compile, [ :package, :source, :destination, :plugin ] do |tasks, args|
|
7
|
+
args.with_defaults(:destination => 'lib')
|
8
|
+
args.with_defaults(:source => 'definitions')
|
9
|
+
args.with_defaults(:plugin => 'ruby')
|
10
|
+
|
11
|
+
unless do_not_clean?
|
12
|
+
force_clean!
|
13
|
+
::Rake::Task[:clean].invoke(args[:package], args[:destination])
|
14
|
+
end
|
15
|
+
|
16
|
+
command = []
|
17
|
+
command << "protoc"
|
18
|
+
command << "--#{args[:plugin]}_out=#{args[:destination]}"
|
19
|
+
command << "-I #{args[:source]}"
|
20
|
+
command << "#{args[:source]}/#{args[:package]}/*.proto"
|
21
|
+
command << "#{args[:source]}/#{args[:package]}/**/*.proto"
|
22
|
+
full_command = command.join(' ')
|
23
|
+
|
24
|
+
puts full_command
|
25
|
+
exec(full_command)
|
26
|
+
end
|
27
|
+
|
28
|
+
desc 'Clean the generated *.pb.rb files from the destination package. Pass PB_FORCE_CLEAN=1 to skip confirmation step.'
|
29
|
+
task :clean, [ :package, :destination ] do |task, args|
|
30
|
+
args.with_defaults(:destination => 'lib')
|
31
|
+
|
32
|
+
files_to_clean = ::File.join(args[:destination], args[:package], '**', '*.pb.rb')
|
33
|
+
|
34
|
+
if force_clean? || permission_to_clean?(files_to_clean)
|
35
|
+
::Dir.glob(files_to_clean).each do |file|
|
36
|
+
::FileUtils.rm(file)
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
def do_not_clean?
|
42
|
+
! ::ENV.key?('PB_NO_CLEAN')
|
43
|
+
end
|
44
|
+
|
45
|
+
def force_clean?
|
46
|
+
::ENV.key?('PB_FORCE_CLEAN')
|
47
|
+
end
|
48
|
+
|
49
|
+
def force_clean!
|
50
|
+
::ENV['PB_FORCE_CLEAN'] = '1'
|
51
|
+
end
|
52
|
+
|
53
|
+
def permission_to_clean?(files_to_clean)
|
54
|
+
puts "Do you really want to remove files matching pattern #{files_to_clean}? (y/n)"
|
55
|
+
::STDIN.gets.chomp =~ /y(es)?/i
|
56
|
+
end
|
57
|
+
|
58
|
+
end
|
data/lib/protobuf/version.rb
CHANGED
@@ -9,13 +9,13 @@ describe ::Protobuf::CLI do
|
|
9
9
|
|
10
10
|
let(:sock_runner) {
|
11
11
|
runner = double("SocketRunner", :register_signals => nil)
|
12
|
-
runner.stub(:run) { ::
|
12
|
+
runner.stub(:run) { ::ActiveSupport::Notifications.publish( "after_server_bind" ) }
|
13
13
|
runner
|
14
14
|
}
|
15
15
|
|
16
16
|
let(:zmq_runner) {
|
17
17
|
runner = double "ZmqRunner", register_signals: nil
|
18
|
-
runner.stub(:run) { ::
|
18
|
+
runner.stub(:run) { ::ActiveSupport::Notifications.publish( "after_server_bind" ) }
|
19
19
|
runner
|
20
20
|
}
|
21
21
|
|
@@ -5,23 +5,12 @@ describe ::Protobuf::Lifecycle do
|
|
5
5
|
subject { described_class }
|
6
6
|
|
7
7
|
before(:each) do
|
8
|
-
|
8
|
+
::ActiveSupport::Notifications.notifier = ::ActiveSupport::Notifications::Fanout.new
|
9
9
|
end
|
10
10
|
|
11
11
|
it "registers a string as the event_name" do
|
12
|
-
|
13
|
-
subject.register("something")
|
14
|
-
true
|
15
|
-
end
|
16
|
-
}.to change { subject.lifecycle_events.size }.by(1)
|
17
|
-
end
|
18
|
-
|
19
|
-
it "registers a symbol as the event_name" do
|
20
|
-
expect {
|
21
|
-
subject.register("something") do
|
22
|
-
true
|
23
|
-
end
|
24
|
-
}.to change { subject.lifecycle_events.size }.by(1)
|
12
|
+
::ActiveSupport::Notifications.should_receive(:subscribe).with("something")
|
13
|
+
subject.register("something") { true }
|
25
14
|
end
|
26
15
|
|
27
16
|
it "only registers blocks for event callbacks" do
|
@@ -56,10 +56,9 @@ describe ::Protobuf::Rpc::ServiceDirectory do
|
|
56
56
|
end
|
57
57
|
|
58
58
|
def expect_event_trigger(event)
|
59
|
-
::
|
60
|
-
.should_receive(:
|
61
|
-
.with(event,
|
62
|
-
an_instance_of(::Protobuf::Rpc::ServiceDirectory::Listing))
|
59
|
+
::ActiveSupport::Notifications
|
60
|
+
.should_receive(:instrument)
|
61
|
+
.with(event, hash_including(:listing => an_instance_of(::Protobuf::Rpc::ServiceDirectory::Listing)))
|
63
62
|
.once
|
64
63
|
end
|
65
64
|
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: protobuf
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.8.
|
4
|
+
version: 2.8.9
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- BJ Neilsen
|
@@ -10,7 +10,7 @@ authors:
|
|
10
10
|
autorequire:
|
11
11
|
bindir: bin
|
12
12
|
cert_chain: []
|
13
|
-
date:
|
13
|
+
date: 2014-02-06 00:00:00.000000000 Z
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
16
16
|
name: activesupport
|
@@ -193,6 +193,7 @@ files:
|
|
193
193
|
- lib/protobuf.rb
|
194
194
|
- lib/protobuf/cli.rb
|
195
195
|
- lib/protobuf/code_generator.rb
|
196
|
+
- lib/protobuf/descriptors.rb
|
196
197
|
- lib/protobuf/descriptors/google/protobuf/compiler/plugin.pb.rb
|
197
198
|
- lib/protobuf/descriptors/google/protobuf/descriptor.pb.rb
|
198
199
|
- lib/protobuf/enum.rb
|
@@ -269,6 +270,8 @@ files:
|
|
269
270
|
- lib/protobuf/rpc/service_filters.rb
|
270
271
|
- lib/protobuf/rpc/stat.rb
|
271
272
|
- lib/protobuf/socket.rb
|
273
|
+
- lib/protobuf/tasks.rb
|
274
|
+
- lib/protobuf/tasks/compile.rake
|
272
275
|
- lib/protobuf/version.rb
|
273
276
|
- lib/protobuf/wire_type.rb
|
274
277
|
- lib/protobuf/zmq.rb
|