hub.go 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152
  1. package di
  2. import (
  3. "reflect"
  4. "go.uber.org/dig"
  5. "kpt-event/util/cleanup"
  6. "kpt-event/util/di/xreflect"
  7. "kpt-event/util/xerr"
  8. )
  9. func New(opts ...HubOption) (*Hub, error) {
  10. hub := &Hub{
  11. cleanup: cleanup.Entry{},
  12. provides: make([]Provided, 0),
  13. }
  14. for _, opt := range opts {
  15. opt.Apply(hub)
  16. }
  17. hub.container = dig.New(
  18. dig.DryRun(hub.validate),
  19. )
  20. for i, p := range hub.provides {
  21. if err := hub.usingProvide(p); err != nil {
  22. return nil, xerr.Errorf("error after options[%d] were applied: %v", i, err)
  23. }
  24. }
  25. return hub, nil
  26. }
  27. // Hub is a directed acyclic graph of types and their dependencies.
  28. // extend dig.Container
  29. type Hub struct {
  30. container *dig.Container
  31. cleanup cleanup.Entry
  32. provides []Provided
  33. validate bool
  34. }
  35. // Cleanup runs all the cleanup functions registered in the hub.
  36. func (hub *Hub) Cleanup() {
  37. hub.cleanup.Run()
  38. }
  39. // Provided is a single constructor provided to di.
  40. type Provided struct {
  41. // Constructor provided to di. This may be an di.Annotated.
  42. Target interface{}
  43. // Stack trace of where this Provided was made.
  44. Stack xreflect.Stack
  45. // IsSupply is true when the Target constructor was emitted by di.Supply.
  46. IsSupply bool
  47. }
  48. func (hub *Hub) usingProvide(p Provided) error {
  49. constructor := p.Target
  50. if _, ok := constructor.(HubOption); ok {
  51. return xerr.Errorf("di.Option should be passed to di.New directly, "+
  52. "not to di.Provide: di.Provide received %v from:\n%+v",
  53. constructor, p.Stack)
  54. }
  55. if ann, ok := constructor.(Annotated); ok {
  56. var opts []dig.ProvideOption
  57. switch {
  58. case len(ann.Group) > 0 && len(ann.Name) > 0:
  59. return xerr.Errorf(
  60. "di.Annotated may specify only one of Name or Group: received %v from:\n%+v",
  61. ann, p.Stack)
  62. case len(ann.Name) > 0:
  63. opts = append(opts, dig.Name(ann.Name))
  64. case len(ann.Group) > 0:
  65. opts = append(opts, dig.Group(ann.Group))
  66. }
  67. // 注册初始化函数
  68. if err := hub.Provide(ann.Target, opts...); err != nil {
  69. return xerr.Errorf("di.Provide(%v) from:\n%+vFailed: %v", ann, p.Stack, err)
  70. }
  71. // 注册清理函数
  72. if ann.Close != nil {
  73. hub.cleanup.Register(ann.Close)
  74. }
  75. return nil
  76. }
  77. if reflect.TypeOf(constructor).Kind() == reflect.Func {
  78. ft := reflect.ValueOf(constructor).Type()
  79. for i := 0; i < ft.NumOut(); i++ {
  80. t := ft.Out(i)
  81. if t == reflect.TypeOf(Annotated{}) {
  82. return xerr.Errorf(
  83. "di.Annotated should be passed to di.Provide directly, "+
  84. "it should not be returned by the constructor: "+
  85. "di.Provide received %v from:\n%+v",
  86. xreflect.FuncName(constructor), p.Stack)
  87. }
  88. }
  89. }
  90. if err := hub.Provide(constructor); err != nil {
  91. return xerr.Errorf("di.Provide(%v) from:\n%+vFailed: %v", xreflect.FuncName(constructor), p.Stack, err)
  92. }
  93. return nil
  94. }
  95. // Invoke runs the given function after instantiating its dependencies.
  96. //
  97. // Any arguments that the function has are treated as its dependencies. The
  98. // dependencies are instantiated in an unspecified order along with any
  99. // dependencies that they might have.
  100. //
  101. // The function may return an error to indicate failure. The error will be
  102. // returned to the caller as-is.
  103. func (hub *Hub) Invoke(function interface{}, opts ...InvokeOption) error {
  104. return hub.container.Invoke(function, opts...)
  105. }
  106. // Provide teaches the container how to build values of one or more types and
  107. // expresses their dependencies.
  108. //
  109. // The first argument of Provide is a function that accepts zero or more
  110. // parameters and returns one or more results. The function may optionally
  111. // return an error to indicate that it failed to build the value. This
  112. // function will be treated as the constructor for all the types it returns.
  113. // This function will be called AT MOST ONCE when a type produced by it, or a
  114. // type that consumes this function's output, is requested via Invoke. If the
  115. // same types are requested multiple times, the previously produced value will
  116. // be reused.
  117. //
  118. // In addition to accepting constructors that accept dependencies as separate
  119. // arguments and produce results as separate return values, Provide also
  120. // accepts constructors that specify dependencies as dig.In structs and/or
  121. // specify results as dig.Out structs.
  122. func (hub *Hub) Provide(constructor interface{}, opts ...ProvideOption) error {
  123. return hub.container.Provide(constructor, opts...)
  124. }
  125. func (hub *Hub) GetProvidedSlice() []Provided {
  126. return hub.provides
  127. }