quartz 0.2.2 → 0.2.3

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: a9b32688049786025781cf7243a2cab933d83d0d
4
- data.tar.gz: ca72a56ea8e7098daf9a05560353e0982c3c67b4
3
+ metadata.gz: 39afea8c7e6257e1015e85a28419bfe839879c2b
4
+ data.tar.gz: dd1345ed700b6e1b343d382436ed14f3032352ef
5
5
  SHA512:
6
- metadata.gz: 979ad4c2465c424464c0f40ac89f0671959ec27f6d91cbfe45099b409fa9d95ae45a325d5a3a230c69066d203a29f5d0281e85747f639539c1b74846dceec52d
7
- data.tar.gz: 86fad9d659b2912ba1bab12afe798f7eb44477062737a770e69db3865ad5351428da0bbf1c00edb2f09b71dac4d5bf772a45747991c607ca9a0cad05af2b2e28
6
+ metadata.gz: bad1814c347eb1e6727b208bb30b09b288af48f18a5a3e2014cd5e20d1e9108fda38e1c86388c2177913db07b0e14ca7b82d0d4b0d1657645cac2b1570cb29a8
7
+ data.tar.gz: c8913655aea693c38519c7fe4165d31f9f85708f73ac648d4b2fa3a2f26365f1b1c2e068c0ec3ec9e34bb01a72d37c594bea3e091fbec3c695b9038de7931e3d
data/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # quartz
2
2
 
