quartz 0.2.2 → 0.2.3

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: 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