Skip to content
Snippets Groups Projects
Commit 4d8ebd67 authored by Yordan Kinkov's avatar Yordan Kinkov
Browse files

#15 tasklist status endpoint

parent 20e42216
No related branches found
No related tags found
No related merge requests found
Pipeline #51545 passed
......@@ -107,7 +107,7 @@ func main() {
)
{
taskSvc = task.New(storage, storage, cache, logger)
taskListSvc = tasklist.New(storage, storage, logger)
taskListSvc = tasklist.New(storage, storage, cache, logger)
healthSvc = health.New()
}
......
......@@ -55,9 +55,70 @@ an input to the next. If one task fails to execute, all following tasks are mark
- Parallel group execution: tasks within the group are executed in parallel and the results are dependant. If a task
fails to execute, this does not affect the other tasks but the group is marked with failed status.
### Task list State
The state of the task list asynchronous execution is available later on the `result` endpoint:
```shell
curl -v -X GET http://localhost:8082/v1/taskListResult/{taskListID}
```
The state is returned as an HTTP status code.
- Status code `200` for `Done` state;
- Status code `201` for `Created` state;
- Status code `202` for `Pending` state (the task list is being executed);
- Status code `207` for `Failed` state (at least one task within the task list has failed).
Example responses:
HTTP Response code `200`: Done
```json
{
"id": "ad641603-1ca0-4342-ad73-d70a6b1ec502",
"status": "done",
"groups": [
{
"id": "ad641603-1ca0-4342-ad73-d70a6b1ec502",
"type": "sequential",
"status": "done",
"tasks": [
{
"id": "ad641603-1ca0-4342-ad73-d70a6b1ec502",
"status": "done"
},
{
"id": "ad641603-1ca0-4342-ad73-d70a6b1ec502",
"status": "done"
}
]
}
]
}
```
HTTP Response code `207`: Failed
```json
{
"id": "ad641603-1ca0-4342-ad73-d70a6b1ec502",
"status": "failed",
"groups": [
{
"id": "ad641603-1ca0-4342-ad73-d70a6b1ec502",
"type": "sequential",
"status": "failed",
"tasks": [
{
"id": "ad641603-1ca0-4342-ad73-d70a6b1ec502",
"status": "done"
},
{
"id": "ad641603-1ca0-4342-ad73-d70a6b1ec502",
"status": "failed"
}
]
}
]
}
```
### Task list Executor Configuration
......
......@@ -3,6 +3,7 @@ package listexecutor
import (
"bytes"
"context"
"encoding/json"
"io"
"net/http"
"sync"
......@@ -11,6 +12,8 @@ import (
"go.uber.org/zap"
"code.vereign.com/gaiax/tsa/golib/errors"
"code.vereign.com/gaiax/tsa/golib/ptr"
goatasklist "code.vereign.com/gaiax/tsa/task/gen/task_list"
taskpkg "code.vereign.com/gaiax/tsa/task/internal/service/task"
"code.vereign.com/gaiax/tsa/task/internal/service/tasklist"
)
......@@ -125,13 +128,17 @@ func (l *ListExecutor) Execute(ctx context.Context, list *tasklist.TaskList) {
list.State = taskpkg.Pending
list.StartedAt = time.Now()
var state goatasklist.TaskListStatus
// execute groups sequentially
for i := range list.Groups {
if err := l.executeGroup(ctx, &list.Groups[i]); err != nil {
groupState, err := l.executeGroup(ctx, &list.Groups[i])
if err != nil {
logger.Error("error executing group", zap.Error(err))
list.Groups[i].State = taskpkg.Failed
list.State = taskpkg.Failed
}
state.Groups = append(state.Groups, groupState)
}
if list.State != taskpkg.Failed {
......@@ -139,6 +146,20 @@ func (l *ListExecutor) Execute(ctx context.Context, list *tasklist.TaskList) {
}
list.FinishedAt = time.Now()
state.ID = list.ID
state.Status = string(list.State)
value, err := json.Marshal(state)
if err != nil {
logger.Error("error marshaling taskList state", zap.Error(err))
} else {
if err := l.cache.Set(ctx, list.ID, list.CacheNamespace, list.CacheScope, value); err != nil {
logger.Error("error storing taskList state in cache", zap.Error(err))
} else {
logger.Debug("taskList state is stored in cache")
}
}
if err := l.storage.SaveTaskListHistory(ctx, list); err != nil {
logger.Error("error saving taskList history", zap.Error(err))
} else {
......@@ -150,7 +171,7 @@ func (l *ListExecutor) Execute(ctx context.Context, list *tasklist.TaskList) {
}
}
func (l *ListExecutor) executeGroup(ctx context.Context, group *tasklist.Group) error {
func (l *ListExecutor) executeGroup(ctx context.Context, group *tasklist.Group) (*goatasklist.GroupStatus, error) {
switch exec := group.Execution; exec {
case sequential:
return l.executeSequential(ctx, group)
......@@ -158,19 +179,22 @@ func (l *ListExecutor) executeGroup(ctx context.Context, group *tasklist.Group)
return l.executeParallel(ctx, group)
}
return errors.New("unknown type of group execution")
return nil, errors.New("unknown type of group execution")
}
func (l *ListExecutor) executeSequential(ctx context.Context, group *tasklist.Group) error {
func (l *ListExecutor) executeSequential(ctx context.Context, group *tasklist.Group) (*goatasklist.GroupStatus, error) {
group.State = taskpkg.Pending
var state goatasklist.GroupStatus
tasks, err := l.storage.GetGroupTasks(ctx, group)
if err != nil {
return err
return nil, err
}
req := group.Request
for _, task := range tasks {
taskState := goatasklist.TaskStatus{ID: &task.ID}
logger := l.logger.With(
zap.String("taskID", task.ID),
zap.String("taskName", task.Name),
......@@ -179,6 +203,8 @@ func (l *ListExecutor) executeSequential(ctx context.Context, group *tasklist.Gr
// mark all subsequent tasks as failed if one task already failed
if group.State == taskpkg.Failed {
task.State = taskpkg.Failed
taskState.Status = ptr.String(taskpkg.Failed)
state.Tasks = append(state.Tasks, &taskState)
continue
}
......@@ -186,12 +212,17 @@ func (l *ListExecutor) executeSequential(ctx context.Context, group *tasklist.Gr
err := l.executeTask(ctx, task)
if err != nil {
task.State = taskpkg.Failed
taskState.Status = ptr.String(taskpkg.Failed)
state.Tasks = append(state.Tasks, &taskState)
group.State = taskpkg.Failed
logger.Error("error executing task", zap.Error(err))
continue
}
logger.Debug("task execution completed successfully")
taskState.Status = ptr.String(string(task.State))
state.Tasks = append(state.Tasks, &taskState)
// pass the response from current task as an input to the next task
req = task.Response
......@@ -223,21 +254,29 @@ func (l *ListExecutor) executeSequential(ctx context.Context, group *tasklist.Gr
group.State = taskpkg.Done
}
return nil
state.ID = &group.ID
state.Status = ptr.String(string(group.State))
return &state, nil
}
func (l *ListExecutor) executeParallel(ctx context.Context, group *tasklist.Group) error {
func (l *ListExecutor) executeParallel(ctx context.Context, group *tasklist.Group) (*goatasklist.GroupStatus, error) {
group.State = taskpkg.Pending
var state goatasklist.GroupStatus
tasks, err := l.storage.GetGroupTasks(ctx, group)
if err != nil {
return err
return nil, err
}
var wg sync.WaitGroup
for _, task := range tasks {
wg.Add(1)
go func(t *taskpkg.Task) {
taskState := goatasklist.TaskStatus{
ID: &t.ID,
}
defer wg.Done()
logger := l.logger.With(
zap.String("taskID", t.ID),
......@@ -248,12 +287,17 @@ func (l *ListExecutor) executeParallel(ctx context.Context, group *tasklist.Grou
if err := l.executeTask(ctx, t); err != nil {
t.State = taskpkg.Failed
taskState.Status = ptr.String(taskpkg.Failed)
state.Tasks = append(state.Tasks, &taskState)
group.State = taskpkg.Failed
logger.Error("error executing task", zap.Error(err))
return
}
logger.Debug("task execution completed successfully")
taskState.Status = ptr.String(string(t.State))
state.Tasks = append(state.Tasks, &taskState)
if err := l.cache.Set(
ctx,
t.ID,
......@@ -286,7 +330,10 @@ func (l *ListExecutor) executeParallel(ctx context.Context, group *tasklist.Grou
group.State = taskpkg.Done
}
return nil
state.ID = &group.ID
state.Status = ptr.String(string(group.State))
return &state, nil
}
func (l *ListExecutor) executeTask(ctx context.Context, task *taskpkg.Task) error {
......
package tasklist
import (
"bytes"
"context"
"encoding/json"
"time"
......@@ -9,34 +10,45 @@ import (
"go.uber.org/zap"
"code.vereign.com/gaiax/tsa/golib/errors"
"code.vereign.com/gaiax/tsa/golib/ptr"
goatasklist "code.vereign.com/gaiax/tsa/task/gen/task_list"
"code.vereign.com/gaiax/tsa/task/internal/service/task"
)
//go:generate counterfeiter . Storage
//go:generate counterfeiter . Queue
//go:generate counterfeiter . Cache
// Storage for retrieving predefined task templates.
type Storage interface {
TaskListTemplate(ctx context.Context, taskListName string) (*Template, error)
TaskTemplates(ctx context.Context, names []string) (map[string]*task.Task, error)
TaskList(ctx context.Context, taskListID string) (*TaskList, error)
TaskListHistory(ctx context.Context, taskListID string) (*TaskList, error)
GetGroupTasks(ctx context.Context, group *Group) ([]*task.Task, error)
}
type Queue interface {
AddTaskList(ctx context.Context, taskList *TaskList, tasks []*task.Task) error
}
type Cache interface {
Get(ctx context.Context, key, namespace, scope string) ([]byte, error)
}
type Service struct {
storage Storage
queue Queue
cache Cache
logger *zap.Logger
}
func New(template Storage, queue Queue, logger *zap.Logger) *Service {
func New(template Storage, queue Queue, cache Cache, logger *zap.Logger) *Service {
return &Service{
storage: template,
queue: queue,
cache: cache,
logger: logger,
}
}
......@@ -105,6 +117,59 @@ func (s *Service) Create(ctx context.Context, req *goatasklist.CreateTaskListReq
}, nil
}
// TaskListResult retrieves a taskList result containing all tasks' unique IDs
// and statuses from the Cache service.
func (s *Service) TaskListResult(ctx context.Context, req *goatasklist.TaskListResultRequest) (res *goatasklist.TaskListStatus, err error) {
if req.TaskListID == "" {
return nil, errors.New(errors.BadRequest, "missing taskListID")
}
logger := s.logger.With(zap.String("taskListID", req.TaskListID))
var list *TaskList
list, err = s.storage.TaskListHistory(ctx, req.TaskListID)
if err != nil && !errors.Is(errors.NotFound, err) {
logger.Error("error getting taskList from history collection", zap.Error(err))
return nil, err
}
if list == nil {
list, err = s.storage.TaskList(ctx, req.TaskListID)
if err != nil {
if errors.Is(errors.NotFound, err) {
return nil, errors.New("taskList is not found", err)
}
logger.Error("error getting taskList from taskLists collection", zap.Error(err))
return nil, err
}
}
var result *goatasklist.TaskListStatus
if list.State != task.Done && list.State != task.Failed {
// taskList is not executed yet
result, err = s.calculateState(ctx, list)
if err != nil {
logger.Error("error calculating taskList state", zap.Error(err))
return nil, err
}
} else {
// taskList is already executed
var value []byte
value, err = s.cache.Get(ctx, list.ID, list.CacheNamespace, list.CacheScope)
if err != nil {
logger.Error("error getting taskList result from cache", zap.Error(err))
return nil, err
}
if err := json.NewDecoder(bytes.NewReader(value)).Decode(&result); err != nil {
logger.Error("error decoding result from cache", zap.Error(err))
return nil, errors.New("error decoding result from cache", err)
}
}
return result, nil
}
func createGroups(t *Template, req []byte) []Group {
var groups []Group
for _, group := range t.Groups {
......@@ -163,6 +228,36 @@ func createTasks(t *TaskList, templates map[string]*task.Task) ([]*task.Task, er
return tasks, nil
}
func (s *Service) calculateState(ctx context.Context, list *TaskList) (*goatasklist.TaskListStatus, error) {
result := &goatasklist.TaskListStatus{
ID: list.ID,
Status: string(list.State),
}
for i := range list.Groups {
groupState := goatasklist.GroupStatus{
ID: &list.Groups[i].ID,
Status: ptr.String(string(list.Groups[i].State)),
}
tasks, err := s.storage.GetGroupTasks(ctx, &list.Groups[i])
if err != nil {
return nil, err
}
for j := range tasks {
taskState := goatasklist.TaskStatus{
ID: &tasks[j].ID,
Status: ptr.String(string(tasks[j].State)),
}
groupState.Tasks = append(groupState.Tasks, &taskState)
}
result.Groups = append(result.Groups, &groupState)
}
return result, nil
}
// taskNamesFromTaskListTemplate returns the names of all tasks within
// one taskList template
func taskNamesFromTaskListTemplate(template *Template) []string {
......
......@@ -15,7 +15,7 @@ import (
)
func TestNew(t *testing.T) {
svc := tasklist.New(nil, nil, zap.NewNop())
svc := tasklist.New(nil, nil, nil, zap.NewNop())
assert.Implements(t, (*goatasklist.Service)(nil), svc)
}
......@@ -120,7 +120,7 @@ func Test_Create(t *testing.T) {
for _, test := range tests {
t.Run(test.name, func(t *testing.T) {
svc := tasklist.New(test.storage, test.queue, zap.NewNop())
svc := tasklist.New(test.storage, test.queue, nil, zap.NewNop())
res, err := svc.Create(context.Background(), test.req)
if err != nil {
assert.NotEmpty(t, test.errtext)
......@@ -138,3 +138,181 @@ func Test_Create(t *testing.T) {
})
}
}
func Test_TaskListResult(t *testing.T) {
tests := []struct {
name string
req *goatasklist.TaskListResultRequest
storage *tasklistfakes.FakeStorage
queue *tasklistfakes.FakeQueue
cache *tasklistfakes.FakeCache
errkind errors.Kind
errtext string
}{
{
name: "missing taskList ID",
req: &goatasklist.TaskListResultRequest{},
errkind: errors.BadRequest,
errtext: "missing taskListID",
},
{
name: "error getting taskList form history collection",
req: &goatasklist.TaskListResultRequest{TaskListID: "d16996cd-1977-42a9-90b2-b4548a35c1b4"},
storage: &tasklistfakes.FakeStorage{
TaskListHistoryStub: func(ctx context.Context, taskListID string) (*tasklist.TaskList, error) {
return nil, errors.New("some error")
},
},
errkind: errors.Unknown,
errtext: "some error",
},
{
name: "taskList not found",
req: &goatasklist.TaskListResultRequest{TaskListID: "d16996cd-1977-42a9-90b2-b4548a35c1b4"},
storage: &tasklistfakes.FakeStorage{
TaskListHistoryStub: func(ctx context.Context, taskListID string) (*tasklist.TaskList, error) {
return nil, errors.New(errors.NotFound)
},
TaskListStub: func(ctx context.Context, taskListID string) (*tasklist.TaskList, error) {
return nil, errors.New(errors.NotFound)
},
},
errkind: errors.NotFound,
errtext: "taskList is not found",
},
{
name: "error getting taskList from taskLists collection",
req: &goatasklist.TaskListResultRequest{TaskListID: "d16996cd-1977-42a9-90b2-b4548a35c1b4"},
storage: &tasklistfakes.FakeStorage{
TaskListHistoryStub: func(ctx context.Context, taskListID string) (*tasklist.TaskList, error) {
return nil, errors.New(errors.NotFound)
},
TaskListStub: func(ctx context.Context, taskListID string) (*tasklist.TaskList, error) {
return nil, errors.New("some error")
},
},
errkind: errors.Unknown,
errtext: "some error",
},
{
name: "error calculating taskList state",
req: &goatasklist.TaskListResultRequest{TaskListID: "d16996cd-1977-42a9-90b2-b4548a35c1b4"},
storage: &tasklistfakes.FakeStorage{
TaskListHistoryStub: func(ctx context.Context, taskListID string) (*tasklist.TaskList, error) {
return pendingTaskList, nil
},
GetGroupTasksStub: func(ctx context.Context, group *tasklist.Group) ([]*task.Task, error) {
return nil, errors.New("some error")
},
},
errkind: errors.Unknown,
errtext: "some error",
},
{
name: "error getting taskList from cache",
req: &goatasklist.TaskListResultRequest{TaskListID: "d16996cd-1977-42a9-90b2-b4548a35c1b4"},
storage: &tasklistfakes.FakeStorage{
TaskListHistoryStub: func(ctx context.Context, taskListID string) (*tasklist.TaskList, error) {
return doneTaskList, nil
},
},
cache: &tasklistfakes.FakeCache{
GetStub: func(ctx context.Context, key, namespace, scope string) ([]byte, error) {
return nil, errors.New("some cache error")
},
},
errkind: errors.Unknown,
errtext: "some cache error",
},
{
name: "successfully get taskList state on pending task",
req: &goatasklist.TaskListResultRequest{TaskListID: "d16996cd-1977-42a9-90b2-b4548a35c1b4"},
storage: &tasklistfakes.FakeStorage{
TaskListHistoryStub: func(ctx context.Context, taskListID string) (*tasklist.TaskList, error) {
return pendingTaskList, nil
},
GetGroupTasksStub: func(ctx context.Context, group *tasklist.Group) ([]*task.Task, error) {
return []*task.Task{}, nil
},
},
},
{
name: "successfully get taskList state on executed task",
req: &goatasklist.TaskListResultRequest{TaskListID: "d16996cd-1977-42a9-90b2-b4548a35c1b4"},
storage: &tasklistfakes.FakeStorage{
TaskListHistoryStub: func(ctx context.Context, taskListID string) (*tasklist.TaskList, error) {
return doneTaskList, nil
},
},
cache: &tasklistfakes.FakeCache{
GetStub: func(ctx context.Context, key, namespace, scope string) ([]byte, error) {
return doneTaskState, nil
},
},
},
}
for _, test := range tests {
t.Run(test.name, func(t *testing.T) {
svc := tasklist.New(test.storage, test.queue, test.cache, zap.NewNop())
res, err := svc.TaskListResult(context.Background(), test.req)
if err != nil {
assert.NotEmpty(t, test.errtext)
e, ok := err.(*errors.Error)
assert.True(t, ok)
assert.Equal(t, test.errkind, e.Kind)
assert.Contains(t, e.Error(), test.errtext)
assert.Nil(t, res)
} else {
assert.Empty(t, test.errtext)
assert.NotNil(t, res)
assert.NotEmpty(t, res.ID)
assert.NotEmpty(t, res.Status)
assert.NotEmpty(t, res.Groups)
}
})
}
}
//nolint:gosec
var pendingTaskList = &tasklist.TaskList{
ID: "16996cd-1977-42a9-90b2-b4548a35c1b4",
State: "pending",
Groups: []tasklist.Group{
{
ID: "074076d5-c995-4d2d-8d38-da57360453d4",
Tasks: []string{"createdTask", "createdTask2"},
State: "created",
},
},
}
//nolint:gosec
var doneTaskList = &tasklist.TaskList{
ID: "16996cd-1977-42a9-90b2-b4548a35c1b4",
State: "done",
}
//nolint:gosec
var doneTaskState = []byte(`{
"id": "ad641603-1ca0-4342-ad73-d70a6b1ec502",
"status": "done",
"groups": [
{
"id": "ad641603-1ca0-4342-ad73-d70a6b1ec502",
"type": "sequential",
"status": "done",
"tasks": [
{
"id": "ad641603-1ca0-4342-ad73-d70a6b1ec502",
"status": "done"
},
{
"id": "ad641603-1ca0-4342-ad73-d70a6b1ec502",
"status": "done"
}
]
}
]
}`)
// Code generated by counterfeiter. DO NOT EDIT.
package tasklistfakes
import (
"context"
"sync"
"code.vereign.com/gaiax/tsa/task/internal/service/tasklist"
)
type FakeCache struct {
GetStub func(context.Context, string, string, string) ([]byte, error)
getMutex sync.RWMutex
getArgsForCall []struct {
arg1 context.Context
arg2 string
arg3 string
arg4 string
}
getReturns struct {
result1 []byte
result2 error
}
getReturnsOnCall map[int]struct {
result1 []byte
result2 error
}
invocations map[string][][]interface{}
invocationsMutex sync.RWMutex
}
func (fake *FakeCache) Get(arg1 context.Context, arg2 string, arg3 string, arg4 string) ([]byte, error) {
fake.getMutex.Lock()
ret, specificReturn := fake.getReturnsOnCall[len(fake.getArgsForCall)]
fake.getArgsForCall = append(fake.getArgsForCall, struct {
arg1 context.Context
arg2 string
arg3 string
arg4 string
}{arg1, arg2, arg3, arg4})
stub := fake.GetStub
fakeReturns := fake.getReturns
fake.recordInvocation("Get", []interface{}{arg1, arg2, arg3, arg4})
fake.getMutex.Unlock()
if stub != nil {
return stub(arg1, arg2, arg3, arg4)
}
if specificReturn {
return ret.result1, ret.result2
}
return fakeReturns.result1, fakeReturns.result2
}
func (fake *FakeCache) GetCallCount() int {
fake.getMutex.RLock()
defer fake.getMutex.RUnlock()
return len(fake.getArgsForCall)
}
func (fake *FakeCache) GetCalls(stub func(context.Context, string, string, string) ([]byte, error)) {
fake.getMutex.Lock()
defer fake.getMutex.Unlock()
fake.GetStub = stub
}
func (fake *FakeCache) GetArgsForCall(i int) (context.Context, string, string, string) {
fake.getMutex.RLock()
defer fake.getMutex.RUnlock()
argsForCall := fake.getArgsForCall[i]
return argsForCall.arg1, argsForCall.arg2, argsForCall.arg3, argsForCall.arg4
}
func (fake *FakeCache) GetReturns(result1 []byte, result2 error) {
fake.getMutex.Lock()
defer fake.getMutex.Unlock()
fake.GetStub = nil
fake.getReturns = struct {
result1 []byte
result2 error
}{result1, result2}
}
func (fake *FakeCache) GetReturnsOnCall(i int, result1 []byte, result2 error) {
fake.getMutex.Lock()
defer fake.getMutex.Unlock()
fake.GetStub = nil
if fake.getReturnsOnCall == nil {
fake.getReturnsOnCall = make(map[int]struct {
result1 []byte
result2 error
})
}
fake.getReturnsOnCall[i] = struct {
result1 []byte
result2 error
}{result1, result2}
}
func (fake *FakeCache) Invocations() map[string][][]interface{} {
fake.invocationsMutex.RLock()
defer fake.invocationsMutex.RUnlock()
fake.getMutex.RLock()
defer fake.getMutex.RUnlock()
copiedInvocations := map[string][][]interface{}{}
for key, value := range fake.invocations {
copiedInvocations[key] = value
}
return copiedInvocations
}
func (fake *FakeCache) recordInvocation(key string, args []interface{}) {
fake.invocationsMutex.Lock()
defer fake.invocationsMutex.Unlock()
if fake.invocations == nil {
fake.invocations = map[string][][]interface{}{}
}
if fake.invocations[key] == nil {
fake.invocations[key] = [][]interface{}{}
}
fake.invocations[key] = append(fake.invocations[key], args)
}
var _ tasklist.Cache = new(FakeCache)
......@@ -10,6 +10,48 @@ import (
)
type FakeStorage struct {
GetGroupTasksStub func(context.Context, *tasklist.Group) ([]*task.Task, error)
getGroupTasksMutex sync.RWMutex
getGroupTasksArgsForCall []struct {
arg1 context.Context
arg2 *tasklist.Group
}
getGroupTasksReturns struct {
result1 []*task.Task
result2 error
}
getGroupTasksReturnsOnCall map[int]struct {
result1 []*task.Task
result2 error
}
TaskListStub func(context.Context, string) (*tasklist.TaskList, error)
taskListMutex sync.RWMutex
taskListArgsForCall []struct {
arg1 context.Context
arg2 string
}
taskListReturns struct {
result1 *tasklist.TaskList
result2 error
}
taskListReturnsOnCall map[int]struct {
result1 *tasklist.TaskList
result2 error
}
TaskListHistoryStub func(context.Context, string) (*tasklist.TaskList, error)
taskListHistoryMutex sync.RWMutex
taskListHistoryArgsForCall []struct {
arg1 context.Context
arg2 string
}
taskListHistoryReturns struct {
result1 *tasklist.TaskList
result2 error
}
taskListHistoryReturnsOnCall map[int]struct {
result1 *tasklist.TaskList
result2 error
}
TaskListTemplateStub func(context.Context, string) (*tasklist.Template, error)
taskListTemplateMutex sync.RWMutex
taskListTemplateArgsForCall []struct {
......@@ -42,6 +84,201 @@ type FakeStorage struct {
invocationsMutex sync.RWMutex
}
func (fake *FakeStorage) GetGroupTasks(arg1 context.Context, arg2 *tasklist.Group) ([]*task.Task, error) {
fake.getGroupTasksMutex.Lock()
ret, specificReturn := fake.getGroupTasksReturnsOnCall[len(fake.getGroupTasksArgsForCall)]
fake.getGroupTasksArgsForCall = append(fake.getGroupTasksArgsForCall, struct {
arg1 context.Context
arg2 *tasklist.Group
}{arg1, arg2})
stub := fake.GetGroupTasksStub
fakeReturns := fake.getGroupTasksReturns
fake.recordInvocation("GetGroupTasks", []interface{}{arg1, arg2})
fake.getGroupTasksMutex.Unlock()
if stub != nil {
return stub(arg1, arg2)
}
if specificReturn {
return ret.result1, ret.result2
}
return fakeReturns.result1, fakeReturns.result2
}
func (fake *FakeStorage) GetGroupTasksCallCount() int {
fake.getGroupTasksMutex.RLock()
defer fake.getGroupTasksMutex.RUnlock()
return len(fake.getGroupTasksArgsForCall)
}
func (fake *FakeStorage) GetGroupTasksCalls(stub func(context.Context, *tasklist.Group) ([]*task.Task, error)) {
fake.getGroupTasksMutex.Lock()
defer fake.getGroupTasksMutex.Unlock()
fake.GetGroupTasksStub = stub
}
func (fake *FakeStorage) GetGroupTasksArgsForCall(i int) (context.Context, *tasklist.Group) {
fake.getGroupTasksMutex.RLock()
defer fake.getGroupTasksMutex.RUnlock()
argsForCall := fake.getGroupTasksArgsForCall[i]
return argsForCall.arg1, argsForCall.arg2
}
func (fake *FakeStorage) GetGroupTasksReturns(result1 []*task.Task, result2 error) {
fake.getGroupTasksMutex.Lock()
defer fake.getGroupTasksMutex.Unlock()
fake.GetGroupTasksStub = nil
fake.getGroupTasksReturns = struct {
result1 []*task.Task
result2 error
}{result1, result2}
}
func (fake *FakeStorage) GetGroupTasksReturnsOnCall(i int, result1 []*task.Task, result2 error) {
fake.getGroupTasksMutex.Lock()
defer fake.getGroupTasksMutex.Unlock()
fake.GetGroupTasksStub = nil
if fake.getGroupTasksReturnsOnCall == nil {
fake.getGroupTasksReturnsOnCall = make(map[int]struct {
result1 []*task.Task
result2 error
})
}
fake.getGroupTasksReturnsOnCall[i] = struct {
result1 []*task.Task
result2 error
}{result1, result2}
}
func (fake *FakeStorage) TaskList(arg1 context.Context, arg2 string) (*tasklist.TaskList, error) {
fake.taskListMutex.Lock()
ret, specificReturn := fake.taskListReturnsOnCall[len(fake.taskListArgsForCall)]
fake.taskListArgsForCall = append(fake.taskListArgsForCall, struct {
arg1 context.Context
arg2 string
}{arg1, arg2})
stub := fake.TaskListStub
fakeReturns := fake.taskListReturns
fake.recordInvocation("TaskList", []interface{}{arg1, arg2})
fake.taskListMutex.Unlock()
if stub != nil {
return stub(arg1, arg2)
}
if specificReturn {
return ret.result1, ret.result2
}
return fakeReturns.result1, fakeReturns.result2
}
func (fake *FakeStorage) TaskListCallCount() int {
fake.taskListMutex.RLock()
defer fake.taskListMutex.RUnlock()
return len(fake.taskListArgsForCall)
}
func (fake *FakeStorage) TaskListCalls(stub func(context.Context, string) (*tasklist.TaskList, error)) {
fake.taskListMutex.Lock()
defer fake.taskListMutex.Unlock()
fake.TaskListStub = stub
}
func (fake *FakeStorage) TaskListArgsForCall(i int) (context.Context, string) {
fake.taskListMutex.RLock()
defer fake.taskListMutex.RUnlock()
argsForCall := fake.taskListArgsForCall[i]
return argsForCall.arg1, argsForCall.arg2
}
func (fake *FakeStorage) TaskListReturns(result1 *tasklist.TaskList, result2 error) {
fake.taskListMutex.Lock()
defer fake.taskListMutex.Unlock()
fake.TaskListStub = nil
fake.taskListReturns = struct {
result1 *tasklist.TaskList
result2 error
}{result1, result2}
}
func (fake *FakeStorage) TaskListReturnsOnCall(i int, result1 *tasklist.TaskList, result2 error) {
fake.taskListMutex.Lock()
defer fake.taskListMutex.Unlock()
fake.TaskListStub = nil
if fake.taskListReturnsOnCall == nil {
fake.taskListReturnsOnCall = make(map[int]struct {
result1 *tasklist.TaskList
result2 error
})
}
fake.taskListReturnsOnCall[i] = struct {
result1 *tasklist.TaskList
result2 error
}{result1, result2}
}
func (fake *FakeStorage) TaskListHistory(arg1 context.Context, arg2 string) (*tasklist.TaskList, error) {
fake.taskListHistoryMutex.Lock()
ret, specificReturn := fake.taskListHistoryReturnsOnCall[len(fake.taskListHistoryArgsForCall)]
fake.taskListHistoryArgsForCall = append(fake.taskListHistoryArgsForCall, struct {
arg1 context.Context
arg2 string
}{arg1, arg2})
stub := fake.TaskListHistoryStub
fakeReturns := fake.taskListHistoryReturns
fake.recordInvocation("TaskListHistory", []interface{}{arg1, arg2})
fake.taskListHistoryMutex.Unlock()
if stub != nil {
return stub(arg1, arg2)
}
if specificReturn {
return ret.result1, ret.result2
}
return fakeReturns.result1, fakeReturns.result2
}
func (fake *FakeStorage) TaskListHistoryCallCount() int {
fake.taskListHistoryMutex.RLock()
defer fake.taskListHistoryMutex.RUnlock()
return len(fake.taskListHistoryArgsForCall)
}
func (fake *FakeStorage) TaskListHistoryCalls(stub func(context.Context, string) (*tasklist.TaskList, error)) {
fake.taskListHistoryMutex.Lock()
defer fake.taskListHistoryMutex.Unlock()
fake.TaskListHistoryStub = stub
}
func (fake *FakeStorage) TaskListHistoryArgsForCall(i int) (context.Context, string) {
fake.taskListHistoryMutex.RLock()
defer fake.taskListHistoryMutex.RUnlock()
argsForCall := fake.taskListHistoryArgsForCall[i]
return argsForCall.arg1, argsForCall.arg2
}
func (fake *FakeStorage) TaskListHistoryReturns(result1 *tasklist.TaskList, result2 error) {
fake.taskListHistoryMutex.Lock()
defer fake.taskListHistoryMutex.Unlock()
fake.TaskListHistoryStub = nil
fake.taskListHistoryReturns = struct {
result1 *tasklist.TaskList
result2 error
}{result1, result2}
}
func (fake *FakeStorage) TaskListHistoryReturnsOnCall(i int, result1 *tasklist.TaskList, result2 error) {
fake.taskListHistoryMutex.Lock()
defer fake.taskListHistoryMutex.Unlock()
fake.TaskListHistoryStub = nil
if fake.taskListHistoryReturnsOnCall == nil {
fake.taskListHistoryReturnsOnCall = make(map[int]struct {
result1 *tasklist.TaskList
result2 error
})
}
fake.taskListHistoryReturnsOnCall[i] = struct {
result1 *tasklist.TaskList
result2 error
}{result1, result2}
}
func (fake *FakeStorage) TaskListTemplate(arg1 context.Context, arg2 string) (*tasklist.Template, error) {
fake.taskListTemplateMutex.Lock()
ret, specificReturn := fake.taskListTemplateReturnsOnCall[len(fake.taskListTemplateArgsForCall)]
......@@ -180,6 +417,12 @@ func (fake *FakeStorage) TaskTemplatesReturnsOnCall(i int, result1 map[string]*t
func (fake *FakeStorage) Invocations() map[string][][]interface{} {
fake.invocationsMutex.RLock()
defer fake.invocationsMutex.RUnlock()
fake.getGroupTasksMutex.RLock()
defer fake.getGroupTasksMutex.RUnlock()
fake.taskListMutex.RLock()
defer fake.taskListMutex.RUnlock()
fake.taskListHistoryMutex.RLock()
defer fake.taskListHistoryMutex.RUnlock()
fake.taskListTemplateMutex.RLock()
defer fake.taskListTemplateMutex.RUnlock()
fake.taskTemplatesMutex.RLock()
......
......@@ -315,3 +315,45 @@ func (s *Storage) SaveTaskListHistory(ctx context.Context, taskList *tasklist.Ta
b := backoff.WithContext(backoff.NewExponentialBackOff(), ctx)
return backoff.Retry(insert, b)
}
// TaskList retrieves a tasklist.TaskList from taskLists collection by ID
func (s *Storage) TaskList(ctx context.Context, taskListID string) (*tasklist.TaskList, error) {
result := s.taskLists.FindOne(ctx, bson.M{
"id": taskListID,
})
if result.Err() != nil {
if strings.Contains(result.Err().Error(), "no documents in result") {
return nil, errors.New(errors.NotFound, "taskList not found")
}
return nil, result.Err()
}
var list tasklist.TaskList
if err := result.Decode(&list); err != nil {
return nil, err
}
return &list, nil
}
// TaskListHistory retrieves a tasklist.TaskList from taskListHistory collection by ID
func (s *Storage) TaskListHistory(ctx context.Context, taskListID string) (*tasklist.TaskList, error) {
result := s.taskListHistory.FindOne(ctx, bson.M{
"id": taskListID,
})
if result.Err() != nil {
if strings.Contains(result.Err().Error(), "no documents in result") {
return nil, errors.New(errors.NotFound, "taskList not found")
}
return nil, result.Err()
}
var list tasklist.TaskList
if err := result.Decode(&list); err != nil {
return nil, err
}
return &list, nil
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment