github.com/pf-qiu/concourse/v6@v6.7.3-0.20201207032516-1f455d73275f/atc/db/pipeline_lifecycle.go (about)

     1  package db
     2  
     3  import (
     4  	"database/sql"
     5  	"fmt"
     6  
     7  	sq "github.com/Masterminds/squirrel"
     8  	"github.com/pf-qiu/concourse/v6/atc/db/lock"
     9  )
    10  
    11  //go:generate counterfeiter . PipelineLifecycle
    12  
    13  type PipelineLifecycle interface {
    14  	ArchiveAbandonedPipelines() error
    15  	RemoveBuildEventsForDeletedPipelines() error
    16  }
    17  
    18  func NewPipelineLifecycle(conn Conn, lockFactory lock.LockFactory) PipelineLifecycle {
    19  	return &pipelineLifecycle{
    20  		conn:        conn,
    21  		lockFactory: lockFactory,
    22  	}
    23  }
    24  
    25  type pipelineLifecycle struct {
    26  	conn        Conn
    27  	lockFactory lock.LockFactory
    28  }
    29  
    30  func (pl *pipelineLifecycle) ArchiveAbandonedPipelines() error {
    31  	tx, err := pl.conn.Begin()
    32  	if err != nil {
    33  		return err
    34  	}
    35  
    36  	defer Rollback(tx)
    37  
    38  	rows, err := pipelinesQuery.
    39  		LeftJoin("jobs j ON j.id = p.parent_job_id").
    40  		LeftJoin("pipelines p2 ON j.pipeline_id = p2.id").
    41  		Where(sq.Or{
    42  			// parent pipeline was destroyed
    43  			sq.And{
    44  				sq.NotEq{"p.parent_build_id": nil},
    45  				sq.Eq{"j.id": nil},
    46  			},
    47  			// pipeline was set by a job. The job was removed from the parent pipeline
    48  			sq.Eq{"j.active": false},
    49  			// parent pipeline was archived
    50  			sq.Eq{"p2.archived": true},
    51  		}).
    52  		RunWith(tx).
    53  		Query()
    54  	if err != nil {
    55  		return err
    56  	}
    57  	defer rows.Close()
    58  
    59  	err = archivePipelines(tx, pl.conn, pl.lockFactory, rows)
    60  	if err != nil {
    61  		return err
    62  	}
    63  
    64  	err = tx.Commit()
    65  	if err != nil {
    66  		return err
    67  	}
    68  
    69  	return nil
    70  }
    71  
    72  func archivePipelines(tx Tx, conn Conn, lockFactory lock.LockFactory, rows *sql.Rows) error {
    73  	var toArchive []pipeline
    74  	for rows.Next() {
    75  		p := newPipeline(conn, lockFactory)
    76  		if err := scanPipeline(p, rows); err != nil {
    77  			return err
    78  		}
    79  
    80  		toArchive = append(toArchive, *p)
    81  	}
    82  
    83  	for _, pipeline := range toArchive {
    84  		err := pipeline.archive(tx)
    85  		if err != nil {
    86  			return err
    87  		}
    88  	}
    89  
    90  	return nil
    91  }
    92  
    93  func (p *pipelineLifecycle) RemoveBuildEventsForDeletedPipelines() error {
    94  	rows, err := psql.Select("id").
    95  		From("deleted_pipelines").
    96  		RunWith(p.conn).
    97  		Query()
    98  	if err != nil {
    99  		return err
   100  	}
   101  
   102  	var idsToDelete []int
   103  	for rows.Next() {
   104  		var id int
   105  		if err := rows.Scan(&id); err != nil {
   106  			return err
   107  		}
   108  		idsToDelete = append(idsToDelete, id)
   109  	}
   110  
   111  	rows.Close()
   112  
   113  	if len(idsToDelete) == 0 {
   114  		return nil
   115  	}
   116  
   117  	for _, id := range idsToDelete {
   118  		_, err = p.conn.Exec(fmt.Sprintf("DROP TABLE IF EXISTS pipeline_build_events_%d", id))
   119  		if err != nil {
   120  			return err
   121  		}
   122  	}
   123  
   124  	_, err = psql.Delete("deleted_pipelines").
   125  		Where(sq.Eq{"id": idsToDelete}).
   126  		RunWith(p.conn).
   127  		Exec()
   128  	if err != nil {
   129  		return err
   130  	}
   131  
   132  	return nil
   133  }