stark 0.7.0 → 0.8.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,10 @@
1
+ ---
2
+ script: rake travis
3
+ before_script:
4
+ - gem install hoe-travis --no-rdoc --no-ri
5
+ - rake travis:before -t
6
+ language: ruby
7
+ rvm:
8
+ - 1.8.7
9
+ - 1.9.2
10
+ - 1.9.3
@@ -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:
@@ -1,18 +1,23 @@
1
1
  .autotest
2
+ .gemtest
3
+ .travis.yml
2
4
  History.txt
3
5
  Manifest.txt
4
- README.txt
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
@@ -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 out = ARGV.shift
16
- out = File.open out, "w"
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
- ruby.run ast
23
+ begin
24
+ ruby.run ast
25
+ rescue
26
+ if file
27
+ out.close
28
+ File.unlink file
29
+ end
30
+ raise
31
+ end
@@ -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
+
@@ -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
+
@@ -0,0 +1,9 @@
1
+ struct Healthcheck {
2
+ 1: bool ok,
3
+ 2: string message
4
+ }
5
+
6
+ service Health {
7
+ Healthcheck check()
8
+ }
9
+
@@ -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
+