3
- [![Build Status](https://travis-ci.org/DavidHuie/quartz.svg?branch=master)](https://travis-ci.org/DavidHuie/quartz)
3
+ [![Build Status](https://travis-ci.org/DavidHuie/quartz.svg?branch=master)](https://travis-ci.org/DavidHuie/quartz) [![Code Climate](https://codeclimate.com/github/DavidHuie/quartz.png)](https://codeclimate.com/github/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
@@ -18,9 +18,9 @@ the `examples/` directory.
18
18
  Quartz shares Go code by exporting methods on a struct to Ruby.
19
19
 
20
20
  Quartz requires that all arguments to exported struct methods be JSON-serializable
21
- structs. Additionally, the arguments to an exported method should be of the form
22
- `(A, *B)`, where `A` and `B` are struct types. The method should also return an error.
23
- Here's an example of an exportable struct and method:
21
+ types. Additionally, the arguments to an exported method should be of the form
22
+ `(A, *B)`, where `A` and `B` are JSON-serializable types. The method should also
23
+ return an error. Here's an example of an exportable struct and method:
24
24
 
25
25
  ```go
26
26
  type Adder struct{}
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.2.2
1
+ 0.2.3
@@ -1,7 +1,6 @@
1
1
  package quartz
2
2
 
3
3
  import (
4
- "encoding/json"
5
4
  "net"
6
5
  "net/rpc"
7
6
  "net/rpc/jsonrpc"
@@ -11,20 +10,26 @@ import (
11
10
  "syscall"
12
11
  )
13
12
 
14
- var (
15
- quartz *Quartz
16
- listener net.Listener
17
- )
18
-
13
+ // This holds information about exported structs.
19
14
  type Quartz struct {
20
15
  Registry map[string]*StructMetadata
21
16
  }
22
17
 
23
- type MethodMetadata struct {
24
- Method reflect.Method `json:"-"`
25
- ArgumentToType map[string]string
18
+ // Return's the struct registry. This method is exported via RPC
19
+ // so that the Ruby client can have knowledge about which structs and
20
+ // which methods are exported.
21
+ func (q *Quartz) GetMetadata(_ interface{}, value *map[string]*StructMetadata) error {
22
+ *value = q.Registry
23
+ return nil
26
24
  }
27
25
 
26
+ var (
27
+ quartz = &Quartz{
28
+ Registry: make(map[string]*StructMetadata),
29
+ }
30
+ socketPath = "/tmp/quartz.socket"
31
+ )
32
+
28
33
  type StructMetadata struct {
29
34
  NameToMethodMetadata map[string]*MethodMetadata
30
35
  TargetStruct interface{} `json:"-"`
@@ -37,106 +42,55 @@ func NewStructMetadata(targetStruct interface{}) *StructMetadata {
37
42
  }
38
43
  }
39
44
 
40
- func RegisterName(name string, s interface{}) error {
41
- // TODO: check that s is a pointer
45
+ type MethodMetadata struct {
46
+ Method reflect.Method `json:"-"`
47
+ ArgumentToType map[string]string
48
+ }
42
49
 
50
+ // Exports a struct via RPC and generates metadata for each of the struct's methods.
51
+ func RegisterName(name string, s interface{}) error {
43
52
  quartz.Registry[name] = NewStructMetadata(s)
44
-
45
53
  t := reflect.TypeOf(s)
46
54
  for i := 0; i < t.NumMethod(); i++ {
47
55
  method := t.Method(i)
48
-
49
56
  // TODO: only export methods with JSON serializable arguments
50
57
  // and responses.
51
-
52
58
  metadata := &MethodMetadata{
53
59
  method,
54
60
  StructFieldToType(method.Type.In(1)),
55
61
  }
56
-
57
62
  quartz.Registry[name].NameToMethodMetadata[method.Name] = metadata
58
63
  }
59
-
60
- return nil
64
+ return rpc.RegisterName(name, s)
61
65
  }
62
66
 
67
+ // Given a struct type, creates a mapping of field name
68
+ // to string representation of the field name's type.
63
69
  func StructFieldToType(t reflect.Type) map[string]string {
64
70
  fieldToType := make(map[string]string)
65
-
66
71
  for i := 0; i < t.NumField(); i++ {
67
72
  fieldToType[t.Field(i).Name] = t.Field(i).Type.String()
68
73
  }
69
-
70
74
  return fieldToType
71
75
  }
72
76
 
73
- type CallArgs struct {
74
- StructName string
75
- Method string
76
- MethodArgs string
77
- }
78
-
79
- func (q *Quartz) Call(args *CallArgs, response *interface{}) error {
80
-
81
- // TODO: validate args
82
-
83
- metadata := quartz.Registry[args.StructName]
84
- method := metadata.NameToMethodMetadata[args.Method].Method
85
-
86
- structValue := reflect.ValueOf(metadata.TargetStruct)
87
- methodArgsValue := reflect.ValueOf([]byte(args.MethodArgs))
88
- unmarshallerValue := reflect.ValueOf(json.Unmarshal)
89
- functionResponse := reflect.Indirect(reflect.ValueOf(response))
90
-
91
- // Determine what arguments the function requires
92
- argsType := method.Type.In(1)
93
- responseType := method.Type.In(2).Elem()
94
- responseValuePointer := reflect.New(responseType)
95
-
96
- // Create a value that's a direct reference to the arg argument
97
- argStructPointer := reflect.New(argsType)
98
- argStruct := reflect.Indirect(argStructPointer)
99
-
100
- // Unmarshall the argument json
101
- // TODO: check for unmarshalling errors
102
- unmarshallerValue.Call([]reflect.Value{methodArgsValue, argStructPointer})
103
-
104
- // Call the method
105
- err := method.Func.Call([]reflect.Value{structValue, argStruct, responseValuePointer})
106
- if !err[0].IsNil() {
107
- return err[0].Interface().(error)
108
- }
109
-
110
- // Set this method's response value
111
- rpcResponse := reflect.Indirect(responseValuePointer)
112
- functionResponse.Set(rpcResponse)
113
-
114
- return nil
115
- }
116
-
117
- func (q *Quartz) GetMetadata(_ interface{}, value *map[string]*StructMetadata) error {
118
- *value = q.Registry
119
- return nil
120
- }
121
-
122
- func init() {
123
- socket_path := os.Getenv("QUARTZ_SOCKET")
124
- if socket_path == "" {
125
- socket_path = "/tmp/quartz.socket"
126
- }
127
-
128
- var err error
129
- listener, err = net.Listen("unix", socket_path)
77
+ func Start() {
78
+ // Start the server and accept connections on a
79
+ // UNIX domain socket.
80
+ rpc.Register(quartz)
81
+ listener, err := net.Listen("unix", socketPath)
130
82
  if err != nil {
131
83
  panic(err)
132
84
  }
85
+ for {
86
+ conn, err := listener.Accept()
87
+ if err != nil {
88
+ panic(err)
89
+ }
90
+ go jsonrpc.ServeConn(conn)
91
+ }
133
92
 
134
- quartz = &Quartz{}
135
- quartz.Registry = make(map[string]*StructMetadata)
136
-
137
- rpc.Register(quartz)
138
-
139
- // Cleanup the socket file when the server is killed
93
+ // Destroy the socket file when the server is killed.
140
94
  sigc := make(chan os.Signal)
141
95
  signal.Notify(sigc, syscall.SIGTERM)
142
96
  go func() {
@@ -149,12 +103,9 @@ func init() {
149
103
  }()
150
104
  }
151
105
 
152
- func Start() {
153
- for {
154
- conn, err := listener.Accept()
155
- if err != nil {
156
- panic(err)
157
- }
158
- go jsonrpc.ServeConn(conn)
106
+ func init() {
107
+ // The Ruby gem sets this environment variable for us.
108
+ if os.Getenv("QUARTZ_SOCKET") != "" {
109
+ socketPath = os.Getenv("QUARTZ_SOCKET")
159
110
  }
160
111
  }
@@ -57,6 +57,8 @@ class Quartz::GoProcess
57
57
  payload = {
58
58
  'method' => 'Quartz.GetMetadata',
59
59
  'params' => [],
60
+ # This parameter isn't needed because we use a different
61
+ # connection for each thread.
60
62
  'id' => 1
61
63
  }
62
64
 
@@ -72,15 +74,10 @@ class Quartz::GoProcess
72
74
 
73
75
  def call(struct_name, method, args)
74
76
  payload = {
75
- 'method' => 'Quartz.Call',
76
- 'params' => [{
77
- 'StructName' => struct_name,
78
- 'Method' => method,
79
- 'MethodArgs' => args.to_json
80
- }],
77
+ 'method' => "#{struct_name}.#{method}",
78
+ 'params' => [args],
81
79
  'id' => 1
82
80
  }
83
-
84
81
  socket.send(payload.to_json, 0)
85
82
  read
86
83
  end
@@ -27,7 +27,7 @@ class Quartz::GoStruct
27
27
  raise "Invalid argument: #{k}"
28
28
  end
29
29
 
30
- # TODO: validate type
30
+ # TODO: validate types
31
31
  end
32
32
 
33
33
  response = @process.call(@struct_name, method_name, args)
@@ -2,11 +2,11 @@
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.2.2 ruby lib
5
+ # stub: quartz 0.2.3 ruby lib
6
6
 
7
7
  Gem::Specification.new do |s|
8
8
  s.name = "quartz"
9
- s.version = "0.2.2"
9
+ s.version = "0.2.3"
10
10
 
11
11
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
12
12
  s.require_paths = ["lib"]
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.2.2
4
+ version: 0.2.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - David Huie