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.
@@ -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
+