func()

in internal/graph/graph_scanner.go [149:217]


func (a AprlScanner) Scan(ctx context.Context, cred azcore.TokenCredential) (map[string]map[string]models.AprlRecommendation, []models.AprlResult) {
	recommendations := map[string]map[string]models.AprlRecommendation{}
	results := []models.AprlResult{}
	rules := []models.AprlRecommendation{}
	graph := NewGraphQuery(cred)

	// get APRL recommendations
	aprl := a.GetAprlRecommendations()

	for _, s := range a.serviceScanners {
		for _, t := range s.ResourceTypes() {
			models.LogResourceTypeScan(t)
			gr := a.getGraphRules(t, aprl)
			for _, r := range gr {
				rules = append(rules, r)
			}

			for i, r := range gr {
				if recommendations[strings.ToLower(t)] == nil {
					recommendations[strings.ToLower(t)] = map[string]models.AprlRecommendation{}
				}
				recommendations[strings.ToLower(t)][i] = r
			}
		}
	}

	batches := int(math.Ceil(float64(len(rules)) / 12))

	jobs := make(chan []models.AprlRecommendation, batches)
	ch := make(chan []models.AprlResult, batches)
	var wg sync.WaitGroup

	// Start workers
	numWorkers := 12 // Define the number of workers in the pool
	for w := 0; w < numWorkers; w++ {
		go a.worker(ctx, graph, a.subscriptions, jobs, ch, &wg)
	}
	wg.Add(batches)

	batchSize := 12
	for i := 0; i < len(rules); i += batchSize {
		j := i + batchSize
		if j > len(rules) {
			j = len(rules)
		}

		jobs <- rules[i:j]

		// Staggering queries to avoid throttling. Max 15 queries each 5 seconds.
		// https://learn.microsoft.com/en-us/azure/governance/resource-graph/concepts/guidance-for-throttled-requests#staggering-queries
		time.Sleep(5 * time.Second)
	}

	// Wait for all workers to finish
	close(jobs)
	wg.Wait()

	for i := 0; i < batches; i++ {
		res := <-ch
		for _, r := range res {
			if a.filters.Azqr.IsServiceExcluded(r.ResourceID) {
				continue
			}
			results = append(results, r)
		}
	}

	return recommendations, results
}