handler_cache.go 1.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657
  1. /*
  2. Copyright 2021 The Kubernetes Authors.
  3. Licensed under the Apache License, Version 2.0 (the "License");
  4. you may not use this file except in compliance with the License.
  5. You may obtain a copy of the License at
  6. http://www.apache.org/licenses/LICENSE-2.0
  7. Unless required by applicable law or agreed to in writing, software
  8. distributed under the License is distributed on an "AS IS" BASIS,
  9. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  10. See the License for the specific language governing permissions and
  11. limitations under the License.
  12. */
  13. package handler
  14. import (
  15. "sync"
  16. )
  17. // HandlerCache represents a lazy cache for generating a byte array
  18. // It is used to lazily marshal OpenAPI v2/v3 and lazily generate the ETag
  19. type HandlerCache struct {
  20. BuildCache func() ([]byte, error)
  21. once sync.Once
  22. bytes []byte
  23. err error
  24. }
  25. // Get either returns the cached value or calls BuildCache() once before caching and returning
  26. // its results. If BuildCache returns an error, the last valid value for the cache (from prior
  27. // calls to New()) is used instead if possible.
  28. func (c *HandlerCache) Get() ([]byte, error) {
  29. c.once.Do(func() {
  30. bytes, err := c.BuildCache()
  31. // if there is an error updating the cache, there can be situations where
  32. // c.bytes contains a valid value (carried over from the previous update)
  33. // but c.err is also not nil; the cache user is expected to check for this
  34. c.err = err
  35. if c.err == nil {
  36. // don't override previous spec if we had an error
  37. c.bytes = bytes
  38. }
  39. })
  40. return c.bytes, c.err
  41. }
  42. // New creates a new HandlerCache for situations where a cache refresh is needed.
  43. // This function is not thread-safe and should not be called at the same time as Get().
  44. func (c *HandlerCache) New(cacheBuilder func() ([]byte, error)) HandlerCache {
  45. return HandlerCache{
  46. bytes: c.bytes,
  47. BuildCache: cacheBuilder,
  48. }
  49. }