quartz 0.0.1 → 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: ede307136d543e7451dd9328969152e7d9b29d81
4
- data.tar.gz: 01c7dceb7ea7859fda5a716566bca594cfb8c53a
3
+ metadata.gz: d520e80d9a379cdb4307bb348bb432575e6d1b49
4
+ data.tar.gz: 3aff1a2208541befddf074d95555989f0dec15fe
5
5
  SHA512:
6
- metadata.gz: cdfaebcd6fd90c55b8a9e2d11171827f15b92a5fe07d87cfe9306a28f222c1f803672a4fc7e704031b71d5a57daaf5db49e06448da8a9b6632836bc5bccae19c
7
- data.tar.gz: a015e450a1f9e6e19d32fed4b3a0ebaf5dd03e37842f8ebb813d65619ce28ed6799aeb09626c60f071a30397f9b06ea7d03f5df55b1afd318b52bdfe200e6032
6
+ metadata.gz: c00b4e411caff77ac6cbf23eeb921f27cd4fc98ccd73f5fd096c6913dace57037a995e38feeb58d4a8b46c06403a706c8093abf29ccbbc916b42556d442d4493
7
+ data.tar.gz: 7bbd949d31479cbe7aa5263245d09cc1650fc1024454f90b03d3047948ff24ed8e5d8bdea09c2071b13c5f84a33f81f304992ba36e4c4a9f0698521054b5f121
data/README.md ADDED
@@ -0,0 +1,102 @@
1
+ # quartz
2
+
3
+ Quartz enables you to call Go code from within your
4
+ Ruby code. This is accomplished by running a Go program
5
+ as a child process of your Ruby application and using UNIX domain sockets
6
+ for communication.
7
+
8
+ With this gem, you can now write performance critical code in Go, and that
9
+ code can be called from anywhere in a Ruby project.
10
+
11
+ To see some real world examples where Go can aid a Ruby project, please see
12
+ the `examples/` directory.
13
+
14
+ ## Defining exportable structs
15
+
16
+ Quartz shares Go code by exporting methods on a struct to Ruby.
17
+
18
+ Quartz requires that all arguments to exported struct methods be JSON-serializable
19
+ structs. Additionally, the arguments to an exported method should be of the form
20
+ `(A, *B)`, where `A` and `B` are struct types. The method should also return an error.
21
+ Here's an example of an exportable struct and method:
22
+
23
+ ```go
24
+ type Adder struct{}
25
+
26
+ type Args struct {
27
+ A int
28
+ B int
29
+ }
30
+
31
+ type Response struct {
32
+ Sum int
33
+ }
34
+
35
+ func (t *Adder) Add(args Args, response *Response) error {
36
+ *response = Response{args.A + args.B}
37
+ return nil
38
+ }
39
+ ```
40
+
41
+ ## Preparing a Quartz RPC server in Go
42
+
43
+ Instead of integrating Quartz into an existing Go application,
44
+ it is recommended that a new `go run`-able file is created
45
+ that explicitly defines the structs that should be available
46
+ to Ruby.
47
+
48
+ First, import the Go package:
49
+
50
+ ```go
51
+ import (
52
+ "github.com/DavidHuie/quartz/go/quartz"
53
+ )
54
+ ```
55
+
56
+ Quartz maintains most of Go's native RPC interface. Thus, export a struct
57
+ by calling this in your `main` function:
58
+
59
+ ```go
60
+ myAdder := &Adder{}
61
+ quartz.RegisterName("my_adder", myAdder)
62
+ ```
63
+
64
+ Once all structs have been declared, start the RPC server (this is a blocking call):
65
+
66
+ ```go
67
+ quartz.Start()
68
+ ```
69
+
70
+ ## In Ruby
71
+
72
+ Naturally:
73
+
74
+ ```shell
75
+ $ gem install quartz
76
+ ```
77
+
78
+ After you've found created a `go run`-able file, create a Go process wrapper that
79
+ points to that file:
80
+
81
+ ```ruby
82
+ require 'quartz'
83
+
84
+ go_process = Quartz::GoProcess.new(file_path: 'spec/test.go')
85
+ ```
86
+
87
+ Now, you can create a client:
88
+
89
+ ```ruby
90
+ client = Quartz::Client.new(go_process)
91
+ ```
92
+
93
+ To call a method on a struct:
94
+
95
+ ```ruby
96
+ client[:my_adder].call('Add', 'A' => 2, 'B' => 5)
97
+ # => { 'Sum' => 7 }
98
+ ```
99
+
100
+ ## Copyright
101
+
102
+ Copyright (c) 2014 David Huie. See LICENSE.txt for further details.
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.0.1
1
+ 0.0.2
@@ -0,0 +1,48 @@
1
+ package main
2
+
3
+ import (
4
+ "net"
5
+
6
+ "github.com/DavidHuie/quartz/go/quartz"
7
+ )
8
+
9
+ type Resolver struct{}
10
+
11
+ type FindIPsArgs struct {
12
+ Hostnames []string
13
+ }
14
+
15
+ type FindIPsResponse struct {
16
+ HostnameToIPs map[string][]net.IP
17
+ }
18
+
19
+ func (r *Resolver) FindIPs(args FindIPsArgs, response *FindIPsResponse) error {
20
+ *response = FindIPsResponse{}
21
+ response.HostnameToIPs = make(map[string][]net.IP)
22
+ c := make(chan bool)
23
+
24
+ for _, hostname := range args.Hostnames {
25
+ go func(h string) {
26
+ addrs, err := net.LookupIP(h)
27
+ if err != nil {
28
+ panic(err)
29
+ }
30
+
31
+ response.HostnameToIPs[h] = addrs
32
+
33
+ c <- true
34
+ }(hostname)
35
+ }
36
+
37
+ for i := 0; i < len(args.Hostnames); i++ {
38
+ <-c
39
+ }
40
+
41
+ return nil
42
+ }
43
+
44
+ func main() {
45
+ resolver := &Resolver{}
46
+ quartz.RegisterName("resolver", resolver)
47
+ quartz.Start()
48
+ }
@@ -0,0 +1,9 @@
1
+ require 'quartz'
2
+
3
+ go_process = Quartz::GoProcess.new(file_path: 'lookup_dns.go')
4
+ client = Quartz::Client.new(go_process)
5
+
6
+ puts client[:resolver].call('FindIPs',
7
+ 'Hostnames' => ['www.google.com',
8
+ 'www.facebook.com',
9
+ 'www.microsoft.com'])
@@ -1,20 +1,35 @@
1
1
  class Quartz::GoProcess
