resourcemanager.go 1.5 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970
  1. package syncx
  2. import (
  3. "io"
  4. "sync"
  5. "github.com/tal-tech/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)) (io.Closer, error) {
  37. val, err := manager.singleFlight.Do(key, func() (interface{}, error) {
  38. manager.lock.RLock()
  39. resource, ok := manager.resources[key]
  40. manager.lock.RUnlock()
  41. if ok {
  42. return resource, nil
  43. }
  44. resource, err := create()
  45. if err != nil {
  46. return nil, err
  47. }
  48. manager.lock.Lock()
  49. manager.resources[key] = resource
  50. manager.lock.Unlock()
  51. return resource, nil
  52. })
  53. if err != nil {
  54. return nil, err
  55. }
  56. return val.(io.Closer), nil
  57. }