mirror of
https://github.com/aptly-dev/aptly.git
synced 2026-05-31 04:30:44 +00:00
Compare commits
1 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| d5f1929dd1 |
@@ -182,13 +182,6 @@ func apiSnapshotsCreate(c *gin.Context) {
|
||||
resources = append(resources, string(sources[i].ResourceKey()))
|
||||
}
|
||||
|
||||
// Pre-task check for destination snapshot name
|
||||
_, err = snapshotCollection.ByName(b.Name)
|
||||
if err == nil {
|
||||
AbortWithJSONError(c, 409, fmt.Errorf("unable to create: snapshot %s already exists", b.Name))
|
||||
return
|
||||
}
|
||||
|
||||
maybeRunTaskInBackground(c, "Create snapshot "+b.Name, resources, func(_ aptly.Progress, _ *task.Detail) (*task.ProcessReturnValue, error) {
|
||||
// Phase 2: Inside task lock - create fresh factory
|
||||
taskCollectionFactory := context.NewCollectionFactory()
|
||||
|
||||
@@ -461,3 +461,34 @@ class ReposAPITestCopyPackage(APITest):
|
||||
|
||||
self.check_equal(self.get(f"/api/repos/{repo2_name}/packages").json(),
|
||||
['Pi386 libboost-program-options-dev 1.49.0.1 918d2f433384e378'])
|
||||
|
||||
|
||||
class ReposAPITestCreateEdit(APITest):
|
||||
"""
|
||||
POST /api/repos,
|
||||
"""
|
||||
def check(self):
|
||||
repo_name = self.random_name() + ' with space'
|
||||
repo_desc = {'Comment': 'fun repo',
|
||||
'DefaultComponent': 'contrib',
|
||||
'DefaultDistribution': 'bookworm',
|
||||
'Name': repo_name}
|
||||
|
||||
resp = self.post("/api/repos", json=repo_desc)
|
||||
self.check_equal(resp.json(), repo_desc)
|
||||
self.check_equal(resp.status_code, 201)
|
||||
|
||||
repo_desc = {'Comment': 'modified repo',
|
||||
'DefaultComponent': 'main',
|
||||
'DefaultDistribution': 'trixie',
|
||||
'Name': repo_name + '@renamed'}
|
||||
resp = self.put(f"/api/repos/{repo_name}", json=repo_desc)
|
||||
self.check_equal(resp.json(), repo_desc)
|
||||
self.check_equal(resp.status_code, 200)
|
||||
|
||||
resp = self.get("/api/repos/" + repo_name + '@renamed')
|
||||
self.check_equal(resp.json(), repo_desc)
|
||||
self.check_equal(resp.status_code, 200)
|
||||
|
||||
resp = self.delete("/api/repos/" + repo_name + '@renamed')
|
||||
self.check_equal(resp.status_code, 200)
|
||||
|
||||
+21
-34
@@ -44,27 +44,25 @@ func (list *List) consumer() {
|
||||
for {
|
||||
select {
|
||||
case task := <-list.queue:
|
||||
// Set task state to RUNNING before processing
|
||||
list.Lock()
|
||||
task.State = RUNNING
|
||||
{
|
||||
task.State = RUNNING
|
||||
}
|
||||
list.Unlock()
|
||||
|
||||
go func() {
|
||||
retValue, err := task.process(aptly.Progress(task.output), task.detail)
|
||||
|
||||
// Update task completion state and cleanup with list lock held
|
||||
list.Lock()
|
||||
{
|
||||
task.processReturnValue = retValue
|
||||
task.err = err
|
||||
if err != nil {
|
||||
task.output.Printf("Task failed with error: %v", err)
|
||||
task.State = FAILED
|
||||
task.err = err
|
||||
task.processReturnValue = retValue
|
||||
} else {
|
||||
task.output.Print("Task succeeded")
|
||||
task.State = SUCCEEDED
|
||||
task.err = nil
|
||||
task.processReturnValue = retValue
|
||||
}
|
||||
|
||||
list.usedResources.Free(task.resources)
|
||||
@@ -107,15 +105,13 @@ func (list *List) Stop() {
|
||||
|
||||
// GetTasks gets complete list of tasks
|
||||
func (list *List) GetTasks() []Task {
|
||||
list.Lock()
|
||||
defer list.Unlock()
|
||||
|
||||
tasks := []Task{}
|
||||
list.Lock()
|
||||
for _, task := range list.tasks {
|
||||
// Copy task while holding list lock
|
||||
tasks = append(tasks, *task)
|
||||
}
|
||||
|
||||
list.Unlock()
|
||||
return tasks
|
||||
}
|
||||
|
||||
@@ -143,11 +139,11 @@ func (list *List) DeleteTaskByID(ID int) (Task, error) {
|
||||
// GetTaskByID returns task with given id
|
||||
func (list *List) GetTaskByID(ID int) (Task, error) {
|
||||
list.Lock()
|
||||
defer list.Unlock()
|
||||
tasks := list.tasks
|
||||
list.Unlock()
|
||||
|
||||
for _, task := range list.tasks {
|
||||
for _, task := range tasks {
|
||||
if task.ID == ID {
|
||||
// Copy task while holding list lock
|
||||
return *task, nil
|
||||
}
|
||||
}
|
||||
@@ -184,16 +180,13 @@ func (list *List) GetTaskDetailByID(ID int) (interface{}, error) {
|
||||
|
||||
// GetTaskReturnValueByID returns process return value of task with given id
|
||||
func (list *List) GetTaskReturnValueByID(ID int) (*ProcessReturnValue, error) {
|
||||
list.Lock()
|
||||
defer list.Unlock()
|
||||
task, err := list.GetTaskByID(ID)
|
||||
|
||||
for _, task := range list.tasks {
|
||||
if task.ID == ID {
|
||||
return task.processReturnValue, nil
|
||||
}
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return nil, fmt.Errorf("could not find task with id %v", ID)
|
||||
return task.processReturnValue, nil
|
||||
}
|
||||
|
||||
// RunTaskInBackground creates task and runs it in background. This will block until the necessary resources
|
||||
@@ -211,10 +204,6 @@ func (list *List) RunTaskInBackground(name string, resources []string, process P
|
||||
list.wg.Add(1)
|
||||
task.wgTask.Add(1)
|
||||
|
||||
// Copy task while still holding the lock to avoid racing with consumer
|
||||
// setting State=RUNNING after receiving from queue
|
||||
taskCopy := *task
|
||||
|
||||
// add task to queue for processing if resources are available
|
||||
// if not, task will be queued by the consumer once resources are available
|
||||
tasks := list.usedResources.UsedBy(resources)
|
||||
@@ -227,13 +216,12 @@ func (list *List) RunTaskInBackground(name string, resources []string, process P
|
||||
list.Unlock()
|
||||
}
|
||||
|
||||
return taskCopy, nil
|
||||
return *task, nil
|
||||
}
|
||||
|
||||
// Clear removes finished tasks from list
|
||||
func (list *List) Clear() {
|
||||
list.Lock()
|
||||
defer list.Unlock()
|
||||
|
||||
var tasks []*Task
|
||||
for _, task := range list.tasks {
|
||||
@@ -242,6 +230,8 @@ func (list *List) Clear() {
|
||||
}
|
||||
}
|
||||
list.tasks = tasks
|
||||
|
||||
list.Unlock()
|
||||
}
|
||||
|
||||
// Wait waits till all tasks are processed
|
||||
@@ -264,14 +254,11 @@ func (list *List) WaitForTaskByID(ID int) (Task, error) {
|
||||
|
||||
// GetTaskErrorByID returns the Task error for a given id
|
||||
func (list *List) GetTaskErrorByID(ID int) (error, error) {
|
||||
list.Lock()
|
||||
defer list.Unlock()
|
||||
task, err := list.GetTaskByID(ID)
|
||||
|
||||
for _, task := range list.tasks {
|
||||
if task.ID == ID {
|
||||
return task.err, nil
|
||||
}
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return nil, fmt.Errorf("could not find task with id %v", ID)
|
||||
return task.err, nil
|
||||
}
|
||||
|
||||
@@ -42,7 +42,6 @@ const (
|
||||
)
|
||||
|
||||
// Task represents as task in a queue encapsulates process code
|
||||
// All fields are protected by List.Mutex - access task fields only while holding list.Lock()
|
||||
type Task struct {
|
||||
output *Output
|
||||
detail *Detail
|
||||
|
||||
Reference in New Issue
Block a user