quartz 0.1.0 → 0.2.0

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: 05b5dae726bdb30517440604cef9323e3f603977
4
- data.tar.gz: 0b29eb3c722db7dd97b38807b0801914c6bb7bbd
3
+ metadata.gz: 38e17e14fd92fe48bde386619caf1a6c290b382f
4
+ data.tar.gz: 67579895994930814c09d929af14a4df14e38a42
5
5
  SHA512:
6
- metadata.gz: 46f9a875047aeb19208991da607f1bfd21e2e747a660137aa9c75627e11ac0ced0b31d91faab36d565c19caa2c22fdd958c797e1136af5615e572c043fbc0c69
7
- data.tar.gz: 41b49e461b6859c33b4ab87bb6d8f7ff0ef483cacb83ea7317824b49f8b8c6bdd307535d73fd188db3d6db167d1944013eac6b5c5dad36b99446757ba78a524c
6
+ metadata.gz: 1be3464bd2d6dd945f2f7abc0d4da0551c362fa1d69011a35699daa515b325533f43b3acad5e1a91bd83bb30b8a141fe4daad5d626190fa3bfe13395d694cba9
7
+ data.tar.gz: dea73da76d59574c5b984e612b5ff1b97c8025db45c42edeb05b4560500521e54943704532c8a3abd187a63f27dab9d3a35d58d9b5a9bfe1da08eed0a6f3fe6b
data/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # quartz
2
2
 
