Repository: kubeflow/kfp-tekton (language: python)

Issue:
Pipelineloop cachehit on wrong argument inputs
/kind bug

**What steps did you take and what happened:**
This pipeline can reproduce the bug. When a nested pipeline take the same argument and pass it down to the nested component, the pipelineloop cache hit triggered because it was using the same pipeline argument reference. However, because the argument is a loop, the actual content is different between each loop. Since nested pipeline content won't get stringify until the nested pipeline is executed, it thought the nested loop is already ran before which is a wrong assumption.

Here is the pipeline to reproduce this error
```yaml
apiVersion: tekton.dev/v1beta1
kind: PipelineRun
metadata:
  name: loop-multi
  annotations:
    tekton.dev/output_artifacts: '{"print-01": [{"key": "artifacts/$PIPELINERUN/print-01/output_value.tgz",
      "name": "print-01-output_value", "path": "/tmp/outputs/output_value/data"}]}'
    tekton.dev/input_artifacts: '{}'
    tekton.dev/artifact_bucket: mlpipeline
    tekton.dev/artifact_endpoint: minio-service.kubeflow:9000
    tekton.dev/artifact_endpoint_scheme: http://
    tekton.dev/artifact_items: '{"print-01": [["output_value", "$(results.output-value.path)"]]}'
    sidecar.istio.io/inject: "false"
    tekton.dev/template: ''
    pipelines.kubeflow.org/big_data_passing_format: $(workspaces.$TASK_NAME.path)/artifacts/$ORIG_PR_NAME/$TASKRUN_NAME/$TASK_PARAM_NAME
    pipelines.kubeflow.org/pipeline_spec: '{"inputs": [{"default": "[\"a\", \"b\",
      \"c\"]", "name": "param", "optional": true, "type": "JsonArray"}], "name": "loop-multi"}'
  labels:
    pipelines.kubeflow.org/pipelinename: ''
    pipelines.kubeflow.org/generation: ''
spec:
  params:
  - name: param
    value: '["a", "b", "c"]'
  pipelineSpec:
    params:
    - name: param
      default: '["a", "b", "c"]'
    tasks:
    - name: loop-multi-for-loop-2
      params:
      - name: loop-item-param-1
        value: $(params.param)
      - name: loop-item-param-3
        value: $(params.param)
      - name: param
        value: $(params.param)
      taskSpec:
        apiVersion: custom.tekton.dev/v1alpha1
        kind: PipelineLoop
        spec:
          pipelineSpec:
            params:
            - name: loop-item-param-1
              type: string
            - name: loop-item-param-3
              type: string
            - name: param
              type: string
            tasks:
            - name: loop-multi-for-loop-4
              params:
              - name: loop-item-param-1
                value: $(params.loop-item-param-1)
              - name: loop-item-param-3
                value: $(params.loop-item-param-3)
              taskSpec:
                apiVersion: custom.tekton.dev/v1alpha1
                kind: PipelineLoop
                spec:
                  pipelineSpec:
                    params:
                    - name: loop-item-param-1
                      type: string
                    - name: loop-item-param-3
                      type: string
                    tasks:
                    - name: print-01
                      params:
                      - name: loop-item-param-1
                        value: $(params.loop-item-param-1)
                      - name: loop-item-param-3
                        value: $(params.loop-item-param-3)
                      taskSpec:
                        steps:
                        - name: main
                          command:
                          - sh
                          - -c
                          - |
                            set -e
                            echo $0 > $1
                          - print $(inputs.params.loop-item-param-1) $(inputs.params.loop-item-param-3)
                          - $(results.output-value.path)
                          image: alpine:3.6
                        params:
                        - name: loop-item-param-1
                          type: string
                        - name: loop-item-param-3
                          type: string
                        results:
                        - name: output-value
                          type: string
                          description: /tmp/outputs/output_value/data
                        metadata:
                          labels:
                            pipelines.kubeflow.org/cache_enabled: "true"
                          annotations:
                            pipelines.kubeflow.org/component_spec_digest: '{"name":
                              "print-01", "outputs": [{"description": "Represents
                              an output paramter.", "name": "output_value", "type":
                              "String"}], "version": "print-01@sha256=d511ac628d43cc5b393fbebd10be93662b30117f1413b84afd4e7b2e5ff5ed33"}'
                  iterateParam: loop-item-param-3
                metadata:
                  labels:
                    pipelines.kubeflow.org/cache_enabled: "true"
          iterateParam: loop-item-param-1
        metadata:
          labels:
            pipelines.kubeflow.org/cache_enabled: "true"
```


