77 "strings"
88)
99
10- // Dispatch is system for handling calls to lib. Currently only implemented for FSI methods.
10+ // Dispatch is a system for handling calls to lib. Should only be called by top-level lib methods.
1111//
1212// When programs are using qri as a library (such as the `cmd` package), calls to `lib` will
1313// arrive at dispatch, before being routed to the actual implementation routine. This solves
@@ -22,13 +22,6 @@ import (
2222// as the input and output parameters for those methods, and associates a string name for each
2323// method. Dispatch works by looking up that method name, constructing the necessary input,
2424// then invoking the actual implementation.
25-
26- // RegMethodSet represents a set of registered methods
27- type RegMethodSet struct {
28- reg map [string ]callable
29- }
30-
31- // Dispatch looks up the method, and invokes it with the given input
3225func (inst * Instance ) Dispatch (ctx context.Context , method string , param interface {}) (res interface {}, err error ) {
3326 if inst == nil {
3427 return nil , fmt .Errorf ("instance is nil, cannot dispatch" )
@@ -60,12 +53,12 @@ func (inst *Instance) Dispatch(ctx context.Context, method string, param interfa
6053 // TODO(dustmop): Add user authentication, profile, identity, etc
6154 // TODO(dustmop): Also determine if the method is read-only vs read-write,
6255 // and only execute a single read-write method at a time
63- // Eventually, the data that lives in Scope should be immutable for its lifetime,
56+ // Eventually, the data that lives in scope should be immutable for its lifetime,
6457 // or use copy-on-write semantics, so that one method running at the same time as
6558 // another cannot modify the out-of-scope data of the other. This will mostly
6659 // involve making copies of the right things
67- scope := Scope {
68- ctx : ctx ,
60+ scope := scope {
61+ ctx : ctx ,
6962 inst : inst ,
7063 }
7164
@@ -110,8 +103,13 @@ func (inst *Instance) NewInputParam(method string) interface{} {
110103 return nil
111104}
112105
106+ // regMethodSet represents a set of registered methods
107+ type regMethodSet struct {
108+ reg map [string ]callable
109+ }
110+
113111// lookup finds the callable structure with the given method name
114- func (r * RegMethodSet ) lookup (method string ) (* callable , bool ) {
112+ func (r * regMethodSet ) lookup (method string ) (* callable , bool ) {
115113 if c , ok := r .reg [method ]; ok {
116114 return & c , true
117115 }
@@ -129,7 +127,7 @@ type callable struct {
129127func (inst * Instance ) RegisterMethods () {
130128 reg := make (map [string ]callable )
131129 inst .registerOne ("fsi" , & FSIImpl {}, reg )
132- inst .regMethods = & RegMethodSet {reg : reg }
130+ inst .regMethods = & regMethodSet {reg : reg }
133131}
134132
135133func (inst * Instance ) registerOne (ourName string , impl interface {}, reg map [string ]callable ) {
@@ -139,51 +137,44 @@ func (inst *Instance) registerOne(ourName string, impl interface{}, reg map[stri
139137 for k := 0 ; k < num ; k ++ {
140138 m := implType .Method (k )
141139 lowerName := strings .ToLower (m .Name )
142- funcName := ourName + "." + lowerName
140+ funcName := fmt . Sprintf ( "%s.%s" , ourName , lowerName )
143141
144142 // Validate the parameters to the method
145143 // should have 3 input parameters: (receiver, scope, input struct)
146144 // should have 2 output parametres: (output value, error)
147145 // TODO(dustmop): allow variadic returns: error only, cursor for pagination
148146 f := m .Type
149147 if f .NumIn () != 3 {
150- log .Errorf ("%s: bad number of inputs: %d" , funcName , f .NumIn ())
151- continue
148+ log .Fatalf ("%s: bad number of inputs: %d" , funcName , f .NumIn ())
152149 }
153150 if f .NumOut () != 2 {
154- log .Errorf ("%s: bad number of outputs: %d" , funcName , f .NumOut ())
155- continue
151+ log .Fatalf ("%s: bad number of outputs: %d" , funcName , f .NumOut ())
156152 }
157153 // First input must be the receiver
158154 inType := f .In (0 )
159155 if inType != implType {
160- log .Errorf ("%s: first input param should be impl, got %v" , funcName , inType )
161- continue
156+ log .Fatalf ("%s: first input param should be impl, got %v" , funcName , inType )
162157 }
163158 // Second input must be a scope
164159 inType = f .In (1 )
165- if inType .Name () != "Scope" {
166- log .Errorf ("%s: second input param should be scope, got %v" , funcName , inType )
167- continue
160+ if inType .Name () != "scope" {
161+ log .Fatalf ("%s: second input param should be scope, got %v" , funcName , inType )
168162 }
169163 // Third input is a pointer to the input struct
170164 inType = f .In (2 )
171165 if inType .Kind () != reflect .Ptr {
172- log .Errorf ("%s: third input param must be a struct pointer, got %v" , funcName , inType )
173- continue
166+ log .Fatalf ("%s: third input param must be a struct pointer, got %v" , funcName , inType )
174167 }
175168 inType = inType .Elem ()
176169 if inType .Kind () != reflect .Struct {
177- log .Errorf ("%s: third input param must be a struct pointer, got %v" , funcName , inType )
178- continue
170+ log .Fatalf ("%s: third input param must be a struct pointer, got %v" , funcName , inType )
179171 }
180172 // First output is anything
181173 outType := f .Out (0 )
182174 // Second output must be an error
183175 outErrType := f .Out (1 )
184176 if outErrType .Name () != "error" {
185- log .Errorf ("%s: second output param should be error, got %v" , funcName , inType )
186- continue
177+ log .Fatalf ("%s: second output param should be error, got %v" , funcName , outErrType )
187178 }
188179
189180 // Save the method to the registration table
@@ -193,12 +184,16 @@ func (inst *Instance) registerOne(ourName string, impl interface{}, reg map[stri
193184 InType : inType ,
194185 OutType : outType ,
195186 }
196- log .Infof ("%d: registered %s(*%s) %v" , k , funcName , inType , outType )
187+ log .Debugf ("%d: registered %s(*%s) %v" , k , funcName , inType , outType )
197188 }
198189}
199190
200191// methodEndpoint returns a method name and returns the API endpoint for it
201192func methodEndpoint (method string ) APIEndpoint {
193+ // TODO(dustmop): This is here temporarily. /fsi/write/ works differently than
194+ // other methods; their http API endpoints are only their method name, for
195+ // exmaple /status/. This should be replaced with an explicit mapping from
196+ // method names to endpoints.
202197 if method == "fsi.write" {
203198 return "/fsi/write/"
204199 }
0 commit comments