Hi Wire authors/contributors @zombiezen! How about implement smth like this. Do you have smth like this in roadmap/plans?
package main
import (
"fmt"
"net/http"
)
import "github.com/google/wire"
type WebControllerInterface interface {
Get(w http.ResponseWriter, r *http.Request)
}
func NewDB() *DB
func NewHTTPClient() *HTTPClient
func NewServer(a WebControllerInterface, db *DB) *SomePopularWebserver {
a = &SomePopularWebserver{}
a.Middleware(func(f func(w http.ResponseWriter, r *http.Request)) {
// db create transaction
f(w, r.WithContext(context.WithValue(r.Context(), "tx", tx)))
// will be clear when to stop with
// db transaction.Commit/Rollback
})
a.GET("/", a.Get)
a.POST("/", a.Post) // other methods
a.PUT("/", a.Put) // other methods
return
}
// web controller which methods work inside transaction scope
func NewWebController(ModelRepositoryInterface, *Logger, *HTTPClient) *Controller
// repo with request scope transaction
func NewModelRepository(*Transaction) *ModelRepository
// request scope transaction
func NewTransaction(*http.Request) (*Transaction)
// get some headers and create logger probably some parent logger injection will take place as well
func NewLogger(*http.Request) (*Logger)
func InitializeServer() Server {
var scoped = wire.Scoped(NewTransaction, NewLogger, NewModelRepository)
wire.Build(
NewDB,
NewServer,
NewHTTPClient,
wire.Prototype(NewWebController,
wire.As(WebControllerInterface), scoped,
// wire.Prototype(NewWebController2,
// wire.As(WebControllerInterface2), scoped),
),
)
return Server{}
}
// which results after wire CLI into NewServer injected with custom WebControllerInterface implementation constructed with singleton scoped dependencies
// where each method is factory to produce NewWebController and execute matching method
// like:
// constructed by wire
type DecoratedWebController struct {
client *HTTPClient
}
func (d *DecoratedWebController) Get(w http.ResponseWriter, r *http.Request) {
l := NewLogger(r) // in case of NewLogger() (*logger, error) just panic on error?
t := NewTransaction(r)
mr := NewModelRepository(t)
c := NewWebController(mr, l, d.client)
c.Get(w, r)
// later execute cleanup functions like in wire
}
// highly likely inject only instances which not provided by Prototype scope constructors results or wrapped by them like dig.Decorate
func NewDecoratedWebController(c *HTTPClient) *DecoratedWebController {
return &DecoratedWebController{c}
}
// and finally smth like this after wire CLI:
func InitializeServer() Server {
db := NewDB()
c := NewHTTPClient()
dc := NewDecoratedWebController(c)
return NewServer(dc, db)
}
In fact I though about building some kind of wire preprocessor to construct such NewDecoratedWebController and later regenerate code once more with wire.
Is it make sense or do you think such a thing will be hard to customize accross frameworks which have some kind of request/response functionality/hard to check errors on cleanup/ etc ?
Hi Wire authors/contributors @zombiezen! How about implement smth like this. Do you have smth like this in roadmap/plans?
In fact I though about building some kind of wire preprocessor to construct such NewDecoratedWebController and later regenerate code once more with wire. Is it make sense or do you think such a thing will be hard to customize accross frameworks which have some kind of request/response functionality/hard to check errors on cleanup/ etc ?