di.go 2.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596
  1. package main
  2. import (
  3. "context"
  4. "flag"
  5. "fmt"
  6. "io"
  7. "log"
  8. "time"
  9. "code.osinet.fr/fgm/izidic"
  10. "github.com/dcowgill/envflag"
  11. "code.osinet.fr/fgm/lbc/internal"
  12. "code.osinet.fr/fgm/lbc/web"
  13. )
  14. // 12-factor/XI: log to stdout.
  15. func loggerService(dic *izidic.Container) (any, error) {
  16. sw, err := dic.Param("writer")
  17. if err != nil {
  18. return nil, err
  19. }
  20. w, ok := sw.(io.Writer)
  21. if !ok {
  22. return nil, fmt.Errorf("incorrect type for service writer: %T", sw)
  23. }
  24. logger := log.New(w, "", log.LstdFlags)
  25. // Support code not able to use an injected logger
  26. log.SetOutput(w)
  27. return logger, nil
  28. }
  29. func configService(dic *izidic.Container) (any, error) {
  30. name := dic.MustParam("name").(string)
  31. // Provide fallback configuration.
  32. c := &web.Config{
  33. Config: internal.Config{
  34. Verbose: false,
  35. },
  36. Addr: ":8080",
  37. Base: "/",
  38. WriteTimeout: 100 * time.Millisecond,
  39. }
  40. // Build runtime configuration.
  41. fs := flag.NewFlagSet(name, flag.ContinueOnError)
  42. fs.StringVar(&c.Addr, "addr", c.Addr, "the address on which to listen")
  43. fs.StringVar(&c.Base, "base", c.Base, "the base path for the server")
  44. fs.BoolVar(&c.Verbose, "v", c.Verbose, "be verbose")
  45. fs.DurationVar(&c.WriteTimeout, "wt", c.WriteTimeout, "the write timeout")
  46. err := fs.Parse(dic.MustParam("args").([]string))
  47. if err != nil {
  48. return nil, err
  49. }
  50. vs := envflag.NewVarSet(fs)
  51. vs.SetPrefix(name)
  52. vs.Parse()
  53. return c, nil
  54. }
  55. func statsService(dic *izidic.Container) (any, error) {
  56. return web.NewStats(), nil
  57. }
  58. func webService(dic *izidic.Container) (any, error) {
  59. logger := dic.MustService("logger").(*log.Logger)
  60. config := dic.MustService("config").(*web.Config)
  61. stats := dic.MustService("stats").(*web.Stats)
  62. ctx := context.Background()
  63. return &web.Server{
  64. BaseContext: ctx,
  65. Config: config,
  66. Logger: logger,
  67. Stats: stats,
  68. }, nil
  69. }
  70. // resolve configures dependency injection.
  71. func resolve(w io.Writer, args []string) *izidic.Container {
  72. dic := izidic.New()
  73. dic.Register("config", configService)
  74. dic.Register("logger", loggerService)
  75. dic.Register("stats", statsService)
  76. dic.Register("web", webService)
  77. dic.Store("name", "fizzbuzz")
  78. dic.Store("args", args[1:])
  79. dic.Store("writer", w)
  80. dic.Freeze()
  81. return dic
  82. }