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 +4 -4
- data/README.md +102 -0
- data/VERSION +1 -1
- data/examples/lookup_dns.go +48 -0
- data/examples/lookup_dns.rb +9 -0
- data/lib/quartz/go_process.rb +23 -8
- data/quartz.gemspec +8 -6
- metadata +20 -18
- data/README.rdoc +0 -18
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: d520e80d9a379cdb4307bb348bb432575e6d1b49
|
4
|
+
data.tar.gz: 3aff1a2208541befddf074d95555989f0dec15fe
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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
|
+
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
|
+
}
|
data/lib/quartz/go_process.rb
CHANGED
@@ -1,20 +1,35 @@
|
|
1
1
|
class Quartz::GoProcess
|
2
2
|
|
3
3
|
def initialize(opts)
|
4
|
-
@
|
5
|
-
ENV['QUARTZ_SOCKET'] = @
|
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
|
12
|
+
raise 'Missing go binary'
|
13
13
|
end
|
14
14
|
|
15
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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(
|
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.
|
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.
|
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.
|
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.
|
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.
|
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.
|
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.
|
89
|
+
- README.md
|
90
90
|
files:
|
91
|
-
-
|
92
|
-
-
|
91
|
+
- .document
|
92
|
+
- .rspec
|
93
93
|
- Gemfile
|
94
94
|
- Gemfile.lock
|
95
95
|
- LICENSE.txt
|
96
|
-
- README.
|
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.
|
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.
|