diff --git a/models/cloudbrain.go b/models/cloudbrain.go index edd5f102a..5be07f741 100755 --- a/models/cloudbrain.go +++ b/models/cloudbrain.go @@ -620,6 +620,18 @@ func GetCloudbrainByJobID(jobID string) (*Cloudbrain, error) { return getRepoCloudBrain(cb) } +func GetCloudbrainsNeededStopByUserID(userID int64) ([]*Cloudbrain, error) { + cloudBrains := make([]*Cloudbrain, 0) + err := x.Cols("job_id", "status", "type").Where("user_id=? AND (status =? OR status=?)", userID, string(JobRunning), string(JobWaiting)).Find(&cloudBrains) + return cloudBrains, err +} + +func GetCloudbrainsNeededStopByRepoID(repoID int64) ([]*Cloudbrain, error) { + cloudBrains := make([]*Cloudbrain, 0) + err := x.Cols("job_id", "status", "type").Where("repo_id=? AND (status =? OR status=?)", repoID, string(JobRunning), string(JobWaiting)).Find(&cloudBrains) + return cloudBrains, err +} + func SetCloudbrainStatusByJobID(jobID string, status CloudbrainStatus) (err error) { cb := &Cloudbrain{JobID: jobID, Status: string(status)} _, err = x.Cols("status").Where("cloudbrain.job_id=?", jobID).Update(cb) diff --git a/models/models.go b/models/models.go index 2fab3d0dc..eee29d2c7 100755 --- a/models/models.go +++ b/models/models.go @@ -59,6 +59,9 @@ var ( x *xorm.Engine tables []interface{} + xStatistic *xorm.Engine + tablesStatistic []interface{} + // HasEngine specifies if we have a xorm.Engine HasEngine bool ) @@ -132,14 +135,17 @@ func init() { new(RecommendOrg), ) + tablesStatistic = append(tablesStatistic, + new(FileChunk)) + gonicNames := []string{"SSL", "UID"} for _, name := range gonicNames { names.LintGonicMapper[name] = true } } -func getEngine() (*xorm.Engine, error) { - connStr, err := setting.DBConnStr() +func getEngine(database *setting.DBInfo) (*xorm.Engine, error) { + connStr, err := setting.DBConnStr(database) if err != nil { return nil, err } @@ -153,14 +159,12 @@ func getEngine() (*xorm.Engine, error) { } engine.SetSchema(setting.Database.Schema) - HasEngine = true - return engine, nil } // NewTestEngine sets a new test xorm.Engine func NewTestEngine(x *xorm.Engine) (err error) { - x, err = getEngine() + x, err = getEngine(setting.Database) if err != nil { return fmt.Errorf("Connect to database: %v", err) } @@ -171,43 +175,80 @@ func NewTestEngine(x *xorm.Engine) (err error) { return x.StoreEngine("InnoDB").Sync2(tables...) } -// SetEngine sets the xorm.Engine +// setEngine sets the xorm.Engine +func setEngine(engine *xorm.Engine, table []interface{}, database *setting.DBInfo) (err error) { + engine.SetMapper(names.GonicMapper{}) + // WARNING: for serv command, MUST remove the output to os.stdout, + // so use log file to instead print to stdout. + engine.SetLogger(NewXORMLogger(setting.Database.LogSQL)) + engine.ShowSQL(setting.Database.LogSQL) + engine.SetMaxOpenConns(setting.Database.MaxOpenConns) + engine.SetMaxIdleConns(setting.Database.MaxIdleConns) + engine.SetConnMaxLifetime(setting.Database.ConnMaxLifetime) + engine.Sync2(table...) + MigrateCustom(engine) + return nil +} + func SetEngine() (err error) { - x, err = getEngine() + x, err = getEngine(setting.Database) if err != nil { return fmt.Errorf("Failed to connect to database: %v", err) } + if err = setEngine(x, tables, setting.Database); err != nil { + return err + } + + xStatistic, err = getEngine(setting.DatabaseStatistic) + if err != nil { + return fmt.Errorf("Failed to connect to database: %v", err) + } + if err = setEngine(xStatistic, tablesStatistic, setting.DatabaseStatistic); err != nil { + return err + } - x.SetMapper(names.GonicMapper{}) - // WARNING: for serv command, MUST remove the output to os.stdout, - // so use log file to instead print to stdout. - x.SetLogger(NewXORMLogger(setting.Database.LogSQL)) - x.ShowSQL(setting.Database.LogSQL) - x.SetMaxOpenConns(setting.Database.MaxOpenConns) - x.SetMaxIdleConns(setting.Database.MaxIdleConns) - x.SetConnMaxLifetime(setting.Database.ConnMaxLifetime) - x.Sync2(tables...) - MigrateCustom(x) return nil } -// NewEngine initializes a new xorm.Engine func NewEngine(ctx context.Context, migrateFunc func(*xorm.Engine) error) (err error) { - if err = SetEngine(); err != nil { + x, err = getEngine(setting.Database) + if err != nil { + return fmt.Errorf("Failed to connect to database: %v", err) + } + if err = newEngine(ctx, migrateFunc, x, tables, setting.Database); err != nil { + return fmt.Errorf("newEngine failed: %v", err) + } + + xStatistic, err = getEngine(setting.DatabaseStatistic) + if err != nil { + return fmt.Errorf("Failed to connect to database: %v", err) + } + if err = newEngine(ctx, migrateFunc, xStatistic, tablesStatistic, setting.DatabaseStatistic); err != nil { + return fmt.Errorf("newEngine statistic failed: %v", err) + } + + HasEngine = true + + return nil +} + +// newEngine initializes a new xorm.Engine +func newEngine(ctx context.Context, migrateFunc func(*xorm.Engine) error, engine *xorm.Engine, table []interface{}, database *setting.DBInfo) (err error) { + if err = setEngine(engine, table, database); err != nil { return err } - x.SetDefaultContext(ctx) + engine.SetDefaultContext(ctx) - if err = x.Ping(); err != nil { + if err = engine.Ping(); err != nil { return err } - if err = migrateFunc(x); err != nil { + if err = migrateFunc(engine); err != nil { return fmt.Errorf("migrate: %v", err) } - if err = x.StoreEngine("InnoDB").Sync2(tables...); err != nil { + if err = engine.StoreEngine("InnoDB").Sync2(table...); err != nil { return fmt.Errorf("sync database struct error: %v", err) } @@ -257,6 +298,11 @@ func Ping() error { if x != nil { return x.Ping() } + + if xStatistic != nil { + return xStatistic.Ping() + } + return errors.New("database not configured") } diff --git a/models/repo.go b/models/repo.go index 2742c3e31..7f4bfebba 100755 --- a/models/repo.go +++ b/models/repo.go @@ -1424,6 +1424,12 @@ func GetAllRepositories() ([]*Repository, error) { return getALLRepositories(x) } +func GetAllRepositoriesByFilterCols(columns ...string) ([]*Repository, error) { + repos := make([]*Repository, 0, 1000) + return repos, x.Cols(columns...).Find(&repos) + +} + func updateRepository(e Engine, repo *Repository, visibilityChanged bool) (err error) { repo.LowerName = strings.ToLower(repo.Name) diff --git a/models/repo_activity_custom.go b/models/repo_activity_custom.go new file mode 100644 index 000000000..44d20abb3 --- /dev/null +++ b/models/repo_activity_custom.go @@ -0,0 +1,39 @@ +package models + +import "code.gitea.io/gitea/modules/git" + +func GetRepoKPIStats(repo *Repository) (*git.RepoKPIStats, error) { + return git.GetRepoKPIStats(repo.RepoPath()) +} + +func GetAllUserKPIStats() (map[string]*git.UserKPIStats, error) { + authors := make(map[string]*git.UserKPIStats) + repositorys, err := GetAllRepositoriesByFilterCols("owner_name", "name") + if err != nil { + return nil, err + } + + for _, repository := range repositorys { + authorsOneRepo, err1 := git.GetUserKPIStats(repository.RepoPath()) + if err1 != nil { + return nil, err + } + + for key, value := range authorsOneRepo { + if _, ok := authors[key]; !ok { + authors[key] = &git.UserKPIStats{ + + Name: value.Name, + Email: value.Email, + Commits: 0, + CommitLines: 0, + } + } + authors[key].Commits += value.Commits + authors[key].CommitLines += value.CommitLines + + } + + } + return authors, nil +} diff --git a/modules/git/repo_stats_custom.go b/modules/git/repo_stats_custom.go new file mode 100644 index 000000000..95f1086ad --- /dev/null +++ b/modules/git/repo_stats_custom.go @@ -0,0 +1,258 @@ +package git + +import ( + "bufio" + "bytes" + "fmt" + "sort" + "strconv" + "strings" + "time" +) + +type RepoKPIStats struct { + Contributors int64 + KeyContributors int64 + ContributorsAdded int64 + CommitsAdded int64 + CommitLinesModified int64 + Authors []*UserKPITypeStats +} + +type UserKPIStats struct { + Name string + Email string + Commits int64 + CommitLines int64 +} +type UserKPITypeStats struct { + UserKPIStats + isNewContributor bool //是否是4个月内的新增贡献者 +} + +func GetRepoKPIStats(repoPath string) (*RepoKPIStats, error) { + stats := &RepoKPIStats{} + + contributors, err := GetContributors(repoPath) + if err != nil { + return nil, err + } + timeUntil := time.Now() + fourMonthAgo := timeUntil.AddDate(0, -4, 0) + recentlyContributors, err := getContributors(repoPath, fourMonthAgo) + newContributersDict := make(map[string]struct{}) + if err != nil { + return nil, err + } + + if contributors != nil { + stats.Contributors = int64(len(contributors)) + for _, contributor := range contributors { + if contributor.CommitCnt >= 3 { + stats.KeyContributors++ + } + + if recentlyContributors != nil { + for _, recentlyContributor := range recentlyContributors { + if recentlyContributor.Email == contributor.Email && recentlyContributor.CommitCnt == contributor.CommitCnt { + stats.ContributorsAdded++ + newContributersDict[recentlyContributor.Email] = struct{}{} + } + + } + } + + } + + } + + err = setRepoKPIStats(repoPath, fourMonthAgo, stats, newContributersDict) + + if err != nil { + return nil, fmt.Errorf("FillFromGit: %v", err) + } + return stats, nil + +} + +//获取一天内的用户贡献指标 +func GetUserKPIStats(repoPath string) (map[string]*UserKPIStats, error) { + timeUntil := time.Now() + oneDayAgo := timeUntil.AddDate(0, 0, -1) + since := oneDayAgo.Format(time.RFC3339) + args := []string{"log", "--numstat", "--no-merges", "--branches=*", "--pretty=format:---%n%h%n%an%n%ae%n", "--date=iso", fmt.Sprintf("--since='%s'", since)} + stdout, err := NewCommand(args...).RunInDirBytes(repoPath) + if err != nil { + return nil, err + } + scanner := bufio.NewScanner(bytes.NewReader(stdout)) + scanner.Split(bufio.ScanLines) + usersKPIStatses := make(map[string]*UserKPIStats) + var author string + p := 0 + var email string + for scanner.Scan() { + l := strings.TrimSpace(scanner.Text()) + if l == "---" { + p = 1 + } else if p == 0 { + continue + } else { + p++ + } + if p > 4 && len(l) == 0 { + continue + } + switch p { + case 1: // Separator + case 2: // Commit sha-1 + case 3: // Author + author = l + case 4: // E-mail + email = strings.ToLower(l) + if _, ok := usersKPIStatses[email]; !ok { + usersKPIStatses[email] = &UserKPIStats{ + Name: author, + Email: email, + Commits: 0, + CommitLines: 0, + } + } + + usersKPIStatses[email].Commits++ + default: // Changed file + if parts := strings.Fields(l); len(parts) >= 3 { + if parts[0] != "-" { + if c, err := strconv.ParseInt(strings.TrimSpace(parts[0]), 10, 64); err == nil { + usersKPIStatses[email].CommitLines += c + } + } + if parts[1] != "-" { + if c, err := strconv.ParseInt(strings.TrimSpace(parts[1]), 10, 64); err == nil { + usersKPIStatses[email].CommitLines += c + } + } + + } + } + } + + return usersKPIStatses, nil + +} + +func setRepoKPIStats(repoPath string, fromTime time.Time, stats *RepoKPIStats, newContributers map[string]struct{}) error { + since := fromTime.Format(time.RFC3339) + args := []string{"log", "--numstat", "--no-merges", "--branches=*", "--pretty=format:---%n%h%n%an%n%ae%n", "--date=iso", fmt.Sprintf("--since='%s'", since)} + + stdout, err := NewCommand(args...).RunInDirBytes(repoPath) + if err != nil { + return err + } + + scanner := bufio.NewScanner(bytes.NewReader(stdout)) + scanner.Split(bufio.ScanLines) + + authors := make(map[string]*UserKPITypeStats) + + var author string + p := 0 + var email string + for scanner.Scan() { + l := strings.TrimSpace(scanner.Text()) + if l == "---" { + p = 1 + } else if p == 0 { + continue + } else { + p++ + } + if p > 4 && len(l) == 0 { + continue + } + switch p { + case 1: // Separator + case 2: // Commit sha-1 + stats.CommitsAdded++ + case 3: // Author + author = l + case 4: // E-mail + email = strings.ToLower(l) + if _, ok := authors[email]; !ok { + authors[email] = &UserKPITypeStats{ + UserKPIStats: UserKPIStats{ + Name: author, + Email: email, + Commits: 0, + CommitLines: 0, + }, + isNewContributor: false, + } + } + if _, ok := newContributers[email]; ok { + authors[email].isNewContributor = true + } + + authors[email].Commits++ + default: // Changed file + if parts := strings.Fields(l); len(parts) >= 3 { + if parts[0] != "-" { + if c, err := strconv.ParseInt(strings.TrimSpace(parts[0]), 10, 64); err == nil { + stats.CommitLinesModified += c + authors[email].CommitLines += c + } + } + if parts[1] != "-" { + if c, err := strconv.ParseInt(strings.TrimSpace(parts[1]), 10, 64); err == nil { + stats.CommitLinesModified += c + authors[email].CommitLines += c + } + } + + } + } + } + + a := make([]*UserKPITypeStats, 0, len(authors)) + for _, v := range authors { + a = append(a, v) + } + // Sort authors descending depending on commit count + sort.Slice(a, func(i, j int) bool { + return a[i].Commits > a[j].Commits + }) + + stats.Authors = a + return nil + +} + +func getContributors(repoPath string, fromTime time.Time) ([]Contributor, error) { + since := fromTime.Format(time.RFC3339) + cmd := NewCommand("shortlog", "-sne", "--all", fmt.Sprintf("--since='%s'", since)) + stdout, err := cmd.RunInDir(repoPath) + if err != nil { + return nil, err + } + stdout = strings.Trim(stdout, "\n") + contributorRows := strings.Split(stdout, "\n") + if len(contributorRows) > 0 { + contributorsInfo := make([]Contributor, len(contributorRows)) + for i := 0; i < len(contributorRows); i++ { + var oneCount string = strings.Trim(contributorRows[i], " ") + if strings.Index(oneCount, "\t") < 0 { + continue + } + number := oneCount[0:strings.Index(oneCount, "\t")] + commitCnt, _ := strconv.Atoi(number) + committer := oneCount[strings.Index(oneCount, "\t")+1 : strings.LastIndex(oneCount, " ")] + committer = strings.Trim(committer, " ") + email := oneCount[strings.Index(oneCount, "<")+1 : strings.Index(oneCount, ">")] + contributorsInfo[i] = Contributor{ + commitCnt, committer, email, + } + } + return contributorsInfo, nil + } + return nil, nil +} diff --git a/modules/setting/database.go b/modules/setting/database.go old mode 100644 new mode 100755 index 85043e8c1..e4c3a4149 --- a/modules/setting/database.go +++ b/modules/setting/database.go @@ -24,111 +24,119 @@ var ( EnableSQLite3 bool // Database holds the database settings - Database = struct { - Type string - Host string - Name string - User string - Passwd string - Schema string - SSLMode string - Path string - LogSQL bool - Charset string - Timeout int // seconds - UseSQLite3 bool - UseMySQL bool - UseMSSQL bool - UsePostgreSQL bool - DBConnectRetries int - DBConnectBackoff time.Duration - MaxIdleConns int - MaxOpenConns int - ConnMaxLifetime time.Duration - IterateBufferSize int - }{ - Timeout: 500, - } + Database *DBInfo + DatabaseStatistic *DBInfo ) +type DBInfo struct { + Type string + Host string + Name string + User string + Passwd string + Schema string + SSLMode string + Path string + LogSQL bool + Charset string + Timeout int // seconds + UseSQLite3 bool + UseMySQL bool + UseMSSQL bool + UsePostgreSQL bool + DBConnectRetries int + DBConnectBackoff time.Duration + MaxIdleConns int + MaxOpenConns int + ConnMaxLifetime time.Duration + IterateBufferSize int +} + // GetDBTypeByName returns the dataase type as it defined on XORM according the given name func GetDBTypeByName(name string) string { return dbTypes[name] } -// InitDBConfig loads the database settings -func InitDBConfig() { - sec := Cfg.Section("database") - Database.Type = sec.Key("DB_TYPE").String() - switch Database.Type { +// initDBConfig loads the database settings +func initDBConfig(section string, database *DBInfo) { + sec := Cfg.Section(section) + database.Type = sec.Key("DB_TYPE").String() + switch database.Type { case "sqlite3": - Database.UseSQLite3 = true + database.UseSQLite3 = true case "mysql": - Database.UseMySQL = true + database.UseMySQL = true case "postgres": - Database.UsePostgreSQL = true + database.UsePostgreSQL = true case "mssql": - Database.UseMSSQL = true + database.UseMSSQL = true } - Database.Host = sec.Key("HOST").String() - Database.Name = sec.Key("NAME").String() - Database.User = sec.Key("USER").String() - if len(Database.Passwd) == 0 { - Database.Passwd = sec.Key("PASSWD").String() + database.Host = sec.Key("HOST").String() + database.Name = sec.Key("NAME").String() + database.User = sec.Key("USER").String() + if len(database.Passwd) == 0 { + database.Passwd = sec.Key("PASSWD").String() } - Database.Schema = sec.Key("SCHEMA").String() - Database.SSLMode = sec.Key("SSL_MODE").MustString("disable") - Database.Charset = sec.Key("CHARSET").In("utf8", []string{"utf8", "utf8mb4"}) - Database.Path = sec.Key("PATH").MustString(filepath.Join(AppDataPath, "gitea.db")) - Database.Timeout = sec.Key("SQLITE_TIMEOUT").MustInt(500) - Database.MaxIdleConns = sec.Key("MAX_IDLE_CONNS").MustInt(2) - if Database.UseMySQL { - Database.ConnMaxLifetime = sec.Key("CONN_MAX_LIFE_TIME").MustDuration(3 * time.Second) + database.Schema = sec.Key("SCHEMA").String() + database.SSLMode = sec.Key("SSL_MODE").MustString("disable") + database.Charset = sec.Key("CHARSET").In("utf8", []string{"utf8", "utf8mb4"}) + database.Path = sec.Key("PATH").MustString(filepath.Join(AppDataPath, "gitea.db")) + database.Timeout = sec.Key("SQLITE_TIMEOUT").MustInt(500) + database.MaxIdleConns = sec.Key("MAX_IDLE_CONNS").MustInt(2) + if database.UseMySQL { + database.ConnMaxLifetime = sec.Key("CONN_MAX_LIFE_TIME").MustDuration(3 * time.Second) } else { - Database.ConnMaxLifetime = sec.Key("CONN_MAX_LIFE_TIME").MustDuration(0) + database.ConnMaxLifetime = sec.Key("CONN_MAX_LIFE_TIME").MustDuration(0) } - Database.MaxOpenConns = sec.Key("MAX_OPEN_CONNS").MustInt(0) + database.MaxOpenConns = sec.Key("MAX_OPEN_CONNS").MustInt(0) - Database.IterateBufferSize = sec.Key("ITERATE_BUFFER_SIZE").MustInt(50) - Database.LogSQL = sec.Key("LOG_SQL").MustBool(true) - Database.DBConnectRetries = sec.Key("DB_RETRIES").MustInt(10) - Database.DBConnectBackoff = sec.Key("DB_RETRY_BACKOFF").MustDuration(3 * time.Second) + database.IterateBufferSize = sec.Key("ITERATE_BUFFER_SIZE").MustInt(50) + database.LogSQL = sec.Key("LOG_SQL").MustBool(true) + database.DBConnectRetries = sec.Key("DB_RETRIES").MustInt(10) + database.DBConnectBackoff = sec.Key("DB_RETRY_BACKOFF").MustDuration(3 * time.Second) +} + +func InitDBConfig() { + Database = new(DBInfo) + DatabaseStatistic = new(DBInfo) + initDBConfig("database", Database) + initDBConfig("database_statistic", DatabaseStatistic) } // DBConnStr returns database connection string -func DBConnStr() (string, error) { +func DBConnStr(database *DBInfo) (string, error) { connStr := "" var Param = "?" - if strings.Contains(Database.Name, Param) { + if strings.Contains(database.Name, Param) { Param = "&" } - switch Database.Type { + switch database.Type { case "mysql": connType := "tcp" - if Database.Host[0] == '/' { // looks like a unix socket + if database.Host[0] == '/' { // looks like a unix socket connType = "unix" } - tls := Database.SSLMode + tls := database.SSLMode if tls == "disable" { // allow (Postgres-inspired) default value to work in MySQL tls = "false" } connStr = fmt.Sprintf("%s:%s@%s(%s)/%s%scharset=%s&parseTime=true&tls=%s", - Database.User, Database.Passwd, connType, Database.Host, Database.Name, Param, Database.Charset, tls) + database.User, database.Passwd, connType, database.Host, database.Name, Param, database.Charset, tls) case "postgres": - connStr = getPostgreSQLConnectionString(Database.Host, Database.User, Database.Passwd, Database.Name, Param, Database.SSLMode) + connStr = getPostgreSQLConnectionString(database.Host, database.User, database.Passwd, database.Name, Param, database.SSLMode) case "mssql": - host, port := ParseMSSQLHostPort(Database.Host) - connStr = fmt.Sprintf("server=%s; port=%s; database=%s; user id=%s; password=%s;", host, port, Database.Name, Database.User, Database.Passwd) + host, port := ParseMSSQLHostPort(database.Host) + connStr = fmt.Sprintf("server=%s; port=%s; database=%s; user id=%s; password=%s;", host, port, database.Name, database.User, database.Passwd) case "sqlite3": if !EnableSQLite3 { return "", errors.New("this binary version does not build support for SQLite3") } - if err := os.MkdirAll(path.Dir(Database.Path), os.ModePerm); err != nil { + if err := os.MkdirAll(path.Dir(database.Path), os.ModePerm); err != nil { return "", fmt.Errorf("Failed to create directories: %v", err) } - connStr = fmt.Sprintf("file:%s?cache=shared&mode=rwc&_busy_timeout=%d&_txlock=immediate", Database.Path, Database.Timeout) + connStr = fmt.Sprintf("file:%s?cache=shared&mode=rwc&_busy_timeout=%d&_txlock=immediate", database.Path, database.Timeout) default: - return "", fmt.Errorf("Unknown database type: %s", Database.Type) + return "", fmt.Errorf("Unknown database type: %s", database.Type) } return connStr, nil diff --git a/routers/repo/cloudbrain.go b/routers/repo/cloudbrain.go index deac7b312..c30906af4 100755 --- a/routers/repo/cloudbrain.go +++ b/routers/repo/cloudbrain.go @@ -13,6 +13,8 @@ import ( "strings" "time" + "code.gitea.io/gitea/modules/modelarts" + "code.gitea.io/gitea/modules/git" "code.gitea.io/gitea/modules/storage" @@ -361,6 +363,58 @@ func CloudBrainStop(ctx *context.Context) { ctx.Redirect(setting.AppSubURL + ctx.Repo.RepoLink + "/cloudbrain") } +func StopJobsByUserID(userID int64) { + cloudBrains, err := models.GetCloudbrainsNeededStopByUserID(userID) + if err != nil { + log.Warn("Failed to get cloudBrain info", err) + return + } + StopJobs(cloudBrains) + +} + +func StopJobsByRepoID(repoID int64) { + cloudBrains, err := models.GetCloudbrainsNeededStopByRepoID(repoID) + if err != nil { + log.Warn("Failed to get cloudBrain info", err) + return + } + StopJobs(cloudBrains) +} + +/** + + */ +func StopJobs(cloudBrains []*models.Cloudbrain) { + + for _, taskInfo := range cloudBrains { + + if taskInfo.Type == models.TypeCloudBrainOne { + err := cloudbrain.StopJob(taskInfo.JobID) + logErrorAndUpdateJobStatus(err, taskInfo) + } else { + param := models.NotebookAction{ + Action: models.ActionStop, + } + _, err := modelarts.StopJob(taskInfo.JobID, param) + logErrorAndUpdateJobStatus(err, taskInfo) + } + + } +} + +func logErrorAndUpdateJobStatus(err error, taskInfo *models.Cloudbrain) { + if err != nil { + log.Warn("Failed to stop cloudBrain job:"+taskInfo.JobID, err) + } else { + taskInfo.Status = string(models.JobStopped) + err = models.UpdateJob(taskInfo) + if err != nil { + log.Warn("UpdateJob failed", err) + } + } +} + func CloudBrainDel(ctx *context.Context) { var jobID = ctx.Params(":jobid") task, err := models.GetCloudbrainByJobID(jobID) diff --git a/routers/repo/setting.go b/routers/repo/setting.go index b2ca042de..bf11f9e5a 100644 --- a/routers/repo/setting.go +++ b/routers/repo/setting.go @@ -440,6 +440,7 @@ func SettingsPost(ctx *context.Context, form auth.RepoSettingForm) { return } log.Trace("Repository deleted: %s/%s", ctx.Repo.Owner.Name, repo.Name) + go StopJobsByRepoID(repo.ID) ctx.Flash.Success(ctx.Tr("repo.settings.deletion_success")) ctx.Redirect(ctx.Repo.Owner.DashboardLink()) diff --git a/routers/user/auth.go b/routers/user/auth.go index 13e338565..126d0a4c8 100755 --- a/routers/user/auth.go +++ b/routers/user/auth.go @@ -11,6 +11,8 @@ import ( "net/http" "strings" + "code.gitea.io/gitea/routers/repo" + "code.gitea.io/gitea/models" "code.gitea.io/gitea/modules/auth" "code.gitea.io/gitea/modules/auth/oauth2" @@ -1056,6 +1058,7 @@ func SignOut(ctx *context.Context) { }) } HandleSignOut(ctx) + go repo.StopJobsByUserID(ctx.User.ID) ctx.Redirect(setting.AppSubURL + "/") }