resourcemanager.go 1.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778
  1. package syncx
  2. import (
  3. "io"
  4. "sync"
  5. "github.com/zeromicro/go-zero/core/errorx"
  6. )
  7. // A ResourceManager is a manager that used to manage resources.
  8. type ResourceManager struct {
  9. resources map[string]io.Closer
  10. singleFlight SingleFlight
  11. lock sync.RWMutex
  12. }
  13. // NewResourceManager returns a ResourceManager.
  14. func NewResourceManager() *ResourceManager {
  15. return &ResourceManager{
  16. resources: make(map[string]io.Closer),
  17. singleFlight: NewSingleFlight(),
  18. }
  19. }
  20. // Close closes the manager.
  21. // Don't use the ResourceManager after Close() called.
  22. func (manager *ResourceManager) Close() error {
  23. manager.lock.Lock()
  24. defer manager.lock.Unlock()
  25. var be errorx.BatchError
  26. for _, resource := range manager.resources {
  27. if err := resource.Close(); err != nil {
  28. be.Add(err)
  29. }
  30. }
  31. // release resources to avoid using it later
  32. manager.resources = nil
  33. return be.Err()
  34. }
  35. // GetResource returns the resource associated with given key.
  36. func (manager *ResourceManager) GetResource(key string, create func() (io.Closer, error)) (
  37. io.Closer, error) {
  38. val, err := manager.singleFlight.Do(key, func() (any, error) {
  39. manager.lock.RLock()
  40. resource, ok := manager.resources[key]
  41. manager.lock.RUnlock()
  42. if ok {
  43. return resource, nil
  44. }
  45. resource, err := create()
  46. if err != nil {
  47. return nil, err
  48. }
  49. manager.lock.Lock()
  50. defer manager.lock.Unlock()
  51. manager.resources[key] = resource
  52. return resource, nil
  53. })
  54. if err != nil {
  55. return nil, err
  56. }
  57. return val.(io.Closer), nil
  58. }
  59. // Inject injects the resource associated with given key.
  60. func (manager *ResourceManager) Inject(key string, resource io.Closer) {
  61. manager.lock.Lock()
  62. manager.resources[key] = resource
  63. manager.lock.Unlock()
  64. }