2
2
 
3
3
  def initialize(opts)
4
- @socket_name = "/tmp/quartz#{rand(10000)}.sock"
5
- ENV['QUARTZ_SOCKET'] = @socket_name
4
+ @socket_path = "/tmp/quartz#{rand(10000)}.sock"
5
+ ENV['QUARTZ_SOCKET'] = @socket_path
6
6
 
7
7
  if opts[:file_path]
8
8
  @go_process = Thread.new { `go run #{opts[:file_path]} }` }
9
9
  elsif opts[:bin_path]
10
10
  @go_process = Thread.new { `#{opts[:bin_path]} }` }
11
11
  else
12
- raise 'Missing go binary path'
12
+ raise 'Missing go binary'
13
13
  end
14
14
 
15
- sleep(1)
15
+ block_until_server_starts
16
+ end
17
+
18
+ def socket
19
+ Thread.current[:quartz_socket] ||= UNIXSocket.new(@socket_path)
20
+ end
16
21
 
17
- @socket = UNIXSocket.new(@socket_name)
22
+ def block_until_server_starts
23
+ max_retries = 10
24
+ retries = 0
25
+ delay = 0.1 # seconds
26
+
27
+ loop do
28
+ raise 'RPC server not starting' if retries > max_retries
29
+ return if File.exists?(@socket_path)
30
+ sleep(delay * retries * 2**retries)
31
+ retries += 1
32
+ end
18
33
  end
19
34
 
