mirror of
https://codeberg.org/forgejo/forgejo.git
synced 2024-11-26 23:09:28 +00:00
[GITEA] Show manual cron run's last time
- Currently in the cron tasks, the 'Previous Time' only displays the previous time of when the cron library executes the function, but not any of the manual executions of the task. - Store the last run's time in memory in the Task struct and use that, when that time is later than time that the cron library has executed this task. - This ensures that if an instance admin manually starts a task, there's feedback that this task is/has been run, because the task might be run that quick, that the status icon already has been changed to an checkmark, - Tasks that are executed at startup now reflect this as well, as the time of the execution of that task on startup is now being shown as 'Previous Time'. - Added integration tests for the API part, which is easier to test because querying the HTML table of cron tasks is non-trivial. - Resolves https://codeberg.org/forgejo/forgejo/issues/949 (cherry picked from commit0475e2048e
) (cherry picked from commitdcc952f0db
) (cherry picked from commit7168a240e8
) (cherry picked from commit4bc4cccb1b
) (cherry picked from commit3fe019ca3c
) [GITEA] Show manual cron run's last time (squash) 26 jobs in cron fixtures (cherry picked from commit8473030628
) (cherry picked from commit871c729742
) (cherry picked from commitdaefb27d2c
)
This commit is contained in:
parent
039fa20cc8
commit
2f66c1e4ce
|
@ -106,6 +106,12 @@ func ListTasks() TaskTable {
|
||||||
next = e.NextRun()
|
next = e.NextRun()
|
||||||
prev = e.PreviousRun()
|
prev = e.PreviousRun()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// If the manual run is after the cron run, use that instead.
|
||||||
|
if prev.Before(task.LastRun) {
|
||||||
|
prev = task.LastRun
|
||||||
|
}
|
||||||
|
|
||||||
task.lock.Lock()
|
task.lock.Lock()
|
||||||
tTable = append(tTable, &TaskTableRow{
|
tTable = append(tTable, &TaskTableRow{
|
||||||
Name: task.Name,
|
Name: task.Name,
|
||||||
|
|
|
@ -9,6 +9,7 @@ import (
|
||||||
"reflect"
|
"reflect"
|
||||||
"strings"
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
|
"time"
|
||||||
|
|
||||||
"code.gitea.io/gitea/models/db"
|
"code.gitea.io/gitea/models/db"
|
||||||
system_model "code.gitea.io/gitea/models/system"
|
system_model "code.gitea.io/gitea/models/system"
|
||||||
|
@ -37,6 +38,8 @@ type Task struct {
|
||||||
LastMessage string
|
LastMessage string
|
||||||
LastDoer string
|
LastDoer string
|
||||||
ExecTimes int64
|
ExecTimes int64
|
||||||
|
// This stores the time of the last manual run of this task.
|
||||||
|
LastRun time.Time
|
||||||
}
|
}
|
||||||
|
|
||||||
// DoRunAtStart returns if this task should run at the start
|
// DoRunAtStart returns if this task should run at the start
|
||||||
|
@ -88,6 +91,12 @@ func (t *Task) RunWithUser(doer *user_model.User, config Config) {
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
graceful.GetManager().RunWithShutdownContext(func(baseCtx context.Context) {
|
graceful.GetManager().RunWithShutdownContext(func(baseCtx context.Context) {
|
||||||
|
// Store the time of this run, before the function is executed, so it
|
||||||
|
// matches the behavior of what the cron library does.
|
||||||
|
t.lock.Lock()
|
||||||
|
t.LastRun = time.Now()
|
||||||
|
t.lock.Unlock()
|
||||||
|
|
||||||
pm := process.GetManager()
|
pm := process.GetManager()
|
||||||
doerName := ""
|
doerName := ""
|
||||||
if doer != nil && doer.ID != -1 {
|
if doer != nil && doer.ID != -1 {
|
||||||
|
|
|
@ -7,6 +7,7 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"net/http"
|
"net/http"
|
||||||
"testing"
|
"testing"
|
||||||
|
"time"
|
||||||
|
|
||||||
asymkey_model "code.gitea.io/gitea/models/asymkey"
|
asymkey_model "code.gitea.io/gitea/models/asymkey"
|
||||||
auth_model "code.gitea.io/gitea/models/auth"
|
auth_model "code.gitea.io/gitea/models/auth"
|
||||||
|
@ -282,3 +283,53 @@ func TestAPIRenameUser(t *testing.T) {
|
||||||
})
|
})
|
||||||
MakeRequest(t, req, http.StatusOK)
|
MakeRequest(t, req, http.StatusOK)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestAPICron(t *testing.T) {
|
||||||
|
defer tests.PrepareTestEnv(t)()
|
||||||
|
|
||||||
|
// user1 is an admin user
|
||||||
|
session := loginUser(t, "user1")
|
||||||
|
|
||||||
|
t.Run("List", func(t *testing.T) {
|
||||||
|
defer tests.PrintCurrentTest(t)()
|
||||||
|
|
||||||
|
token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeReadAdmin)
|
||||||
|
urlStr := fmt.Sprintf("/api/v1/admin/cron?token=%s", token)
|
||||||
|
req := NewRequest(t, "GET", urlStr)
|
||||||
|
resp := MakeRequest(t, req, http.StatusOK)
|
||||||
|
|
||||||
|
assert.Equal(t, "26", resp.Header().Get("X-Total-Count"))
|
||||||
|
|
||||||
|
var crons []api.Cron
|
||||||
|
DecodeJSON(t, resp, &crons)
|
||||||
|
assert.Len(t, crons, 26)
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("Execute", func(t *testing.T) {
|
||||||
|
defer tests.PrintCurrentTest(t)()
|
||||||
|
|
||||||
|
now := time.Now()
|
||||||
|
token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeWriteAdmin)
|
||||||
|
/// Archive cleanup is harmless, because in the text environment there are none
|
||||||
|
/// and is thus an NOOP operation and therefore doesn't interfere with any other
|
||||||
|
/// tests.
|
||||||
|
urlStr := fmt.Sprintf("/api/v1/admin/cron/archive_cleanup?token=%s", token)
|
||||||
|
req := NewRequest(t, "POST", urlStr)
|
||||||
|
MakeRequest(t, req, http.StatusNoContent)
|
||||||
|
|
||||||
|
// Check for the latest run time for this cron, to ensure it
|
||||||
|
// has been run.
|
||||||
|
urlStr = fmt.Sprintf("/api/v1/admin/cron?token=%s", token)
|
||||||
|
req = NewRequest(t, "GET", urlStr)
|
||||||
|
resp := MakeRequest(t, req, http.StatusOK)
|
||||||
|
|
||||||
|
var crons []api.Cron
|
||||||
|
DecodeJSON(t, resp, &crons)
|
||||||
|
|
||||||
|
for _, cron := range crons {
|
||||||
|
if cron.Name == "archive_cleanup" {
|
||||||
|
assert.True(t, now.Before(cron.Prev))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in a new issue