123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114 |
- package main
- import (
- "context"
- "flag"
- "fmt"
- "io"
- "log"
- "time"
- "code.osinet.fr/fgm/izidic"
- "github.com/dcowgill/envflag"
- "code.osinet.fr/fgm/lbc/internal"
- "code.osinet.fr/fgm/lbc/web"
- )
- // containers wraps an [izidic.Container] to provide typed services accessors,
- // obviating the need to type-assert calls to Service.
- type container struct {
- *izidic.Container
- }
- func (c *container) Config() *web.Config {
- return c.MustService("config").(*web.Config)
- }
- func (c *container) Logger() *log.Logger {
- return c.MustService("logger").(*log.Logger)
- }
- func (c *container) Stats() *web.Stats {
- return c.MustService("stats").(*web.Stats)
- }
- func (c *container) Web() *web.Server {
- return c.MustService("web").(*web.Server)
- }
- // 12-factor/XI: log to stdout.
- func loggerService(dic *izidic.Container) (any, error) {
- sw, err := dic.Param("writer")
- if err != nil {
- return nil, err
- }
- w, ok := sw.(io.Writer)
- if !ok {
- return nil, fmt.Errorf("incorrect type for service writer: %T", sw)
- }
- logger := log.New(w, "", log.LstdFlags)
- // Support code not able to use an injected logger
- log.SetOutput(w)
- return logger, nil
- }
- func configService(dic *izidic.Container) (any, error) {
- name := dic.MustParam("name").(string)
- // Provide fallback configuration.
- c := &web.Config{
- Config: internal.Config{
- Verbose: false,
- },
- Addr: ":8080",
- Base: "/",
- WriteTimeout: 100 * time.Millisecond,
- }
- // Build runtime configuration.
- fs := flag.NewFlagSet(name, flag.ContinueOnError)
- fs.StringVar(&c.Addr, "addr", c.Addr, "the address on which to listen")
- fs.StringVar(&c.Base, "base", c.Base, "the base path for the server")
- fs.BoolVar(&c.Verbose, "v", c.Verbose, "be verbose")
- fs.DurationVar(&c.WriteTimeout, "wt", c.WriteTimeout, "the write timeout")
- err := fs.Parse(dic.MustParam("args").([]string))
- if err != nil {
- return nil, err
- }
- vs := envflag.NewVarSet(fs)
- vs.SetPrefix(name)
- vs.Parse()
- return c, nil
- }
- func statsService(dic *izidic.Container) (any, error) {
- return web.NewStats(), nil
- }
- func webService(dic *izidic.Container) (any, error) {
- wd := container{dic}
- return &web.Server{
- BaseContext: context.Background(),
- Config: wd.Config(),
- Logger: wd.Logger(),
- Stats: wd.Stats(),
- }, nil
- }
- // resolve configures dependency injection.
- func resolve(w io.Writer, args []string) *izidic.Container {
- dic := izidic.New()
- dic.Register("config", configService)
- dic.Register("logger", loggerService)
- dic.Register("stats", statsService)
- dic.Register("web", webService)
- dic.Store("name", "fizzbuzz")
- dic.Store("args", args[1:])
- dic.Store("writer", w)
- dic.Freeze()
- return dic
- }
|