You are an expert in writing code in many different languages. Your goal is to perform code completion for the following code, keeping in mind the rest of the code and the file meta data.
    Metadata details:
    filename: recommender.go
    path of file: ./repos/porter/workers/jobs
    
    the code of the file until where you have to start completion: //go:build ee

/*

                            === Recommender Job ===

This job checks to see if a cluster matches policies set by the OPA config file.

*/

package jobs

import (
	"context"
	"errors"
	"fmt"
	"log"
	"time"

	"github.com/mitchellh/mapstructure"
	"github.com/porter-dev/porter/api/server/shared/config/env"
	"github.com/porter-dev/porter/api/server/shared/requestutils"
	"github.com/porter-dev/porter/api/types"

	"github.com/porter-dev/porter/ee/integrations/vault"
	"github.com/porter-dev/porter/internal/encryption"
	"github.com/porter-dev/porter/internal/kubernetes"
	"github.com/porter-dev/porter/internal/models"
	"github.com/porter-dev/porter/internal/oauth"
	"github.com/porter-dev/porter/internal/opa"
	"github.com/porter-dev/porter/internal/repository"
	rcreds "github.com/porter-dev/porter/internal/repository/credentials"
	rgorm "github.com/porter-dev/porter/internal/repository/gorm"
	"golang.org/x/oauth2"
	"gorm.io/gorm"
)

type recommender struct {
	enqueueTime          time.Time
	db                   *gorm.DB
	repo                 repository.Repository
	doConf               *oauth2.Config
	clusterAndProjectIDs []clusterAndProjectID
	categories           []string
	policies             *opa.KubernetesPolicies
	runRecommenderID     string
}

// RecommenderOpts holds the options required to run this job
type RecommenderOpts struct {
	DBConf         *env.DBConf
	DOClientID     string
	DOClientSecret string
	DOScopes     
    
func (n *recommender) Run(ctx context.Context) error {
	for _, ids := range n.clusterAndProjectIDs {
		fmt.Println(ids.projectID, ids.clusterID)

		cluster, err := n.repo.Cluster().ReadCluster(ids.projectID, ids.clusterID)
		if err != nil {
			log.Printf("error reading cluster ID %d: %v. skipping cluster ...", ids.clusterID, err)
			continue
		}

		k8sAgent, err := kubernetes.GetAgentOutOfClusterConfig(ctx, &kubernetes.OutOfClusterConfig{
			Cluster:                   cluster,
			Repo:                      n.repo,
			DigitalOceanOAuth:         n.doConf,
			AllowInClusterConnections: false,
			Timeout:                   5 * time.Second,
		})
		if err != nil {
			log.Printf("error getting k8s agent for cluster ID %d: %v. skipping cluster ...", ids.clusterID, err)
			continue
		}

		dynamicClient, err := kubernetes.GetDynamicClientOutOfClusterConfig(&kubernetes.OutOfClusterConfig{
			Cluster:                   cluster,
			Repo:                      n.repo,
			DigitalOceanOAuth:         n.doConf,
			AllowInClusterConnections: false,
		})
		if err != nil {
			log.Printf("error getting dynamic client for cluster ID %d: %v. skipping cluster ...", ids.clusterID, err)
			continue
		}

		runner := opa.NewRunner(n.policies, cluster, k8sAgent, dynamicClient)

		queryResults, err := runner.GetRecommendations(n.categories)
		if err != nil {
			log.Printf("error querying opa policies for cluster ID %d: %v. skipping cluster ...", ids.clusterID, err)
			continue
		}

		for _, queryRes := range queryResults {
			fmt.Println(queryRes.ObjectID, queryRes.Allow, queryRes.PolicyTitle, queryRes.PolicyMessage)

			monitor, err := n.repo.MonitorTestResult().ReadMonitorTestResult(ids.projectID, ids.clusterID, queryRes.ObjectID)

			if err != nil {
				if errors.Is(err, gorm.ErrRecordNotFound) {
					monitor, err = n.repo.MonitorTestResult().CreateMonitorTestResult(n.getMonitorTestResultFromQueryResult(cluster, queryRes, n.runRecommenderID))
				} else {
					continue
				}
			} else {
				monitor, err = n.repo.MonitorTestResult().UpdateMonitorTestResult(mergeMonitorTestResultFromQueryResult(monitor, queryRes, n.runRecommenderID))
			}

			if err != nil {
				continue
			}
		}

		err = n.repo.MonitorTestResult().ArchiveMonitorTestResults(ids.projectID, ids.clusterID, n.runRecommenderID)

		if err != nil {
			log.Printf("error archiving test results for cluster ID %d: %v", ids.clusterID, err)
			continue
		}

		err = n.repo.MonitorTestResult().DeleteOldMonitorTestResults(ids.projectID, ids.clusterID, n.runRecommenderID)

		if err != nil {
			log.Printf("error deleting old test results for cluster ID %d: %v", ids.clusterID, err)
			continue
		}
	}

	return nil
}