mirror of https://github.com/go-gitea/gitea
Make Requests Processes and create process hierarchy. Associate OpenRepository with context. (#17125)
This PR registers requests with the process manager and manages hierarchy within the processes. Git repos are then associated with a context, (usually the request's context) - with sub commands using this context as their base context. Signed-off-by: Andrew Thornton <art27@cantab.net>pull/17849/head^2
parent
d894c90b70
commit
01087e9eef
@ -0,0 +1,69 @@ |
||||
// Copyright 2021 The Gitea Authors. All rights reserved.
|
||||
// Use of this source code is governed by a MIT-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package process |
||||
|
||||
import ( |
||||
"context" |
||||
) |
||||
|
||||
// Context is a wrapper around context.Context and contains the current pid for this context
|
||||
type Context struct { |
||||
context.Context |
||||
pid IDType |
||||
} |
||||
|
||||
// GetPID returns the PID for this context
|
||||
func (c *Context) GetPID() IDType { |
||||
return c.pid |
||||
} |
||||
|
||||
// GetParent returns the parent process context (if any)
|
||||
func (c *Context) GetParent() *Context { |
||||
return GetContext(c.Context) |
||||
} |
||||
|
||||
// Value is part of the interface for context.Context. We mostly defer to the internal context - but we return this in response to the ProcessContextKey
|
||||
func (c *Context) Value(key interface{}) interface{} { |
||||
if key == ProcessContextKey { |
||||
return c |
||||
} |
||||
return c.Context.Value(key) |
||||
} |
||||
|
||||
// ProcessContextKey is the key under which process contexts are stored
|
||||
var ProcessContextKey interface{} = "process-context" |
||||
|
||||
// GetContext will return a process context if one exists
|
||||
func GetContext(ctx context.Context) *Context { |
||||
if pCtx, ok := ctx.(*Context); ok { |
||||
return pCtx |
||||
} |
||||
pCtxInterface := ctx.Value(ProcessContextKey) |
||||
if pCtxInterface == nil { |
||||
return nil |
||||
} |
||||
if pCtx, ok := pCtxInterface.(*Context); ok { |
||||
return pCtx |
||||
} |
||||
return nil |
||||
} |
||||
|
||||
// GetPID returns the PID for this context
|
||||
func GetPID(ctx context.Context) IDType { |
||||
pCtx := GetContext(ctx) |
||||
if pCtx == nil { |
||||
return "" |
||||
} |
||||
return pCtx.GetPID() |
||||
} |
||||
|
||||
// GetParentPID returns the ParentPID for this context
|
||||
func GetParentPID(ctx context.Context) IDType { |
||||
var parentPID IDType |
||||
if parentProcess := GetContext(ctx); parentProcess != nil { |
||||
parentPID = parentProcess.GetPID() |
||||
} |
||||
return parentPID |
||||
} |
@ -0,0 +1,66 @@ |
||||
// Copyright 2021 The Gitea Authors. All rights reserved.
|
||||
// Use of this source code is governed by a MIT-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package process |
||||
|
||||
import ( |
||||
"context" |
||||
"sync" |
||||
"time" |
||||
) |
||||
|
||||
// Process represents a working process inheriting from Gitea.
|
||||
type Process struct { |
||||
PID IDType // Process ID, not system one.
|
||||
ParentPID IDType |
||||
Description string |
||||
Start time.Time |
||||
Cancel context.CancelFunc |
||||
|
||||
lock sync.Mutex |
||||
children []*Process |
||||
} |
||||
|
||||
// Children gets the children of the process
|
||||
// Note: this function will behave nicely even if p is nil
|
||||
func (p *Process) Children() (children []*Process) { |
||||
if p == nil { |
||||
return |
||||
} |
||||
|
||||
p.lock.Lock() |
||||
defer p.lock.Unlock() |
||||
children = make([]*Process, len(p.children)) |
||||
copy(children, p.children) |
||||
return children |
||||
} |
||||
|
||||
// AddChild adds a child process
|
||||
// Note: this function will behave nicely even if p is nil
|
||||
func (p *Process) AddChild(child *Process) { |
||||
if p == nil { |
||||
return |
||||
} |
||||
|
||||
p.lock.Lock() |
||||
defer p.lock.Unlock() |
||||
p.children = append(p.children, child) |
||||
} |
||||
|
||||
// RemoveChild removes a child process
|
||||
// Note: this function will behave nicely even if p is nil
|
||||
func (p *Process) RemoveChild(process *Process) { |
||||
if p == nil { |
||||
return |
||||
} |
||||
|
||||
p.lock.Lock() |
||||
defer p.lock.Unlock() |
||||
for i, child := range p.children { |
||||
if child == process { |
||||
p.children = append(p.children[:i], p.children[i+1:]...) |
||||
return |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,20 @@ |
||||
<div class="item"> |
||||
<div class="df ac"> |
||||
<div class="content f1"> |
||||
<div class="header">{{.Process.Description}}</div> |
||||
<div class="description"><span title="{{DateFmtLong .Process.Start}}">{{TimeSince .Process.Start .root.Lang}}</span></div> |
||||
</div> |
||||
<div> |
||||
<a class="delete-button icon" href="" data-url="{{.root.Link}}/cancel/{{.Process.PID}}" data-id="{{.Process.PID}}" data-name="{{.Process.Description}}">{{svg "octicon-trash" 16 "text-red"}}</a> |
||||
</div> |
||||
</div> |
||||
|
||||
{{$children := .Process.Children}} |
||||
{{if $children}} |
||||
<div class="divided list"> |
||||
{{range $children}} |
||||
{{template "admin/process-row" dict "Process" . "root" $.root}} |
||||
{{end}} |
||||
</div> |
||||
{{end}} |
||||
</div> |
@ -0,0 +1,10 @@ |
||||
<h4 class="ui top attached header"> |
||||
{{.i18n.Tr "admin.monitor.process"}} |
||||
</h4> |
||||
<div class="ui attached segment"> |
||||
<div class="ui relaxed divided list"> |
||||
{{range .Processes}} |
||||
{{template "admin/process-row" dict "Process" . "root" $}} |
||||
{{end}} |
||||
</div> |
||||
</div> |
Loading…
Reference in new issue