You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Suppose you have a handlers.go file that looks something like this:
package handlers
import (
"context""database/sql"
pb "github.com/eriktate/thing"
)
// NewService returns a naïve, stateless implementation of Service.funcNewService() pb.ContextServer {
db, err:=connectToProdDB()
iferr!=nil {
panic("Failed to connect to database")
}
returnBuildService(db)
}
// BuildService returns a dependency injected thingService. Useful for unit testing.funcBuildService(db*sql.DB) thingService {
returnthingService{db: db}
}
typethingServicestruct {
db*sql.DB
}
// DoThing does a thing with the sql.DB pointer housed in thingService.func (sthingService) DoThing(ctx context.Context, in*pb.ThingPayload) (*pb.ThingResponse, error) {
returndoSomethingWithDatbase(s.db)
}
This type of pattern doesn't seem to be possible with truss at the moment, as the BuildService function will be stripped on the next truss run. A workaround might be to add a file in the same package and define the BuildService function there, but it feels like it should be included with the service definition.
A solution I've found is a slight change to the pruneDecls function in gengokit/handlers/handlers.go:
func (mmethodMap) pruneDecls(decls []ast.Decl, svcNamestring, allowExportsbool) []ast.Decl {
varnewDecls []ast.Declfor_, d:=rangedecls {
switchx:=d.(type) {
case*ast.FuncDecl:
name:=x.Name.Name// Special case NewService and ignore unexportedifname==ignoredFunc||!ast.IsExported(name) {
log.WithField("Func", name).
Debug("Ignoring")
newDecls=append(newDecls, x)
continue
}
ifok:=isValidFunc(x, m, svcName); ok==true {
updateParams(x, m[name])
updateResults(x, m[name])
newDecls=append(newDecls, x)
delete(m, name)
} elseifallowExports {
ifok:=isIgnored(x, m, svcName); ok==true {
newDecls=append(newDecls, x)
}
}
default:
newDecls=append(newDecls, d)
}
}
returnnewDecls
}
// potential new functionfuncisIgnored(f*ast.FuncDecl, mmethodMap, svcNamestring) bool {
name:=f.Name.String()
rName:=recvTypeToString(f.Recv)
ifrName!=svcName+"Service" {
log.WithField("Func", name).WithField("Receiver", rName).
Info("Exported func is not on service receiver; ignoring")
returntrue
}
returnfalse
}
The allowExports bool in the function signature would allow for this functionality to be placed behind a flag. This change just checks if the exported function declaration has the service struct as a receiver. If it DOES have the service struct as a receiver than it will be handled normally. If it DOESN'T have the service struct as a receiver, than it will ignore that function when pruning.
Thoughts about adding this sort of functionality? Or the proposed solution? If the desired workflow for something like this is to use a different file than handlers.go that's fine too, just wondering if anyone else would benefit from something like this.
The text was updated successfully, but these errors were encountered:
eriktate
changed the title
Proposal: Allow exported functions with receivers other than *Server
Proposal: Allow exported functions with receivers other than *Service
Dec 15, 2017
Suppose you have a
handlers.go
file that looks something like this:This type of pattern doesn't seem to be possible with truss at the moment, as the
BuildService
function will be stripped on the next truss run. A workaround might be to add a file in the same package and define theBuildService
function there, but it feels like it should be included with the service definition.A solution I've found is a slight change to the
pruneDecls
function ingengokit/handlers/handlers.go
:The
allowExports
bool in the function signature would allow for this functionality to be placed behind a flag. This change just checks if the exported function declaration has the service struct as a receiver. If it DOES have the service struct as a receiver than it will be handled normally. If it DOESN'T have the service struct as a receiver, than it will ignore that function when pruning.Thoughts about adding this sort of functionality? Or the proposed solution? If the desired workflow for something like this is to use a different file than
handlers.go
that's fine too, just wondering if anyone else would benefit from something like this.The text was updated successfully, but these errors were encountered: