(ctx context.Context, aAPI proto.DRPCAgentClient28)
| 605 | } |
| 606 | |
| 607 | func (a *agent) reportMetadata(ctx context.Context, aAPI proto.DRPCAgentClient28) error { |
| 608 | tickerDone := make(chan struct{}) |
| 609 | collectDone := make(chan struct{}) |
| 610 | ctx, cancel := context.WithCancel(ctx) |
| 611 | defer func() { |
| 612 | cancel() |
| 613 | <-collectDone |
| 614 | <-tickerDone |
| 615 | }() |
| 616 | |
| 617 | var ( |
| 618 | logger = a.logger.Named("metadata") |
| 619 | report = make(chan struct{}, 1) |
| 620 | collect = make(chan struct{}, 1) |
| 621 | metadataResults = make(chan metadataResultAndKey, 1) |
| 622 | ) |
| 623 | |
| 624 | // Set up collect and report as a single ticker with two channels, |
| 625 | // this is to allow collection and reporting to be triggered |
| 626 | // independently of each other. |
| 627 | go func() { |
| 628 | t := time.NewTicker(a.reportMetadataInterval) |
| 629 | defer func() { |
| 630 | t.Stop() |
| 631 | close(report) |
| 632 | close(collect) |
| 633 | close(tickerDone) |
| 634 | }() |
| 635 | wake := func(c chan<- struct{}) { |
| 636 | select { |
| 637 | case c <- struct{}{}: |
| 638 | default: |
| 639 | } |
| 640 | } |
| 641 | wake(collect) // Start immediately. |
| 642 | |
| 643 | for { |
| 644 | select { |
| 645 | case <-ctx.Done(): |
| 646 | return |
| 647 | case <-t.C: |
| 648 | wake(report) |
| 649 | wake(collect) |
| 650 | } |
| 651 | } |
| 652 | }() |
| 653 | |
| 654 | go func() { |
| 655 | defer close(collectDone) |
| 656 | |
| 657 | var ( |
| 658 | // We use a custom singleflight that immediately returns if there is already |
| 659 | // a goroutine running for a given key. This is to prevent a build-up of |
| 660 | // goroutines waiting on Do when the script takes many multiples of |
| 661 | // baseInterval to run. |
| 662 | flight = trySingleflight{m: map[string]struct{}{}} |
| 663 | lastCollectedAtMu sync.RWMutex |
| 664 | lastCollectedAts = make(map[string]time.Time) |
nothing calls this directly
no test coverage detected