thrifty 0.0.1

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/.gitignore ADDED
@@ -0,0 +1,17 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in thrifty.gemspec
4
+ gemspec
data/LICENSE.txt ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2013 Greg Brockman
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,30 @@
1
+ # Thrifty
2
+
3
+ Tired of manually regenerating your Thrift interface code every time
4
+ the definition changes? Thrifty manages your Thrift interface
5
+ definitions behind the scenes.
6
+
7
+ ## Usage
8
+
9
+ ```ruby
10
+ require 'thrifty'
11
+ Thrifty.register('my_interface.thrift')
12
+
13
+ Thrifty.require('generated_service')
14
+ GeneratedService.do_things
15
+ ```
16
+
17
+ See the examples directory for a complete working example.
18
+
19
+ ## Caveats
20
+
21
+ You must have a working thrift compiler on your PATH. (That is, you
22
+ should be able to just type 'thrift'.) Thrifty does not currently
23
+ statically check that this is the case.
24
+
25
+ ## TODO
26
+
27
+ - Add a precompile mode, similar to how the Rails asset pipeline
28
+ works.
29
+ - Statically ensure there's a thrift compiler on the PATH.
30
+ - Autorequire of all generated Thrift files?
data/Rakefile ADDED
@@ -0,0 +1 @@
1
+ require "bundler/gem_tasks"
@@ -0,0 +1,3 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gem 'thrifty'
@@ -0,0 +1,15 @@
1
+ Simple client/server example from using the Thrift definition file
2
+ from http://thrift.apache.org/.
3
+
4
+ To test it out, do the following:
5
+
6
+ - Run 'bundle'
7
+ - Run 'bundle exec ruby server.rb' in one terminal. Leave it running.
8
+ - Run 'bundle exec ruby client.rb' in another terminal.
9
+
10
+ You should see something like the following from the client:
11
+
12
+ ```
13
+ Storing <UserProfile uid:1234, name:"my name!", blurb:"your name!">
14
+ Retrieved <UserProfile uid:1234, name:"my name!", blurb:"your name!">
15
+ ```
@@ -0,0 +1,22 @@
1
+ require 'thrifty'
2
+ Thrifty.register('service.thrift')
3
+ Thrifty.require('user_storage')
4
+
5
+ port = ARGV[0] || 9090
6
+
7
+ transport = Thrift::BufferedTransport.new(Thrift::Socket.new('127.0.0.1', 9090))
8
+ protocol = Thrift::BinaryProtocol.new(transport)
9
+ client = UserStorage::Client.new(protocol)
10
+
11
+ transport.open
12
+
13
+ profile = UserProfile.new
14
+ profile.uid = 1234
15
+ profile.name = 'my name!'
16
+ profile.blurb = 'your name!'
17
+
18
+ puts "Storing #{profile.inspect}"
19
+ client.store(profile)
20
+
21
+ retrieved = client.retrieve(1234)
22
+ puts "Retrieved #{retrieved.inspect}"
@@ -0,0 +1,26 @@
1
+ require 'thrifty'
2
+ Thrifty.register('service.thrift')
3
+ Thrifty.require('user_storage')
4
+
5
+ class UserStorageServer
6
+ def initialize
7
+ @store = {}
8
+ end
9
+
10
+ def store(user_profile)
11
+ @store[user_profile.uid] = user_profile
12
+ end
13
+
14
+ def retrieve(uid)
15
+ @store[uid]
16
+ end
17
+ end
18
+
19
+ handler = UserStorageServer.new
20
+ processor = UserStorage::Processor.new(handler)
21
+ transport = Thrift::ServerSocket.new(9090)
22
+ transportFactory = Thrift::BufferedTransportFactory.new()
23
+ server = Thrift::SimpleServer.new(processor, transport, transportFactory)
24
+
25
+ puts "Booting user storage server..."
26
+ server.serve
@@ -0,0 +1,10 @@
1
+ struct UserProfile {
2
+ 1: i32 uid,
3
+ 2: string name,
4
+ 3: string blurb
5
+ }
6
+ service UserStorage {
7
+ void store(1: UserProfile user),
8
+ UserProfile retrieve(1: i32 uid)
9
+ }
10
+
@@ -0,0 +1,84 @@
1
+ require 'digest/sha1'
2
+ require 'fileutils'
3
+ require 'rubysh'
4
+
5
+ module Thrifty
6
+ class ThriftFile
7
+ attr_reader :thrift_file
8
+
9
+ def initialize(thrift_file)
10
+ @thrift_file = thrift_file
11
+ end
12
+
13
+ def defines?(generated_file)
14
+ compile_once
15
+ File.exists?(File.join(build_directory, generated_file + '.rb'))
16
+ end
17
+
18
+ def require(generated_file)
19
+ compile_once
20
+ $:.unshift(build_directory)
21
+
22
+ begin
23
+ Thrifty.logger.info("Requiring #{generated_file.inspect}, generated from #{thrift_file.inspect}")
24
+ # Global require
25
+ super(generated_file)
26
+ ensure
27
+ # Not sure what to do if someone changed $: in the
28
+ # meanwhile. Could happen due a signal handler or something
29
+ # crazy like that.
30
+ if $:.first == build_directory
31
+ $:.shift
32
+ else
33
+ Thrifty.logger.error("Unexpected first element in load path; not removing #{build_directory.inspect}: #{$:.inspect}")
34
+ end
35
+ end
36
+ end
37
+
38
+ def compile_once
39
+ with_cache do
40
+ FileUtils.mkdir_p(build_directory)
41
+ Rubysh('thrift', '--gen', 'rb', '-out', build_directory, thrift_file).check_call
42
+ end
43
+ end
44
+
45
+ private
46
+
47
+ def with_cache(&blk)
48
+ raise "No such Thrift file #{thrift_file.inspect}" unless File.exists?(thrift_file)
49
+
50
+ # There's obviously a race if someone changes the file before
51
+ # the compiler runs, so we capture the sha1 up front so it'll at
52
+ # least be more likely to falsely invalidate the cache.
53
+ new_version = Digest::SHA1.file(thrift_file).to_s
54
+ cached_version = File.read(version_file) if File.exists?(version_file)
55
+
56
+ # cached_version will be nil if the cache doesn't exist, so always miss.
57
+ if new_version == cached_version
58
+ Thrifty.logger.debug("Using cached version")
59
+ return
60
+ end
61
+
62
+ Thrifty.logger.info("Compiling thrift file #{thrift_file} with SHA1 #{new_version} to #{build_directory}")
63
+ blk.call
64
+
65
+ File.open(version_file, 'w') {|f| f.write(new_version)}
66
+ end
67
+
68
+ def version_file
69
+ File.join(build_directory, 'VERSION')
70
+ end
71
+
72
+ def build_directory
73
+ # Use the basename for informational purposes, and the SHA1 for
74
+ # avoid collisions.
75
+ base = File.basename(thrift_file)
76
+ sha1 = Digest::SHA1.hexdigest(thrift_file)
77
+ File.join(basedir, "#{base}-#{sha1}")
78
+ end
79
+
80
+ def basedir
81
+ Thrifty.basedir
82
+ end
83
+ end
84
+ end
@@ -0,0 +1,3 @@
1
+ module Thrifty
2
+ VERSION = "0.0.1"
3
+ end
data/lib/thrifty.rb ADDED
@@ -0,0 +1,47 @@
1
+ require 'logger'
2
+ require 'tmpdir'
3
+
4
+ require 'thrift'
5
+
6
+ require 'thrifty/thrift_file'
7
+ require 'thrifty/version'
8
+
9
+ module Thrifty
10
+ @thrift_files = {}
11
+
12
+ def self.logger
13
+ @logger ||= begin
14
+ logger = Logger.new(STDOUT)
15
+ logger.level = Logger::ERROR
16
+ logger
17
+ end
18
+ end
19
+
20
+ def self.basedir
21
+ @basedir ||= Dir.tmpdir
22
+ end
23
+
24
+ def self.basedir=(basedir)
25
+ @basedir = basedir
26
+ end
27
+
28
+ def self.register(thrift_file)
29
+ raise "File already registered: #{thrift_file.inspect}" if @thrift_files.include?(thrift_file)
30
+ @thrift_files[thrift_file] = Thrifty::ThriftFile.new(thrift_file)
31
+ end
32
+
33
+ def self.require(generated_file)
34
+ definers = @thrift_files.values.select do |thrift_file|
35
+ thrift_file.defines?(generated_file)
36
+ end
37
+
38
+ if definers.length == 0
39
+ raise LoadError, "No registered thrift file defines #{generated_file.inspect}. Perhaps you forgot to run `Thrifty.register(thrift_file)`?"
40
+ elsif definers.length == 1
41
+ definer = definers.first
42
+ definer.require(generated_file)
43
+ else
44
+ raise LoadError, "Ambiguous generated file #{generated_file.inspect} defined in #{definers.map {|definer| definer.thrift_file.inspect}.join(', ')}"
45
+ end
46
+ end
47
+ end
data/thrifty.gemspec ADDED
@@ -0,0 +1,21 @@
1
+ # -*- encoding: utf-8 -*-
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'thrifty/version'
5
+
6
+ Gem::Specification.new do |gem|
7
+ gem.name = "thrifty"
8
+ gem.version = Thrifty::VERSION
9
+ gem.authors = ["Greg Brockman"]
10
+ gem.email = ["gdb@gregbrockman.com"]
11
+ gem.description = "Automatically compile Thrift definitions in Ruby"
12
+ gem.summary = "Begone manual compilation of Thrift definitions! Thrifty makes it easy to automatically manage your Thrift definitions."
13
+ gem.homepage = ""
14
+
15
+ gem.files = `git ls-files`.split($/)
16
+ gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
17
+ gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
18
+ gem.require_paths = ["lib"]
19
+ gem.add_dependency 'thrift'
20
+ gem.add_dependency 'rubysh'
21
+ end
metadata ADDED
@@ -0,0 +1,93 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: thrifty
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Greg Brockman
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2013-04-28 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: thrift
16
+ requirement: !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ! '>='
20
+ - !ruby/object:Gem::Version
21
+ version: '0'
22
+ type: :runtime
23
+ prerelease: false
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ! '>='
28
+ - !ruby/object:Gem::Version
29
+ version: '0'
30
+ - !ruby/object:Gem::Dependency
31
+ name: rubysh
32
+ requirement: !ruby/object:Gem::Requirement
33
+ none: false
34
+ requirements:
35
+ - - ! '>='
36
+ - !ruby/object:Gem::Version
37
+ version: '0'
38
+ type: :runtime
39
+ prerelease: false
40
+ version_requirements: !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ! '>='
44
+ - !ruby/object:Gem::Version
45
+ version: '0'
46
+ description: Automatically compile Thrift definitions in Ruby
47
+ email:
48
+ - gdb@gregbrockman.com
49
+ executables: []
50
+ extensions: []
51
+ extra_rdoc_files: []
52
+ files:
53
+ - .gitignore
54
+ - Gemfile
55
+ - LICENSE.txt
56
+ - README.md
57
+ - Rakefile
58
+ - examples/userdb/Gemfile
59
+ - examples/userdb/README.md
60
+ - examples/userdb/client.rb
61
+ - examples/userdb/server.rb
62
+ - examples/userdb/service.thrift
63
+ - lib/thrifty.rb
64
+ - lib/thrifty/thrift_file.rb
65
+ - lib/thrifty/version.rb
66
+ - thrifty.gemspec
67
+ homepage: ''
68
+ licenses: []
69
+ post_install_message:
70
+ rdoc_options: []
71
+ require_paths:
72
+ - lib
73
+ required_ruby_version: !ruby/object:Gem::Requirement
74
+ none: false
75
+ requirements:
76
+ - - ! '>='
77
+ - !ruby/object:Gem::Version
78
+ version: '0'
79
+ required_rubygems_version: !ruby/object:Gem::Requirement
80
+ none: false
81
+ requirements:
82
+ - - ! '>='
83
+ - !ruby/object:Gem::Version
84
+ version: '0'
85
+ requirements: []
86
+ rubyforge_project:
87
+ rubygems_version: 1.8.23
88
+ signing_key:
89
+ specification_version: 3
90
+ summary: Begone manual compilation of Thrift definitions! Thrifty makes it easy to
91
+ automatically manage your Thrift definitions.
92
+ test_files: []
93
+ has_rdoc: