stark 0.7.0 → 0.8.0
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/.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 [](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
|
+
|