20
35
  def get_metadata
@@ -24,7 +39,7 @@ class Quartz::GoProcess
24
39
  'id' => 1
25
40
  }
26
41
 
27
- @socket.send(payload.to_json, 0)
42
+ socket.send(payload.to_json, 0)
28
43
  read
29
44
  end
30
45
 
@@ -39,14 +54,14 @@ class Quartz::GoProcess
39
54
  'id' => 1
40
55
  }
41
56
 
42
- @socket.send(payload.to_json, 0)
57
+ socket.send(payload.to_json, 0)
43
58
  read
44
59
  end
45
60
 
46
61
  MAX_MESSAGE_SIZE = 1_000_000_000 # Bytes
47
62
 
48
63
  def read
49
- JSON(@socket.recv(MAX_MESSAGE_SIZE))['result']
64
+ JSON(socket.recv(MAX_MESSAGE_SIZE))['result']
50
65
  end
51
66
 
52
67
  end
data/quartz.gemspec CHANGED
@@ -2,21 +2,20 @@
2
2
  # DO NOT EDIT THIS FILE DIRECTLY
3
3
  # Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
4
4
  # -*- encoding: utf-8 -*-
5
- # stub: quartz 0.0.1 ruby lib
5
+ # stub: quartz 0.0.2 ruby lib
6
6
 
7
7
  Gem::Specification.new do |s|
8
8
  s.name = "quartz"
9
- s.version = "0.0.1"
9
+ s.version = "0.0.2"
10
10
 
11
11
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
12
- s.require_paths = ["lib"]
13
12
  s.authors = ["David Huie"]
14
13
  s.date = "2014-06-16"
15
14
  s.description = "A gem for calling #golang code from ruby"
16
15
  s.email = "dahuie@gmail.com"
17
16
  s.extra_rdoc_files = [
18
17
  "LICENSE.txt",
19
- "README.rdoc"
18
+ "README.md"
20
19
  ]
21
20
  s.files = [
22
21
  ".document",
@@ -24,9 +23,11 @@ Gem::Specification.new do |s|
24
23
  "Gemfile",
25
24
  "Gemfile.lock",
26
25
  "LICENSE.txt",
27
- "README.rdoc",
26
+ "README.md",
28
27
  "Rakefile",
29
28
  "VERSION",
29
+ "examples/lookup_dns.go",
30
+ "examples/lookup_dns.rb",
30
31
  "go/quartz/quartz.go",
31
32
  "lib/quartz.rb",
32
33
  "lib/quartz/client.rb",
@@ -41,7 +42,8 @@ Gem::Specification.new do |s|
41
42
  ]
42
43
  s.homepage = "http://github.com/DavidHuie/quartz"
43
44
  s.licenses = ["MIT"]
44
- s.rubygems_version = "2.2.2"
45
+ s.require_paths = ["lib"]
46
+ s.rubygems_version = "2.1.11"
45
47
  s.summary = "A gem for calling #golang code from ruby"
46
48
 
47
49
  if s.respond_to? :specification_version then
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: quartz
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1
4
+ version: 0.0.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - David Huie
@@ -14,70 +14,70 @@ dependencies:
14
14
  name: rspec
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
- - - "~>"
17
+ - - ~>
18
18
  - !ruby/object:Gem::Version
19
19
  version: 2.8.0
20
20
  type: :development
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
- - - "~>"
24
+ - - ~>
25
25
  - !ruby/object:Gem::Version
26
26
  version: 2.8.0
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: rdoc
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
- - - "~>"
31
+ - - ~>
32
32
  - !ruby/object:Gem::Version
33
33
  version: '3.12'
34
34
  type: :development
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
- - - "~>"
38
+ - - ~>
39
39
  - !ruby/object:Gem::Version
40
40
  version: '3.12'
41
41
  - !ruby/object:Gem::Dependency
42
42
  name: bundler
43
43
  requirement: !ruby/object:Gem::Requirement
44
44
  requirements:
45
- - - "~>"
45
+ - - ~>
46
46
  - !ruby/object:Gem::Version