**What did you expect to happen:**
This should produce 9 printop pods, but instead the cachehit was triggered incorrectly for the last 2 nested loop and ended up with 3 printop.


**Additional information:**
[Miscellaneous information that will assist in solving the issue.]


**Environment:**

* Python Version (use `python --version`):
* SDK Version: 
* Tekton Version (use `tkn version`):
* Kubernetes Version (use `kubectl version`):
* OS (e.g. from `/etc/os-release`):



Discussion / hints:
/assign @ScrapCodes 

Fix patch:
diff --git a/tekton-catalog/cache/go.mod b/tekton-catalog/cache/go.mod
index 8728d1c25d..303134d826 100644
--- a/tekton-catalog/cache/go.mod
+++ b/tekton-catalog/cache/go.mod
@@ -3,8 +3,7 @@ module github.com/kubeflow/kfp-tekton/tekton-catalog/cache
 go 1.13
 
 require (
-	github.com/cenkalti/backoff v2.2.1+incompatible
-	github.com/go-sql-driver/mysql v1.6.0
-	github.com/jinzhu/gorm v1.9.16
-	github.com/mattn/go-sqlite3 v1.14.0
+	gorm.io/driver/mysql v1.4.3
+	gorm.io/driver/sqlite v1.4.2
+	gorm.io/gorm v1.24.0
 )
