diff --git a/cmd/server/docs/docs.go b/cmd/server/docs/docs.go index d1a23505b..e7be9fe25 100644 --- a/cmd/server/docs/docs.go +++ b/cmd/server/docs/docs.go @@ -3967,6 +3967,10 @@ const docTemplate = `{ "last_contact": { "type": "integer" }, + "last_work": { + "description": "last time the agent did something, this value is used to determine if the agent is still doing work used by the autoscaler", + "type": "integer" + }, "name": { "type": "string" }, diff --git a/server/grpc/rpc.go b/server/grpc/rpc.go index 0631dd330..83d366c77 100644 --- a/server/grpc/rpc.go +++ b/server/grpc/rpc.go @@ -93,6 +93,17 @@ func (s *RPC) Wait(c context.Context, workflowID string) error { // Extend extends the lease for the workflow with the given ID. func (s *RPC) Extend(c context.Context, workflowID string) error { + agent, err := s.getAgentFromContext(c) + if err != nil { + return err + } + + agent.LastWork = time.Now().Unix() + err = s.store.AgentUpdate(agent) + if err != nil { + return err + } + return s.queue.Extend(c, workflowID) } @@ -226,7 +237,8 @@ func (s *RPC) Init(c context.Context, strWorkflowID string, state rpc.WorkflowSt } s.updateForgeStatus(c, repo, currentPipeline, workflow) - return nil + agent.LastWork = time.Now().Unix() + return s.store.AgentUpdate(agent) } // Done marks the workflow with the given ID as done. @@ -315,7 +327,12 @@ func (s *RPC) Done(c context.Context, strWorkflowID string, state rpc.WorkflowSt s.pipelineTime.WithLabelValues(repo.FullName, currentPipeline.Branch, string(workflow.State), workflow.Name).Set(float64(workflow.Finished - workflow.Started)) } - return nil + agent, err := s.getAgentFromContext(c) + if err != nil { + return err + } + agent.LastWork = time.Now().Unix() + return s.store.AgentUpdate(agent) } // Log writes a log entry to the database and publishes it to the pubsub. @@ -332,6 +349,7 @@ func (s *RPC) Log(c context.Context, rpcLogEntry *rpc.LogEntry) error { Data: rpcLogEntry.Data, Type: model.LogEntryType(rpcLogEntry.Type), } + // make sure writes to pubsub are non blocking (https://github.com/woodpecker-ci/woodpecker/blob/c919f32e0b6432a95e1a6d3d0ad662f591adf73f/server/logging/log.go#L9) go func() { // write line to listening web clients @@ -339,6 +357,16 @@ func (s *RPC) Log(c context.Context, rpcLogEntry *rpc.LogEntry) error { log.Error().Err(err).Msgf("rpc server could not write to logger") } }() + + agent, err := s.getAgentFromContext(c) + if err != nil { + return err + } + agent.LastWork = time.Now().Unix() + if err := s.store.AgentUpdate(agent); err != nil { + return err + } + return server.Config.Services.LogStore.LogAppend(logEntry) } diff --git a/server/model/agent.go b/server/model/agent.go index aebb9d742..31655cbb8 100644 --- a/server/model/agent.go +++ b/server/model/agent.go @@ -22,6 +22,7 @@ type Agent struct { OwnerID int64 `json:"owner_id" xorm:"'owner_id'"` Token string `json:"token" xorm:"token"` LastContact int64 `json:"last_contact" xorm:"last_contact"` + LastWork int64 `json:"last_work" xorm:"last_work"` // last time the agent did something, this value is used to determine if the agent is still doing work used by the autoscaler Platform string `json:"platform" xorm:"VARCHAR(100) 'platform'"` Backend string `json:"backend" xorm:"VARCHAR(100) 'backend'"` Capacity int32 `json:"capacity" xorm:"capacity"` diff --git a/woodpecker-go/woodpecker/types.go b/woodpecker-go/woodpecker/types.go index 7d2f0d46e..86fb90bf4 100644 --- a/woodpecker-go/woodpecker/types.go +++ b/woodpecker-go/woodpecker/types.go @@ -250,6 +250,7 @@ type ( OwnerID int64 `json:"owner_id"` Token string `json:"token"` LastContact int64 `json:"last_contact"` + LastWork int64 `json:"last_work"` Platform string `json:"platform"` Backend string `json:"backend"` Capacity int32 `json:"capacity"`