47
47
  version: '1.0'
48
48
  type: :development
49
49
  prerelease: false
50
50
  version_requirements: !ruby/object:Gem::Requirement
51
51
  requirements:
52
- - - "~>"
52
+ - - ~>
53
53
  - !ruby/object:Gem::Version
54
54
  version: '1.0'
55
55
  - !ruby/object:Gem::Dependency
56
56
  name: jeweler
57
57
  requirement: !ruby/object:Gem::Requirement
58
58
  requirements:
59
- - - "~>"
59
+ - - ~>
60
60
  - !ruby/object:Gem::Version
61
61
  version: 2.0.1
62
62
  type: :development
63
63
  prerelease: false
64
64
  version_requirements: !ruby/object:Gem::Requirement
65
65
  requirements:
66
- - - "~>"
66
+ - - ~>
67
67
  - !ruby/object:Gem::Version
68
68
  version: 2.0.1
69
69
  - !ruby/object:Gem::Dependency
70
70
  name: simplecov
71
71
  requirement: !ruby/object:Gem::Requirement
72
72
  requirements:
73
- - - ">="
73
+ - - '>='
74
74
  - !ruby/object:Gem::Version
75
75
  version: '0'
76
76
  type: :development
77
77
  prerelease: false
78
78
  version_requirements: !ruby/object:Gem::Requirement
79
79
  requirements:
80
- - - ">="
80
+ - - '>='
81
81
  - !ruby/object:Gem::Version
82
82
  version: '0'
83
83
  description: 'A gem for calling #golang code from ruby'
@@ -86,16 +86,18 @@ executables: []
86
86
  extensions: []
87
87
  extra_rdoc_files:
88
88
  - LICENSE.txt
89
- - README.rdoc
89
+ - README.md
90
90
  files:
91
- - ".document"
92
- - ".rspec"
91
+ - .document
92
+ - .rspec
93
93
  - Gemfile
94
94
  - Gemfile.lock
95
95
  - LICENSE.txt
96
- - README.rdoc
96
+ - README.md
97
97
  - Rakefile
98
98
  - VERSION
99
+ - examples/lookup_dns.go
100
+ - examples/lookup_dns.rb
99
101
  - go/quartz/quartz.go
100
102
  - lib/quartz.rb
101
103
  - lib/quartz/client.rb
@@ -117,17 +119,17 @@ require_paths:
117
119
  - lib
118
120
  required_ruby_version: !ruby/object:Gem::Requirement
119
121
  requirements:
120
- - - ">="
122
+ - - '>='
121
123
  - !ruby/object:Gem::Version
122
124
  version: '0'
123
125
  required_rubygems_version: !ruby/object:Gem::Requirement
124
126
  requirements:
125
- - - ">="
127
+ - - '>='
126
128
  - !ruby/object:Gem::Version
127
129
  version: '0'
128
130
  requirements: []
129
131
  rubyforge_project:
130
- rubygems_version: 2.2.2
132
+ rubygems_version: 2.1.11
131
133
  signing_key:
132
134
  specification_version: 4
133
135
  summary: 'A gem for calling #golang code from ruby'
data/README.rdoc DELETED
@@ -1,18 +0,0 @@
1
- = quartz
2
-
3
- A gem for calling #golang code from ruby
4
-
5
- == Contributing to quartz
6
-
7
- * Check out the latest master to make sure the feature hasn't been implemented or the bug hasn't been fixed yet.
8
- * Check out the issue tracker to make sure someone already hasn't requested it and/or contributed it.
9
- * Fork the project.
10
- * Start a feature/bugfix branch.
11
- * Commit and push until you are happy with your contribution.
12
- * Make sure to add tests for it. This is important so I don't break it in a future version unintentionally.
13
- * Please try not to mess with the Rakefile, version, or history. If you want to have your own version, or is otherwise necessary, that is fine, but please isolate to its own commit so I can cherry-pick around it.
14
-
15
- == Copyright
16
-
17
- Copyright (c) 2014 David Huie. See LICENSE.txt for
18
- further details.