diff --git a/tekton-catalog/cache/pkg/db/db_conn_manager.go b/tekton-catalog/cache/pkg/db/db_conn_manager.go
index e72610d882..494758f02b 100644
--- a/tekton-catalog/cache/pkg/db/db_conn_manager.go
+++ b/tekton-catalog/cache/pkg/db/db_conn_manager.go
@@ -18,9 +18,8 @@ import (
 	"fmt"
 	"time"
 
-	_ "github.com/go-sql-driver/mysql"
-	"github.com/jinzhu/gorm"
 	"github.com/kubeflow/kfp-tekton/tekton-catalog/cache/pkg/model"
+	"gorm.io/gorm"
 )
 
 type ConnectionParams struct {
@@ -32,36 +31,32 @@ type ConnectionParams struct {
 	DbPwd               string
 	DbGroupConcatMaxLen string
 	DbExtraParams       string
-	Timeout				time.Duration
+	Timeout             time.Duration
 }
 
 func InitDBClient(params ConnectionParams, initConnectionTimeout time.Duration) (*gorm.DB, error) {
 	driverName := params.DbDriver
-	var arg string
+	var db *gorm.DB
 	var err error
 
 	switch driverName {
-	case mysqlDBDriverDefault:
-		arg, err = initMysql(params, initConnectionTimeout)
-		if err != nil {
-			return nil, err
-		}
-	case sqliteDriverDefault:
-		arg = initSqlite(params.DbName)
+	case "mysql":
+		db, err = initMysql(params)
+	case "sqlite":
+		db, err = initSqlite(params.DbName)
 	default:
-		return nil, fmt.Errorf("driver %v is not supported", driverName)
+		return nil, fmt.Errorf("driver %s is not supported", driverName)
 	}
 
 	// db is safe for concurrent use by multiple goroutines
 	// and maintains its own pool of idle connections.
-	db, err := gorm.Open(driverName, arg)
 	if err != nil {
 		return nil, err
 	}
 	// Create table
 	response := db.AutoMigrate(&model.TaskCache{})
-	if response.Error != nil {
-		return nil, fmt.Errorf("failed to initialize the databases: Error: %w", response.Error)
+	if response != nil {
+		return nil, fmt.Errorf("failed to initialize the databases: Error: %v", response)
 	}
 	return db, nil
 }
diff --git a/tekton-catalog/cache/pkg/db/mysql.go b/tekton-catalog/cache/pkg/db/mysql.go
index f1609e6f08..567fe277b6 100644
--- a/tekton-catalog/cache/pkg/db/mysql.go
+++ b/tekton-catalog/cache/pkg/db/mysql.go
@@ -15,14 +15,12 @@
 package db
 
 import (
-	"database/sql"
 	"encoding/json"
 	"fmt"
 	"time"
 
-	"github.com/cenkalti/backoff"
-
-	"github.com/go-sql-driver/mysql"
+	"gorm.io/driver/mysql"
+	"gorm.io/gorm"
 )
 
 const (
@@ -52,72 +50,37 @@ func (params *ConnectionParams) LoadMySQLDefaults() {
 	}
 }
 
-func initMysql(params ConnectionParams, initConnectionTimeout time.Duration) (string, error) {
+func initMysql(params ConnectionParams) (*gorm.DB, error) {
 	var mysqlExtraParams = map[string]string{}
 	data := []byte(params.DbExtraParams)
 	_ = json.Unmarshal(data, &mysqlExtraParams)
-	mysqlConfig := CreateMySQLConfig(
+	mysqlConfigDSN := CreateMySQLConfigDSN(
 		params.DbUser,
 		params.DbPwd,
 		params.DbHost,
 		params.DbPort,
-		"",
+		params.DbName,
 		params.DbGroupConcatMaxLen,
 		mysqlExtraParams,
 	)
-
-	var db *sql.DB
-	var err error
-	var operation = func() error {
-		db, err = sql.Open(params.DbDriver, mysqlConfig.FormatDSN())
-		if err != nil {
-			return err
-		}
-		return nil
-	}
-	b := backoff.NewExponentialBackOff()
-	b.MaxElapsedTime = initConnectionTimeout
-	err = backoff.Retry(operation, b)
-	if err != nil {
-		return "", err
-	}
-	defer db.Close()
-
-	// Create database if not exist
-	dbName := params.DbName
-	operation = func() error {
-		_, err = db.Exec(fmt.Sprintf("CREATE DATABASE IF NOT EXISTS %s", dbName))
-		if err != nil {
-			return err
-		}
-		return nil
-	}
-	b = backoff.NewExponentialBackOff()
-	b.MaxElapsedTime = initConnectionTimeout
-	err = backoff.Retry(operation, b)
-
-	operation = func() error {
-		_, err = db.Exec(fmt.Sprintf("USE %s", dbName))
-		if err != nil {
-			return err
-		}
-		return nil
-	}
-	b = backoff.NewExponentialBackOff()
-	b.MaxElapsedTime = initConnectionTimeout
-	err = backoff.Retry(operation, b)
-
-	mysqlConfig.DBName = dbName
-	// Config reference: https://github.com/go-sql-driver/mysql#clientfoundrows
-	mysqlConfig.ClientFoundRows = true
-	return mysqlConfig.FormatDSN(), nil
+	db, err := gorm.Open(mysql.New(mysql.Config{
+		DSN:                       mysqlConfigDSN, // data source name, refer https://github.com/go-sql-driver/mysql#dsn-data-source-name
+		DefaultStringSize:         256,            // add default size for string fields, by default, will use db type `longtext` for fields without size, not a primary key, no index defined and don't have default values
+		DontSupportRenameIndex:    true,           // drop & create index when rename index, rename index not supported before MySQL 5.7, MariaDB
+		DontSupportRenameColumn:   true,           // use change when rename column, rename rename not supported before MySQL 8, MariaDB
+		SkipInitializeWithVersion: false,          // smart configure based on used version
+	}), &gorm.Config{})
+
+	return db, err
 }
 
-func CreateMySQLConfig(user, password, mysqlServiceHost, mysqlServicePort, dbName, mysqlGroupConcatMaxLen string,
-	mysqlExtraParams map[string]string) *mysql.Config {
+func CreateMySQLConfigDSN(user, password, mysqlServiceHost, mysqlServicePort, dbName, mysqlGroupConcatMaxLen string,
+	mysqlExtraParams map[string]string) string {
 
+	if mysqlGroupConcatMaxLen == "" {
+		mysqlGroupConcatMaxLen = "4194304"
+	}
 	params := map[string]string{
-		"charset":              "utf8",
 		"parseTime":            "True",
 		"loc":                  "Local",
 		"group_concat_max_len": mysqlGroupConcatMaxLen,
@@ -126,14 +89,10 @@ func CreateMySQLConfig(user, password, mysqlServiceHost, mysqlServicePort, dbNam
 	for k, v := range mysqlExtraParams {
 		params[k] = v
 	}
+	dsn := fmt.Sprintf("%s:%s@tcp(%s:%s)/%s?charset=utf8mb4", user, password, mysqlServiceHost, mysqlServicePort, dbName)
 
-	return &mysql.Config{
-		User:                 user,
-		Passwd:               password,
-		Net:                  "tcp",
-		Addr:                 fmt.Sprintf("%s:%s", mysqlServiceHost, mysqlServicePort),
-		Params:               params,
-		DBName:               dbName,
-		AllowNativePasswords: true,
+	for k, v := range params {
+		dsn = fmt.Sprintf("%s&%s=%s", dsn, k, v)
 	}
+	return dsn
 }
diff --git a/tekton-catalog/cache/pkg/db/sqlite.go b/tekton-catalog/cache/pkg/db/sqlite.go
index 5c2e84a33a..18d2b71723 100644
--- a/tekton-catalog/cache/pkg/db/sqlite.go
+++ b/tekton-catalog/cache/pkg/db/sqlite.go
@@ -14,16 +14,19 @@
 
 package db
 
-const sqliteDriverDefault = "sqlite3"
+import (
+	"gorm.io/driver/sqlite"
+	"gorm.io/gorm"
+)
 
-func (params *ConnectionParams) LoadSqliteDefaults() {
-	setDefault(&params.DbDriver, sqliteDriverDefault)
-	setDefault(&params.DbName, ":memory:")
-}
-
-func initSqlite(dbName string) string {
+func initSqlite(dbName string) (*gorm.DB, error) {
+	var db *gorm.DB
+	var err error
 	if dbName == "" {
-		dbName = ":memory:" // default db.
+		db, err = gorm.Open(sqlite.Open(":memory:"), &gorm.Config{})
+	} else {
+		db, err = gorm.Open(sqlite.Open(dbName), &gorm.Config{})
 	}
-	return dbName
+
+	return db, err
 }
diff --git a/tekton-catalog/cache/pkg/task_cache_store.go b/tekton-catalog/cache/pkg/task_cache_store.go
index 6cb2fbaac6..25fcee430c 100644
--- a/tekton-catalog/cache/pkg/task_cache_store.go
+++ b/tekton-catalog/cache/pkg/task_cache_store.go
@@ -18,16 +18,15 @@ import (
 	"fmt"
 	"time"
 
-	"github.com/jinzhu/gorm"
 	"github.com/kubeflow/kfp-tekton/tekton-catalog/cache/pkg/db"
 	"github.com/kubeflow/kfp-tekton/tekton-catalog/cache/pkg/model"
+	"gorm.io/gorm"
 )
 
-
 type TaskCacheStore struct {
 	db       *gorm.DB
 	Disabled bool
-	Params db.ConnectionParams
+	Params   db.ConnectionParams
 }
 
 func (t *TaskCacheStore) Connect() error {
@@ -44,7 +43,7 @@ func (t *TaskCacheStore) Get(taskHashKey string) (*model.TaskCache, error) {
 		return nil, nil
 	}
 	entry := &model.TaskCache{}
-	d := t.db.Table("task_caches").Where("TaskHashKey = ?", taskHashKey).
+	d := t.db.Model(&model.TaskCache{}).Where("TaskHashKey = ?", taskHashKey).
 		Order("CreatedAt DESC").First(entry)
 	if d.Error != nil {
 		return nil, fmt.Errorf("failed to get entry from cache: %q. Error: %v", taskHashKey, d.Error)
@@ -52,20 +51,15 @@ func (t *TaskCacheStore) Get(taskHashKey string) (*model.TaskCache, error) {
 	return entry, nil
 }
 
-func (t *TaskCacheStore) Put(entry *model.TaskCache) (*model.TaskCache, error) {
+func (t *TaskCacheStore) Put(entry *model.TaskCache) error {
 	if t.Disabled || t.db == nil {
-		return nil, nil
-	}
-	ok := t.db.NewRecord(entry)
-	if !ok {
-		return nil, fmt.Errorf("failed to create a new cache entry, %#v, Error: %v", entry, t.db.Error)
+		return nil
 	}
-	rowInsert := &model.TaskCache{}
-	d := t.db.Create(entry).Scan(rowInsert)
+	d := t.db.Create(entry)
 	if d.Error != nil {
-		return nil, d.Error
+		return fmt.Errorf("failed to create a new cache entry, %#v, Error: %v", entry, t.db.Error)
 	}
-	return rowInsert, nil
+	return nil
 }
 
 func (t *TaskCacheStore) Delete(id string) error {
diff --git a/tekton-catalog/pipeline-loops/go.mod b/tekton-catalog/pipeline-loops/go.mod
index 545fcfb4a6..4802337ac3 100644
--- a/tekton-catalog/pipeline-loops/go.mod
+++ b/tekton-catalog/pipeline-loops/go.mod
@@ -3,11 +3,11 @@ module github.com/kubeflow/kfp-tekton/tekton-catalog/pipeline-loops
 go 1.13
 
 require (
+	github.com/cenkalti/backoff/v4 v4.1.3
 	github.com/google/go-cmp v0.5.8
 	github.com/hashicorp/go-multierror v1.1.1
 	github.com/kubeflow/kfp-tekton/tekton-catalog/cache v0.0.0
 	github.com/kubeflow/kfp-tekton/tekton-catalog/objectstore v0.0.0
-	github.com/mattn/go-sqlite3 v1.14.0
 	github.com/tektoncd/pipeline v0.38.4
 	go.uber.org/zap v1.21.0
 	gomodules.xyz/jsonpatch/v2 v2.2.0
diff --git a/tekton-catalog/pipeline-loops/pkg/reconciler/pipelinelooprun/controller.go b/tekton-catalog/pipeline-loops/pkg/reconciler/pipelinelooprun/controller.go
index a77efb836d..20463cc7d0 100644
--- a/tekton-catalog/pipeline-loops/pkg/reconciler/pipelinelooprun/controller.go
+++ b/tekton-catalog/pipeline-loops/pkg/reconciler/pipelinelooprun/controller.go
@@ -25,6 +25,7 @@ import (
 	"syscall"
 	"time"
 
+	backoff "github.com/cenkalti/backoff/v4"
 	taskCache "github.com/kubeflow/kfp-tekton/tekton-catalog/cache/pkg"
 	"github.com/kubeflow/kfp-tekton/tekton-catalog/cache/pkg/db"
 	cl "github.com/kubeflow/kfp-tekton/tekton-catalog/objectstore/pkg/writer"
@@ -75,7 +76,7 @@ func loadCacheConfig(ctx context.Context, kubeClientSet kubernetes.Interface, p
 	configMap, err := kubeClientSet.CoreV1().ConfigMaps(system.Namespace()).Get(ctx,
 		"cache-config", metaV1.GetOptions{})
 	if err != nil {
-		return false, err
+		return true, err
 	}
 	if configMap.Data["disabled"] == "true" {
 		return true, nil
@@ -89,7 +90,7 @@ func loadCacheConfig(ctx context.Context, kubeClientSet kubernetes.Interface, p
 	p.DbPwd = configMap.Data["password"]
 	timeout, err := time.ParseDuration(configMap.Data["timeout"])
 	if err != nil {
-		return false, err
+		return true, fmt.Errorf("invalid value passed for timeout: %v", err)
 	}
 	p.Timeout = timeout
 	return false, nil
@@ -101,17 +102,21 @@ func initCache(ctx context.Context, kubeClientSet kubernetes.Interface, params d
 	logger := logging.FromContext(ctx)
 	disabled, err := loadCacheConfig(ctx, kubeClientSet, &params)
 	if err != nil {
-		logger.Errorf("Config map could not be loaded. Error : %w", err)
-		params.LoadMySQLDefaults()
-		params.Timeout = 10 * time.Second
+		logger.Errorf("ConfigMap cache-config could not be loaded. "+
+			"Cache store disabled. Error : %v", err)
 	}
 	cacheStore := &taskCache.TaskCacheStore{Params: params}
 	if disabled {
 		cacheStore.Disabled = true
 	}
 	if !cacheStore.Disabled {
-		logger.Infof("Params: %#v", params)
-		err := cacheStore.Connect()
+		logger.Infof("Cache store Params: %#v", params)
+		b := backoff.NewExponentialBackOff()
+		b.MaxElapsedTime = params.Timeout
+		var operation = func() error {
+			return cacheStore.Connect()
+		}
+		err := backoff.Retry(operation, b)
 		if err != nil {
 			cacheStore.Disabled = true
 			logger.Errorf("Failed to connect to cache store backend, cache store disabled. err: %v", err)
diff --git a/tekton-catalog/pipeline-loops/pkg/reconciler/pipelinelooprun/pipelinelooprun.go b/tekton-catalog/pipeline-loops/pkg/reconciler/pipelinelooprun/pipelinelooprun.go
index 33943bcd92..01669a6bdc 100644
--- a/tekton-catalog/pipeline-loops/pkg/reconciler/pipelinelooprun/pipelinelooprun.go
+++ b/tekton-catalog/pipeline-loops/pkg/reconciler/pipelinelooprun/pipelinelooprun.go
@@ -105,6 +105,10 @@ type Reconciler struct {
 	cacheStore            *cache.TaskCacheStore
 	clock                 clock.RealClock
 }
+type CacheKey struct {
+	Params           []v1beta1.Param                        `json:"params"`
+	PipelineLoopSpec *pipelineloopv1alpha1.PipelineLoopSpec `json:"pipelineSpec"`
+}
 
 var (
 	// Check that our Reconciler implements runreconciler.Interface
@@ -207,14 +211,17 @@ func (c *Reconciler) ReconcileKind(ctx context.Context, run *v1alpha1.Run) pkgre
 
 	if run.IsDone() {
 		if run.IsSuccessful() && !c.cacheStore.Disabled && isCachingEnabled(run) {
-			marshal, err := json.Marshal(status.PipelineLoopSpec)
+			marshal, err := json.Marshal(CacheKey{
+				PipelineLoopSpec: status.PipelineLoopSpec,
+				Params:           run.Spec.Params,
+			})
 			if err == nil {
 				hashSum := fmt.Sprintf("%x", md5.Sum(marshal))
 				resultBytes, err1 := json.Marshal(run.Status.Results)
 				if err1 != nil {
 					return fmt.Errorf("error while marshalling result to cache for run: %s, %w", run.Name, err)
 				}
-				_, err = c.cacheStore.Put(&model.TaskCache{
+				err = c.cacheStore.Put(&model.TaskCache{
 					TaskHashKey: hashSum,
 					TaskOutput:  string(resultBytes),
 				})
@@ -353,8 +360,30 @@ func (c *Reconciler) reconcile(ctx context.Context, run *v1alpha1.Run, status *p
 			pipelineLoopMeta.Namespace, pipelineLoopMeta.Name, err)
 		return nil
 	}
+
+	// Determine how many iterations of the Task will be done.
+	totalIterations, iterationElements, err := computeIterations(run, pipelineLoopSpec)
+	if err != nil {
+		run.Status.MarkRunFailed(pipelineloopv1alpha1.PipelineLoopRunReasonFailedValidation.String(),
+			"Cannot determine number of iterations: %s", err)
+		return nil
+	}
+	if totalIterations > iterationLimit {
+		run.Status.MarkRunFailed(pipelineloopv1alpha1.PipelineLoopRunReasonFailedValidation.String(),
+			"Total number of iterations exceeds the limit: %d", iterationLimit)
+		return nil
+	}
+
+	// Update status of PipelineRuns.  Return the PipelineRun representing the highest loop iteration.
+	highestIteration, currentRunningPrs, failedPrs, err := c.updatePipelineRunStatus(ctx, iterationElements, run, status)
+	if err != nil {
+		return fmt.Errorf("error updating PipelineRun status for Run %s/%s: %w", run.Namespace, run.Name, err)
+	}
 	if !c.cacheStore.Disabled && isCachingEnabled(run) {
-		marshal, err := json.Marshal(pipelineLoopSpec)
+		marshal, err := json.Marshal(CacheKey{
+			PipelineLoopSpec: pipelineLoopSpec,
+			Params:           run.Spec.Params,
+		})
 		if marshal != nil && err == nil {
 			hashSum = fmt.Sprintf("%x", md5.Sum(marshal))
 			taskCache, err := c.cacheStore.Get(hashSum)
@@ -373,25 +402,6 @@ func (c *Reconciler) reconcile(ctx context.Context, run *v1alpha1.Run, status *p
 			logger.Warnf("failed marshalling the spec, for pipelineloop: %s", pipelineLoopMeta.Name)
 		}
 	}
-	// Determine how many iterations of the Task will be done.
-	totalIterations, iterationElements, err := computeIterations(run, pipelineLoopSpec)
-	if err != nil {
-		run.Status.MarkRunFailed(pipelineloopv1alpha1.PipelineLoopRunReasonFailedValidation.String(),
-			"Cannot determine number of iterations: %s", err)
-		return nil
-	}
-	if totalIterations > iterationLimit {
-		run.Status.MarkRunFailed(pipelineloopv1alpha1.PipelineLoopRunReasonFailedValidation.String(),
-			"Total number of iterations exceeds the limit: %d", iterationLimit)
-		return nil
-	}
-
-	// Update status of PipelineRuns.  Return the PipelineRun representing the highest loop iteration.
-	highestIteration, currentRunningPrs, failedPrs, err := c.updatePipelineRunStatus(ctx, iterationElements, run, status)
-	if err != nil {
-		return fmt.Errorf("error updating PipelineRun status for Run %s/%s: %w", run.Namespace, run.Name, err)
-	}
-
 	if highestIteration > 0 {
 		updateRunStatus(run, "last-idx", fmt.Sprintf("%d", highestIteration))
 		updateRunStatus(run, "last-elem", fmt.Sprintf("%s", iterationElements[highestIteration-1]))


Test patch:
diff --git a/tekton-catalog/cache/pkg/task_cache_store_test.go b/tekton-catalog/cache/pkg/task_cache_store_test.go
index 6c9f31d79e..fcbdbd92ee 100644
--- a/tekton-catalog/cache/pkg/task_cache_store_test.go
+++ b/tekton-catalog/cache/pkg/task_cache_store_test.go
@@ -22,13 +22,16 @@ import (
 
 	"github.com/kubeflow/kfp-tekton/tekton-catalog/cache/pkg/db"
 	"github.com/kubeflow/kfp-tekton/tekton-catalog/cache/pkg/model"
-	_ "github.com/mattn/go-sqlite3"
 )
 
 func newTestingCacheStore(disabled bool) (*TaskCacheStore, error) {
 	t := TaskCacheStore{
 		Disabled: disabled,
-		Params:   db.ConnectionParams{DbDriver: "sqlite3", DbName: ":memory:"},
+		// Params: db.ConnectionParams{DbDriver: "mysql", DbName: "testdb",
+		// 	DbHost: "127.0.0.1", DbPort: "3306", DbPwd: "", DbUser: "root",
+		// 	Timeout: 10 * time.Second,
+		// },
+		Params: db.ConnectionParams{DbDriver: "sqlite", DbName: ":memory:"},
 	}
 	err := t.Connect()
 	return &t, err
@@ -47,19 +50,11 @@ func TestPut(t *testing.T) {
 		t.Fatal(err)
 	}
 	entry := createTaskCache("x", "y")
-	taskCache, err := taskCacheStore.Put(entry)
+	err = taskCacheStore.Put(entry)
 	if err != nil {
 		t.Fatal(err)
 	}
-	if taskCache.TaskHashKey != entry.TaskHashKey {
-		t.Errorf("Mismatached key. Expected %s Found: %s", entry.TaskHashKey,
-			taskCache.TaskHashKey)
-	}
-	if taskCache.TaskOutput != entry.TaskOutput {
-		t.Errorf("Mismatached output. Expected : %s Found: %s",
-			entry.TaskOutput,
-			taskCache.TaskOutput)
-	}
+
 }
 
 func TestGet(t *testing.T) {
@@ -68,11 +63,11 @@ func TestGet(t *testing.T) {
 		t.Fatal(err)
 	}
 	entry := createTaskCache("x", "y")
-	taskCache, err := taskCacheStore.Put(entry)
+	err = taskCacheStore.Put(entry)
 	if err != nil {
 		t.Fatal(err)
 	}
-	cacheResult, err := taskCacheStore.Get(taskCache.TaskHashKey)
+	cacheResult, err := taskCacheStore.Get(entry.TaskHashKey)
 	if err != nil {
 		t.Error(err)
 	}
@@ -95,11 +90,11 @@ func TestGetLatest(t *testing.T) {
 	}
 	for i := 1; i < 10; i++ {
 		entry := createTaskCache("x", fmt.Sprintf("y%d", i))
-		taskCache, err := taskCacheStore.Put(entry)
+		err := taskCacheStore.Put(entry)
 		if err != nil {
 			t.Fatal(err)
 		}
-		cacheResult, err := taskCacheStore.Get(taskCache.TaskHashKey)
+		cacheResult, err := taskCacheStore.Get(entry.TaskHashKey)
 		if err != nil {
 			t.Error(err)
 		}
@@ -122,7 +117,7 @@ func TestDisabledCache(t *testing.T) {
 	}
 	taskCache, err := taskCacheStore.Get("random")
 	if err != nil {
-		t.Errorf("a disabled cache returned non nil error: %w", err)
+		t.Errorf("a disabled cache returned non nil error: %s", err)
 	}
 	if taskCache != nil {
 		t.Errorf("a disabled cache should return nil")
@@ -141,7 +136,7 @@ func TestPruneOlderThan(t *testing.T) {
 			TaskOutput:  "cacheOutput",
 			CreatedAt:   time.UnixMicro(int64(i * 100)),
 		}
-		_, err = taskCacheStore.Put(t1)
+		err = taskCacheStore.Put(t1)
 		if err != nil {
 			t.Fatal(err)
 		}
@@ -157,7 +152,7 @@ func TestPruneOlderThan(t *testing.T) {
 	if err != nil {
 		t.Fatal(err)
 	}
-	taskCache, err = taskCacheStore.Get(hashKey)
+	_, err = taskCacheStore.Get(hashKey)
 	if err == nil {
 		t.Errorf("Expected error to be not nil")
 	}
diff --git a/tekton-catalog/pipeline-loops/pkg/reconciler/pipelinelooprun/pipelineloop_range_test.go b/tekton-catalog/pipeline-loops/pkg/reconciler/pipelinelooprun/pipelineloop_range_test.go
index f0a2fa6125..70a16aaa83 100644
--- a/tekton-catalog/pipeline-loops/pkg/reconciler/pipelinelooprun/pipelineloop_range_test.go
+++ b/tekton-catalog/pipeline-loops/pkg/reconciler/pipelinelooprun/pipelineloop_range_test.go
@@ -24,7 +24,6 @@ import (
 	"github.com/google/go-cmp/cmp"
 	pipelineloopv1alpha1 "github.com/kubeflow/kfp-tekton/tekton-catalog/pipeline-loops/pkg/apis/pipelineloop/v1alpha1"
 	"github.com/kubeflow/kfp-tekton/tekton-catalog/pipeline-loops/test"
-	_ "github.com/mattn/go-sqlite3"
 	"github.com/tektoncd/pipeline/pkg/apis/pipeline/v1alpha1"
 	"github.com/tektoncd/pipeline/pkg/apis/pipeline/v1beta1"
 	"github.com/tektoncd/pipeline/test/diff"
diff --git a/tekton-catalog/pipeline-loops/pkg/reconciler/pipelinelooprun/pipelinelooprun_test.go b/tekton-catalog/pipeline-loops/pkg/reconciler/pipelinelooprun/pipelinelooprun_test.go
index a7e60b1e8b..9f612e712a 100644
--- a/tekton-catalog/pipeline-loops/pkg/reconciler/pipelinelooprun/pipelinelooprun_test.go
+++ b/tekton-catalog/pipeline-loops/pkg/reconciler/pipelinelooprun/pipelinelooprun_test.go
@@ -33,7 +33,6 @@ import (
 	fakeclient "github.com/kubeflow/kfp-tekton/tekton-catalog/pipeline-loops/pkg/client/injection/client/fake"
 	fakepipelineloopinformer "github.com/kubeflow/kfp-tekton/tekton-catalog/pipeline-loops/pkg/client/injection/informers/pipelineloop/v1alpha1/pipelineloop/fake"
 	"github.com/kubeflow/kfp-tekton/tekton-catalog/pipeline-loops/test"
-	_ "github.com/mattn/go-sqlite3"
 	"github.com/tektoncd/pipeline/pkg/apis/pipeline/v1alpha1"
 	"github.com/tektoncd/pipeline/pkg/apis/pipeline/v1beta1"
 	ttesting "github.com/tektoncd/pipeline/pkg/reconciler/testing"
@@ -61,7 +60,7 @@ var (
 
 func initCacheParams() {
 	tmp := os.TempDir()
-	params.DbDriver = "sqlite3"
+	params.DbDriver = "sqlite"
 	params.DbName = tmp + "/testing.db"
 	params.Timeout = 2 * time.Second
 }
@@ -2347,9 +2346,10 @@ func TestReconcilePipelineLoopRunCachedRun(t *testing.T) {
 			}
 			cm := corev1.ConfigMap{
 				ObjectMeta: metav1.ObjectMeta{
-					Name: "cache-config",
+					Name:      "cache-config",
+					Namespace: system.Namespace(),
 				},
-				Data: map[string]string{"driver": "sqlite3", "dbName": "/tmp/testing.db"},
+				Data: map[string]string{"driver": "sqlite", "dbName": "/tmp/testing2.db", "timeout": "2s"},
 			}
 			d := test.Data{
 				Runs:         []*v1alpha1.Run{tc.run},