stark 0.7.0 → 0.8.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.travis.yml +10 -0
- data/History.txt +19 -0
- data/Manifest.txt +17 -3
- data/README.md +164 -0
- data/Rakefile +4 -1
- data/bin/stark +11 -3
- data/examples/README.md +114 -0
- data/examples/client.rb +13 -0
- data/examples/health.thrift +9 -0
- data/examples/server.rb +18 -0
- data/lib/stark.rb +16 -2
- data/lib/stark/ast.rb +5 -0
- data/lib/stark/client.rb +3 -67
- data/lib/stark/exception.rb +9 -9
- data/lib/stark/processor.rb +13 -52
- data/lib/stark/protocol_helpers.rb +161 -0
- data/lib/stark/raw_parser.rb +75 -14
- data/lib/stark/ruby.rb +267 -248
- data/lib/stark/struct.rb +37 -26
- data/lib/stark/thrift.kpeg +6 -4
- data/stark.gemspec +15 -15
- data/test/ThriftSpec.thrift +4 -0
- data/test/comments.thrift +15 -0
- data/test/leg.rb +0 -2
- data/test/parsing_error.thrift +5 -0
- data/test/properties.thrift +9 -0
- data/test/test_client.rb +116 -241
- data/test/test_coerce_strings.rb +187 -0
- data/test/test_helper.rb +113 -0
- data/test/test_marshal.rb +131 -0
- data/test/test_parser.rb +61 -0
- data/test/test_ruby.rb +148 -9
- data/test/test_server.rb +96 -212
- data/test/test_stark.rb +67 -0
- data/test/types.thrift +49 -0
- data/test/users.thrift +16 -0
- metadata +33 -15
- data/README.txt +0 -67
- data/lib/stark/converters.rb +0 -188
- data/lib/stark/field.rb +0 -27
data/.travis.yml
ADDED
data/History.txt
CHANGED
@@ -1,3 +1,22 @@
|
|
1
|
+
=== 0.8.0 / 2013-05-22
|
2
|
+
|
3
|
+
* 9 new features:
|
4
|
+
|
5
|
+
* Allow circular definitions
|
6
|
+
* Add attr_accessor for structs
|
7
|
+
* Add map and set support
|
8
|
+
* Support structs in lists
|
9
|
+
* Add dotted namespace support
|
10
|
+
* Only serialize fields that are present
|
11
|
+
* Add coercion to/from strings on read
|
12
|
+
* Add coercion and type checking on write
|
13
|
+
* Add Struct#[] and Struct#to_hash
|
14
|
+
|
15
|
+
* 2 bugfixes:
|
16
|
+
|
17
|
+
* Fixes to support comments in more places
|
18
|
+
* Catch and log unexpected exceptions
|
19
|
+
|
1
20
|
=== 0.7.0 / 2013-03-04
|
2
21
|
|
3
22
|
* 5 bugfixes:
|
data/Manifest.txt
CHANGED
@@ -1,18 +1,23 @@
|
|
1
1
|
.autotest
|
2
|
+
.gemtest
|
3
|
+
.travis.yml
|
2
4
|
History.txt
|
3
5
|
Manifest.txt
|
4
|
-
README.
|
6
|
+
README.md
|
5
7
|
Rakefile
|
6
8
|
bin/stark
|
9
|
+
examples/README.md
|
10
|
+
examples/client.rb
|
11
|
+
examples/health.thrift
|
12
|
+
examples/server.rb
|
7
13
|
lib/stark.rb
|
8
14
|
lib/stark/ast.rb
|
9
15
|
lib/stark/client.rb
|
10
|
-
lib/stark/converters.rb
|
11
16
|
lib/stark/exception.rb
|
12
|
-
lib/stark/field.rb
|
13
17
|
lib/stark/log_transport.rb
|
14
18
|
lib/stark/parser.rb
|
15
19
|
lib/stark/processor.rb
|
20
|
+
lib/stark/protocol_helpers.rb
|
16
21
|
lib/stark/raw_parser.rb
|
17
22
|
lib/stark/ruby.rb
|
18
23
|
lib/stark/struct.rb
|
@@ -20,6 +25,7 @@ lib/stark/thrift.kpeg
|
|
20
25
|
stark.gemspec
|
21
26
|
test/ThriftSpec.thrift
|
22
27
|
test/blah.thrift
|
28
|
+
test/comments.thrift
|
23
29
|
test/gen-rb/profile_constants.rb
|
24
30
|
test/gen-rb/profile_types.rb
|
25
31
|
test/gen-rb/user_storage.rb
|
@@ -28,8 +34,16 @@ test/leg.rb
|
|
28
34
|
test/legacy_profile/profile_constants.rb
|
29
35
|
test/legacy_profile/profile_types.rb
|
30
36
|
test/legacy_profile/user_storage.rb
|
37
|
+
test/parsing_error.thrift
|
31
38
|
test/profile.thrift
|
39
|
+
test/properties.thrift
|
32
40
|
test/test_client.rb
|
41
|
+
test/test_coerce_strings.rb
|
42
|
+
test/test_helper.rb
|
43
|
+
test/test_marshal.rb
|
33
44
|
test/test_parser.rb
|
34
45
|
test/test_ruby.rb
|
35
46
|
test/test_server.rb
|
47
|
+
test/test_stark.rb
|
48
|
+
test/types.thrift
|
49
|
+
test/users.thrift
|
data/README.md
ADDED
@@ -0,0 +1,164 @@
|
|
1
|
+
# stark [![Build Status](https://travis-ci.org/evanphx/stark.png)](https://travis-ci.org/evanphx/stark)
|
2
|
+
|
3
|
+
* http://github.com/evanphx/stark
|
4
|
+
|
5
|
+
## DESCRIPTION:
|
6
|
+
|
7
|
+
Optimized thrift bindings for ruby.
|
8
|
+
|
9
|
+
## FEATURES/PROBLEMS:
|
10
|
+
|
11
|
+
* Generates much more straightforward code for thrift clients and servers
|
12
|
+
than the default thrift bindings for ruby.
|
13
|
+
|
14
|
+
## SYNOPSIS:
|
15
|
+
|
16
|
+
```
|
17
|
+
$ stark service.thrift service.rb
|
18
|
+
```
|
19
|
+
|
20
|
+
```ruby
|
21
|
+
require 'service'
|
22
|
+
```
|
23
|
+
|
24
|
+
OR
|
25
|
+
|
26
|
+
```ruby
|
27
|
+
Stark.materialize "service.thrift"
|
28
|
+
```
|
29
|
+
|
30
|
+
Use `Service::Client` and
|
31
|
+
[`Service::Processor`](http://thrift.apache.org/docs/concepts/) like the default thrift
|
32
|
+
docs describe them.
|
33
|
+
|
34
|
+
## REQUIREMENTS:
|
35
|
+
|
36
|
+
* thrift gem
|
37
|
+
* .thrift files
|
38
|
+
|
39
|
+
## INSTALL:
|
40
|
+
|
41
|
+
* gem install stark
|
42
|
+
|
43
|
+
|
44
|
+
## More in depth
|
45
|
+
|
46
|
+
The two main advantages of using Stark are that it allows you to not
|
47
|
+
have to convert thrift files ahead of time and the generated Ruby code is of
|
48
|
+
higher quality than the output of the Thrift Ruby gem.
|
49
|
+
|
50
|
+
### How to
|
51
|
+
|
52
|
+
When using `Stark.materialize` on a `.thrift` file, the file gets parsed
|
53
|
+
and converted into Ruby code that is available right away for you to
|
54
|
+
use.
|
55
|
+
|
56
|
+
Lets take this example thrift file:
|
57
|
+
|
58
|
+
```
|
59
|
+
struct User {
|
60
|
+
1: required i32 id
|
61
|
+
2: string firstName
|
62
|
+
3: string lastName
|
63
|
+
}
|
64
|
+
|
65
|
+
exception UserNotFound {
|
66
|
+
1: i32 errorCode
|
67
|
+
2: string errorMessage
|
68
|
+
}
|
69
|
+
|
70
|
+
service GetUser {
|
71
|
+
User fetchUser(1: string email) throws (1: UserNotFound e)
|
72
|
+
}
|
73
|
+
```
|
74
|
+
|
75
|
+
Stark will generate the equivalent of the following code:
|
76
|
+
|
77
|
+
```ruby
|
78
|
+
class User < Stark::Struct
|
79
|
+
attr_reader :id, :firstName, :lastName
|
80
|
+
end
|
81
|
+
|
82
|
+
class UserNotFound < Stark::Exception
|
83
|
+
attr_reader :errorCode, :errorMessage
|
84
|
+
end
|
85
|
+
|
86
|
+
module GetUser
|
87
|
+
|
88
|
+
class Client < Stark::Client
|
89
|
+
def fetchUser(email)
|
90
|
+
# code to make the RPC call, handle errors etc..
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
class Processor < Stark::Processor
|
95
|
+
def process_fetchUser(seqid, ip, op)
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
end
|
100
|
+
```
|
101
|
+
|
102
|
+
#### Namespacing
|
103
|
+
|
104
|
+
While the generated code above is great, it might conflict with code you
|
105
|
+
already have in your application. To avoid conflicts, you can namespace
|
106
|
+
your materialized thrift examples.
|
107
|
+
|
108
|
+
```ruby
|
109
|
+
module MyApp; end
|
110
|
+
Stark.materialize "example.thrift", MyApp
|
111
|
+
```
|
112
|
+
|
113
|
+
The newly generated `GetUser` class is now generated under the provided
|
114
|
+
namespace: `MyApp::GetUser`.
|
115
|
+
|
116
|
+
Note that materializing a thrift file from within a module or a class
|
117
|
+
will still generate the code at the top level unless you specify a
|
118
|
+
namespace.
|
119
|
+
|
120
|
+
|
121
|
+
### Debugging
|
122
|
+
|
123
|
+
Spark will output some valuable (albeit verbose) debugging information
|
124
|
+
if you set the `STARK_DEBUG` environment variable.
|
125
|
+
|
126
|
+
```
|
127
|
+
$ STARK_DEBUG=true ruby code_using_stark.rb
|
128
|
+
```
|
129
|
+
|
130
|
+
## DEVELOPERS:
|
131
|
+
|
132
|
+
After checking out the source, run:
|
133
|
+
|
134
|
+
```
|
135
|
+
$ rake newb
|
136
|
+
```
|
137
|
+
|
138
|
+
This task will install any missing dependencies, run the tests/specs,
|
139
|
+
and generate the RDoc.
|
140
|
+
|
141
|
+
## LICENSE:
|
142
|
+
|
143
|
+
(The MIT License)
|
144
|
+
|
145
|
+
Copyright (c) 2013 Evan Phoenix
|
146
|
+
|
147
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
148
|
+
a copy of this software and associated documentation files (the
|
149
|
+
'Software'), to deal in the Software without restriction, including
|
150
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
151
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
152
|
+
permit persons to whom the Software is furnished to do so, subject to
|
153
|
+
the following conditions:
|
154
|
+
|
155
|
+
The above copyright notice and this permission notice shall be
|
156
|
+
included in all copies or substantial portions of the Software.
|
157
|
+
|
158
|
+
THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
|
159
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
160
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
161
|
+
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
162
|
+
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
163
|
+
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
164
|
+
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/Rakefile
CHANGED
@@ -1,8 +1,10 @@
|
|
1
1
|
# -*- ruby -*-
|
2
2
|
|
3
|
-
require 'rubygems'
|
4
3
|
require 'hoe'
|
5
4
|
|
5
|
+
# Don't turn on warnings, output is very ugly w/ generated code
|
6
|
+
Hoe::RUBY_FLAGS.sub! /-w/, ''
|
7
|
+
|
6
8
|
Hoe.plugin :travis
|
7
9
|
Hoe.plugin :gemspec
|
8
10
|
Hoe.plugin :git
|
@@ -11,6 +13,7 @@ Hoe.spec 'stark' do
|
|
11
13
|
developer('Evan Phoenix', 'evan@phx.io')
|
12
14
|
|
13
15
|
dependency "thrift", "~> 0.9.0"
|
16
|
+
readme_file = "README.md"
|
14
17
|
end
|
15
18
|
|
16
19
|
task :parser do
|
data/bin/stark
CHANGED
@@ -12,12 +12,20 @@ end
|
|
12
12
|
|
13
13
|
ast = Stark::Parser.ast File.read(file)
|
14
14
|
|
15
|
-
if
|
16
|
-
out = File.open
|
15
|
+
if file = ARGV.shift
|
16
|
+
out = File.open file, "w"
|
17
17
|
else
|
18
18
|
out = STDOUT
|
19
19
|
end
|
20
20
|
|
21
21
|
ruby = Stark::Ruby.new out
|
22
22
|
|
23
|
-
|
23
|
+
begin
|
24
|
+
ruby.run ast
|
25
|
+
rescue
|
26
|
+
if file
|
27
|
+
out.close
|
28
|
+
File.unlink file
|
29
|
+
end
|
30
|
+
raise
|
31
|
+
end
|
data/examples/README.md
ADDED
@@ -0,0 +1,114 @@
|
|
1
|
+
Building a network service and client with Stark
|
2
|
+
================================================
|
3
|
+
|
4
|
+
Writing a service with Stark isn't hard. Wiring up the Thrift network stuff is
|
5
|
+
a little challenging, but knowing where to start helps.
|
6
|
+
|
7
|
+
Running the examples
|
8
|
+
--------------------
|
9
|
+
|
10
|
+
From the root of the stark repo:
|
11
|
+
|
12
|
+
1. `$ ruby -Ilib -Iexamples examples/server.rb &`
|
13
|
+
1. `$ ruby -Ilib -Iexamples examples/client.rb`
|
14
|
+
|
15
|
+
Write the Thrift IDL
|
16
|
+
--------------------
|
17
|
+
|
18
|
+
The first thing you need to do is write a definition for your Thrift service.
|
19
|
+
Here are some good examples:
|
20
|
+
|
21
|
+
* `examples/health.thrift`: a simple service with one procedure and one struct
|
22
|
+
* `test/profile.thrift`: a more sophisticated service for user profiles
|
23
|
+
* `test/ThriftSpec.thrift`: everything in Thrift, presented concisely
|
24
|
+
|
25
|
+
An example Thrift service
|
26
|
+
-------------------------
|
27
|
+
|
28
|
+
For the following examples, we'll use this service defintion:
|
29
|
+
|
30
|
+
```thrift
|
31
|
+
struct Healthcheck {
|
32
|
+
1: bool ok,
|
33
|
+
2: string message
|
34
|
+
}
|
35
|
+
|
36
|
+
service Health {
|
37
|
+
Healthcheck check()
|
38
|
+
}
|
39
|
+
```
|
40
|
+
|
41
|
+
This defines a service with one message, `check` that returns a `Healthcheck`
|
42
|
+
struct.
|
43
|
+
|
44
|
+
Write a client
|
45
|
+
--------------
|
46
|
+
|
47
|
+
Using Stark, you can avoid the need to generate and track sources generated
|
48
|
+
from your Thrift IDL. A simple Thrift client looks like this:
|
49
|
+
|
50
|
+
```ruby
|
51
|
+
require 'thrift'
|
52
|
+
require 'stark'
|
53
|
+
|
54
|
+
Stark.materialize "examples/health.thrift"
|
55
|
+
|
56
|
+
socket = Thrift::UNIXSocket.new('/tmp/health_sock').tap { |s| s.open }
|
57
|
+
transport = Thrift::IOStreamTransport.new socket.to_io, socket.to_io
|
58
|
+
proto = Thrift::BinaryProtocol.new transport
|
59
|
+
client = Health::Client.new proto, proto
|
60
|
+
|
61
|
+
result = client.check
|
62
|
+
```
|
63
|
+
|
64
|
+
For your own purposes, you'll probably use a different kind of socket (one of
|
65
|
+
the TCP-based ones) and your client class will be different. You probably won't need to tinker with the transport and protocol until you've got services in
|
66
|
+
production.
|
67
|
+
|
68
|
+
Write a service
|
69
|
+
---------------
|
70
|
+
|
71
|
+
A Thrift service using Stark has a lot of symmetry to the client. A simple
|
72
|
+
service looks like this:
|
73
|
+
|
74
|
+
```ruby
|
75
|
+
require 'thrift'
|
76
|
+
require 'stark'
|
77
|
+
|
78
|
+
Stark.materialize "examples/health.thrift"
|
79
|
+
|
80
|
+
class Health::Handler
|
81
|
+
|
82
|
+
def check
|
83
|
+
Healthcheck.new('ok' => true, "message" => "OK")
|
84
|
+
end
|
85
|
+
|
86
|
+
end
|
87
|
+
|
88
|
+
transport = Thrift::UNIXServerSocket.new '/tmp/health_sock'
|
89
|
+
processor = Health::Processor.new Health::Handler.new
|
90
|
+
server = Thrift::SimpleServer.new processor, transport
|
91
|
+
server.serve
|
92
|
+
```
|
93
|
+
|
94
|
+
There are a few more moving parts here. We start off similar, requiring `stark`
|
95
|
+
and `thrift`, then dynamically creating the Ruby classes for our service via
|
96
|
+
`Stark.materialize`. Next we define a handler class that implements the logic
|
97
|
+
of our service. It defines the `check` method from our service. We then create
|
98
|
+
a transport and processor for our service and hook it up to a server class
|
99
|
+
provided by the `thrift` gem. Calling `serve` starts the server loop.
|
100
|
+
|
101
|
+
Not too hard!
|
102
|
+
|
103
|
+
Where to go next?
|
104
|
+
-----------------
|
105
|
+
|
106
|
+
* Read up on [Thrift concepts](http://thrift.apache.org/docs/concepts/), it
|
107
|
+
will come in handy as you implement your own services and clients.
|
108
|
+
* Try writing your own service.
|
109
|
+
* Lots of people are already implementing HTTP services. Luckily, stark can
|
110
|
+
help you make the transition from HTTP-based services. You can use
|
111
|
+
[stark-http](https://github.com/evanphx/stark-http) to write Thrift clients
|
112
|
+
over HTTP and [stark-rack](https://github.com/evanphx/stark-rack) to
|
113
|
+
implement Thrift services over HTTP.
|
114
|
+
|
data/examples/client.rb
ADDED
@@ -0,0 +1,13 @@
|
|
1
|
+
require 'thrift'
|
2
|
+
require 'stark'
|
3
|
+
|
4
|
+
Stark.materialize "examples/health.thrift"
|
5
|
+
|
6
|
+
socket = Thrift::UNIXSocket.new('/tmp/health_sock').tap { |s| s.open }
|
7
|
+
transport = Thrift::IOStreamTransport.new socket.to_io, socket.to_io
|
8
|
+
proto = Thrift::BinaryProtocol.new transport
|
9
|
+
client = Health::Client.new proto, proto
|
10
|
+
|
11
|
+
result = client.check
|
12
|
+
p [result.ok, result.message]
|
13
|
+
|
data/examples/server.rb
ADDED
@@ -0,0 +1,18 @@
|
|
1
|
+
require 'thrift'
|
2
|
+
require 'stark'
|
3
|
+
|
4
|
+
Stark.materialize "examples/health.thrift"
|
5
|
+
|
6
|
+
class Health::Handler
|
7
|
+
|
8
|
+
def check
|
9
|
+
Healthcheck.new('ok' => true, "message" => "OK")
|
10
|
+
end
|
11
|
+
|
12
|
+
end
|
13
|
+
|
14
|
+
transport = Thrift::UNIXServerSocket.new '/tmp/health_sock'
|
15
|
+
processor = Health::Processor.new Health::Handler.new
|
16
|
+
server = Thrift::SimpleServer.new processor, transport
|
17
|
+
server.serve
|
18
|
+
|