code.gitea.io/gitea@v1.21.7/models/actions/tasks_version.go (about)

     1  // Copyright 2023 The Gitea Authors. All rights reserved.
     2  // SPDX-License-Identifier: MIT
     3  
     4  package actions
     5  
     6  import (
     7  	"context"
     8  
     9  	"code.gitea.io/gitea/models/db"
    10  	"code.gitea.io/gitea/modules/log"
    11  	"code.gitea.io/gitea/modules/timeutil"
    12  )
    13  
    14  // ActionTasksVersion
    15  // If both ownerID and repoID is zero, its scope is global.
    16  // If ownerID is not zero and repoID is zero, its scope is org (there is no user-level runner currrently).
    17  // If ownerID is zero and repoID is not zero, its scope is repo.
    18  type ActionTasksVersion struct {
    19  	ID          int64 `xorm:"pk autoincr"`
    20  	OwnerID     int64 `xorm:"UNIQUE(owner_repo)"`
    21  	RepoID      int64 `xorm:"INDEX UNIQUE(owner_repo)"`
    22  	Version     int64
    23  	CreatedUnix timeutil.TimeStamp `xorm:"created"`
    24  	UpdatedUnix timeutil.TimeStamp `xorm:"updated"`
    25  }
    26  
    27  func init() {
    28  	db.RegisterModel(new(ActionTasksVersion))
    29  }
    30  
    31  func GetTasksVersionByScope(ctx context.Context, ownerID, repoID int64) (int64, error) {
    32  	var tasksVersion ActionTasksVersion
    33  	has, err := db.GetEngine(ctx).Where("owner_id = ? AND repo_id = ?", ownerID, repoID).Get(&tasksVersion)
    34  	if err != nil {
    35  		return 0, err
    36  	} else if !has {
    37  		return 0, nil
    38  	}
    39  	return tasksVersion.Version, err
    40  }
    41  
    42  func insertTasksVersion(ctx context.Context, ownerID, repoID int64) (*ActionTasksVersion, error) {
    43  	tasksVersion := &ActionTasksVersion{
    44  		OwnerID: ownerID,
    45  		RepoID:  repoID,
    46  		Version: 1,
    47  	}
    48  	if _, err := db.GetEngine(ctx).Insert(tasksVersion); err != nil {
    49  		return nil, err
    50  	}
    51  	return tasksVersion, nil
    52  }
    53  
    54  func increaseTasksVersionByScope(ctx context.Context, ownerID, repoID int64) error {
    55  	result, err := db.GetEngine(ctx).Exec("UPDATE action_tasks_version SET version = version + 1 WHERE owner_id = ? AND repo_id = ?", ownerID, repoID)
    56  	if err != nil {
    57  		return err
    58  	}
    59  	affected, err := result.RowsAffected()
    60  	if err != nil {
    61  		return err
    62  	}
    63  
    64  	if affected == 0 {
    65  		// if update sql does not affect any rows, the database may be broken,
    66  		// so re-insert the row of version data here.
    67  		if _, err := insertTasksVersion(ctx, ownerID, repoID); err != nil {
    68  			return err
    69  		}
    70  	}
    71  
    72  	return nil
    73  }
    74  
    75  func IncreaseTaskVersion(ctx context.Context, ownerID, repoID int64) error {
    76  	ctx, commiter, err := db.TxContext(ctx)
    77  	if err != nil {
    78  		return err
    79  	}
    80  	defer commiter.Close()
    81  
    82  	// 1. increase global
    83  	if err := increaseTasksVersionByScope(ctx, 0, 0); err != nil {
    84  		log.Error("IncreaseTasksVersionByScope(Global): %v", err)
    85  		return err
    86  	}
    87  
    88  	// 2. increase owner
    89  	if ownerID > 0 {
    90  		if err := increaseTasksVersionByScope(ctx, ownerID, 0); err != nil {
    91  			log.Error("IncreaseTasksVersionByScope(Owner): %v", err)
    92  			return err
    93  		}
    94  	}
    95  
    96  	// 3. increase repo
    97  	if repoID > 0 {
    98  		if err := increaseTasksVersionByScope(ctx, 0, repoID); err != nil {
    99  			log.Error("IncreaseTasksVersionByScope(Repo): %v", err)
   100  			return err
   101  		}
   102  	}
   103  
   104  	return commiter.Commit()
   105  }