pin.go 2.2 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455
  1. package source
  2. // PinnableMetricsQuerier is optionally implemented by a MetricsQuerier whose underlying data can change
  3. // between queries, for example one that serves from in-memory snapshots replaced on an interval.
  4. //
  5. // Computations that issue many queries for one window (allocation, assets, kube model) pin the querier
  6. // once and issue every query through the pinned view, so that all results come from one consistent
  7. // state of the data rather than a mix of states from before and after an update.
  8. type PinnableMetricsQuerier interface {
  9. MetricsQuerier
  10. // Pin returns a MetricsQuerier bound to the current state of the data, and a release function
  11. // which must be called once the pinned querier is no longer used. The pinned querier must remain
  12. // valid until released, even if the underlying data is updated in the meantime.
  13. Pin() (MetricsQuerier, func())
  14. }
  15. // PinMetrics pins the querier if it implements PinnableMetricsQuerier. Otherwise it returns the querier
  16. // unchanged and a no-op release function.
  17. func PinMetrics(q MetricsQuerier) (MetricsQuerier, func()) {
  18. if p, ok := q.(PinnableMetricsQuerier); ok {
  19. pinned, release := p.Pin()
  20. if release == nil {
  21. release = func() {}
  22. }
  23. return pinned, release
  24. }
  25. return q, func() {}
  26. }
  27. // PinDataSource returns a data source whose Metrics() always returns the same pinned querier, for use
  28. // by a computation that reads metrics through several helpers taking an OpenCostDataSource. If the data
  29. // source's querier does not implement PinnableMetricsQuerier, the data source is returned unchanged.
  30. //
  31. // The returned data source only forwards the OpenCostDataSource methods; optional interfaces
  32. // implemented by the original are not visible through it.
  33. func PinDataSource(ds OpenCostDataSource) (OpenCostDataSource, func()) {
  34. q := ds.Metrics()
  35. if _, ok := q.(PinnableMetricsQuerier); !ok {
  36. return ds, func() {}
  37. }
  38. pinned, release := PinMetrics(q)
  39. return &pinnedDataSource{OpenCostDataSource: ds, metrics: pinned}, release
  40. }
  41. // pinnedDataSource is an OpenCostDataSource whose Metrics() returns a pinned querier.
  42. type pinnedDataSource struct {
  43. OpenCostDataSource
  44. metrics MetricsQuerier
  45. }
  46. func (p *pinnedDataSource) Metrics() MetricsQuerier {
  47. return p.metrics
  48. }