3
- [![Build Status](https://travis-ci.org/DavidHuie/quartz.svg?branch=travis-ci-test)](https://travis-ci.org/DavidHuie/quartz)
3
+ [![Build Status](https://travis-ci.org/DavidHuie/quartz.svg?branch=master)](https://travis-ci.org/DavidHuie/quartz)
4
4
 
5
5
  Quartz enables you to call Go code from within your
6
6
  Ruby code. This is accomplished by running a Go program
@@ -43,7 +43,7 @@ func (t *Adder) Add(args Args, response *Response) error {
43
43
  ## Preparing a Quartz RPC server in Go
44
44
 
45
45
  Instead of integrating Quartz into an existing Go application,
46
- it is recommended to create a new `go run`-able file
46
+ it is recommended to create a new program
47
47
  that explicitly defines the structs that should be available
48
48
  to Ruby.
49
49
 
@@ -77,11 +77,18 @@ Naturally:
77
77
  $ gem install quartz
78
78
  ```
79
79
 
80
- After you've found created a `go run`-able file, create a Go client that
80
+ If you have a `go run`-able file, you can create a Go client that
81
81
  points to that file:
82
82
 
83
83
  ```ruby
84
- client = Quartz::Client.new(file_path: 'spec/test.go')
84
+ client = Quartz::Client.new(file_path: 'my_adder.go')
85
+ ```
86
+
87
+ If you compiled the Go program yourself, you can create a client
88
+ that points to the binary like this:
89
+
90
+ ```ruby
91
+ client = Quartz::Client.new(bin_path: 'my_adder_binary')
85
92
  ```
86
93
 
87
94
  To list exported structs:
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.1.0
1
+ 0.2.0
data/go/quartz/quartz.go CHANGED
@@ -118,8 +118,13 @@ func (q *Quartz) GetMetadata(_ interface{}, value *map[string]*StructMetadata) e
118
118
  }
119
119
 
120
120
  func init() {
121
+ socket_path := os.Getenv("QUARTZ_SOCKET")
122
+ if socket_path == "" {
123
+ socket_path = "/tmp/quartz.socket"
124
+ }
125
+
121
126
  var err error
122
- listener, err = net.Listen("unix", os.Getenv("QUARTZ_SOCKET"))
127
+ listener, err = net.Listen("unix", socket_path)
123
128
  if err != nil {
124
129
  panic(err)
125
130
  }
@@ -131,7 +136,7 @@ func init() {
131
136
 
132
137
  // Cleanup the socket file when the server is killed
133
138
  sigc := make(chan os.Signal)
134
- signal.Notify(sigc, os.Interrupt, os.Kill, syscall.SIGTERM)
139
+ signal.Notify(sigc, syscall.SIGTERM)
135
140
  go func() {
136
141
  <-sigc
137
142
  err := listener.Close()
data/lib/quartz/client.rb CHANGED
@@ -1,7 +1,7 @@
1
1
  class Quartz::Client
2
2
 
3
3
  def initialize(opts)
4
- @process = Quartz::GoProcess.new(file_path: opts[:file_path])
4
+ @process = Quartz::GoProcess.new(opts)
5
5
  @structs = {}
6
6
  @process.get_metadata.each do |struct_name, metadata|
7
7
  @structs[struct_name.to_sym] = Quartz::GoStruct.new(struct_name, metadata, @process)
@@ -1,18 +1,39 @@
1
1
  class Quartz::GoProcess
2
2
 
3
+ attr_reader :temp_file_path
4
+
5
+ def self.processes
6
+ @processes ||= []
7
+ end
8
+
3
9
  def initialize(opts)
4
- @socket_path = "/tmp/quartz#{rand(10000)}.sock"
10
+ @socket_path = "/tmp/quartz_#{rand(10000)}.sock"
5
11
  ENV['QUARTZ_SOCKET'] = @socket_path
6
12
 
7
13
  if opts[:file_path]
8
- @go_process = Thread.new { `go run #{opts[:file_path]} }` }
14
+ compile_and_run(opts[:file_path])
9
15
  elsif opts[:bin_path]
10
- @go_process = Thread.new { `#{opts[:bin_path]} }` }
16
+ @go_process = IO.popen(opts[:bin_path])
11
17
  else
12
18
  raise 'Missing go binary'
13
19
  end
14
20
 
15
21
  block_until_server_starts
22
+ self.class.processes << self
23
+ end
24
+
25
+ def compile_and_run(path)
26
+ @temp_file_path = "/tmp/quartz_runner_#{rand(10000)}"
27
+
28
+ unless system('go', 'build', '-o', @temp_file_path, path)
29
+ raise 'Go compilation failed'
30
+ end
31
+
32
+ @go_process = IO.popen(@temp_file_path)
33
+ end
34
+
35
+ def pid
36
+ @go_process.pid
16
37
  end
17
38
 
18
39
  def socket
@@ -40,7 +61,13 @@ class Quartz::GoProcess
40
61
  }
41
62
 
42
63
  socket.send(payload.to_json, 0)
43
- read
64
+ response = read
65
+
66
+ if response['error']
67
+ raise "Metadata error: #{read['error']}"
68
+ end
69
+
70
+ response['result']
44
71
  end
45
72
 
46
73
  def call(struct_name, method, args)
@@ -61,7 +88,20 @@ class Quartz::GoProcess
61
88
  MAX_MESSAGE_SIZE = 1_000_000_000 # Bytes
62
89
 
63
90
  def read
64
- JSON(socket.recv(MAX_MESSAGE_SIZE))['result']
91
+ JSON(socket.recv(MAX_MESSAGE_SIZE))
92
+ end
93
+
94
+ def cleanup
95
+ Process.kill('SIGTERM', pid)
96
+ Process.wait(pid)
97
+ File.delete(@temp_file_path) if @temp_file_path
98
+ self.class.processes.delete(self)
99
+ end
100
+
101
+ def self.cleanup
102
+ processes.each { |p| p.cleanup }
65
103
  end
66
104
 
67
105
  end
106
+
107
+ at_exit { Quartz::GoProcess.cleanup }
@@ -30,7 +30,13 @@ class Quartz::GoStruct
30
30
  # TODO: validate type
31
31
  end
32
32
 
33
- @process.call(@struct_name, method_name, args)
33
+ response = @process.call(@struct_name, method_name, args)
34
+
35
+ if response['error']
36
+ raise "Error calling #{method_name}: #{response['error']}"
37
+ end
38
+
39
+ response['result']
34
40
  end
35
41
 
36
42
  end
data/quartz.gemspec CHANGED
@@ -2,15 +2,15 @@
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.1.0 ruby lib
5
+ # stub: quartz 0.2.0 ruby lib
6
6
 
7
7
  Gem::Specification.new do |s|
8
8
  s.name = "quartz"
9
- s.version = "0.1.0"
9
+ s.version = "0.2.0"
10
10
 
11
11
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
12
12
  s.authors = ["David Huie"]
13
- s.date = "2014-06-16"
13
+ s.date = "2014-06-17"
14
14
  s.description = "A gem for calling #golang code from ruby"
15
15
  s.email = "dahuie@gmail.com"
16
16
  s.extra_rdoc_files = [
@@ -20,7 +20,40 @@ describe Quartz::GoProcess do
20
20
 
21
21
  it 'is able to call a method on a struct' do
22
22
  result = process.call('adder', 'Add', { 'A' => 5, 'B' => 6 })
23
- result.should eq({"X"=>11})
23
+ result.should eq({"id"=>1, "result"=>{"X"=>11}, "error"=>nil})
24
+ end
25
+
26
+ end
27
+
28
+ it 'works with an existing binary file' do
29
+ temp_file = "/tmp/quartz_test_#{rand(10000)}"
30
+ system('go', 'build', '-o', temp_file, 'spec/test.go')
31
+ process = Quartz::GoProcess.new(bin_path: temp_file)
32
+ result = process.call('adder', 'Add', { 'A' => 5, 'B' => 6 })
33
+ result.should eq({"id"=>1, "result"=>{"X"=>11}, "error"=>nil})
34
+ File.delete(temp_file)
35
+ end
36
+
37
+ describe '.cleanup' do
38
+
39
+ context 'files' do
40
+
41
+ it "it deletes temporary files" do
42
+ File.exists?(process.temp_file_path).should be_true
43
+ process.cleanup
44
+ File.exists?(process.temp_file_path).should be_false
45
+ end
46
+
47
+ end
48
+
49
+ context 'processes' do
50
+
51
+ it "it kills child processes" do
52
+ File.exists?(process.temp_file_path).should be_true
53
+ process.cleanup
54
+ File.exists?(process.temp_file_path).should be_false
55
+ end
56
+
24
57
  end
25
58
 
26
59
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: quartz
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - David Huie
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-06-16 00:00:00.000000000 Z
11
+ date: 2014-06-17 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rspec