Skip to content

Commit 93c39bf

Browse files
committed
Moved utility logics of progress bar to inspection/progress
Related to #250
1 parent 68059a4 commit 93c39bf

19 files changed

Lines changed: 268 additions & 70 deletions

File tree

pkg/core/inspection/runner.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -260,15 +260,15 @@ func (i *InspectionTaskRunner) Run(ctx context.Context, req *inspection_task.Ins
260260
resultSize := 0
261261
if result, err := i.runner.Result(); err != nil {
262262
if errors.Is(cancelableCtx.Err(), context.Canceled) {
263-
progress.Cancel()
263+
progress.MarkCancelled()
264264
status = "cancel"
265265
} else {
266-
progress.Error()
266+
progress.MarkError()
267267
status = "error"
268268
}
269269
slog.WarnContext(runCtx, fmt.Sprintf("task %s was finished with an error\n%s", i.ID, err))
270270
} else {
271-
progress.Done()
271+
progress.MarkDone()
272272
status = "done"
273273

274274
history, found := typedmap.Get(result, typedmap.NewTypedKey[inspectiondata.Store](serializer.SerializerTaskID.ReferenceIDString()))

pkg/inspection/form/fileform.go

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -52,10 +52,10 @@ func (b *FileFormTaskBuilder) WithDescription(description string) *FileFormTaskB
5252
}
5353

5454
func (b *FileFormTaskBuilder) Build(labelOpts ...common_task.LabelOpt) common_task.Task[upload.UploadResult] {
55-
return common_task.NewTask(b.id, b.dependencies, func(ctx context.Context) (upload.UploadResult, error) {
55+
return common_task.NewTask(b.FormTaskBuilderBase.id, b.FormTaskBuilderBase.dependencies, func(ctx context.Context) (upload.UploadResult, error) {
5656
metadata := khictx.MustGetValue(ctx, inspectioncontract.InspectionRunMetadata)
5757

58-
token := upload.DefaultUploadFileStore.GetUploadToken(upload.GenerateUploadIDWithTaskContext(ctx, b.id.ReferenceIDString()), b.verifier)
58+
token := upload.DefaultUploadFileStore.GetUploadToken(upload.GenerateUploadIDWithTaskContext(ctx, b.FormTaskBuilderBase.id.ReferenceIDString()), b.verifier)
5959
uploadResult, err := upload.DefaultUploadFileStore.GetResult(token)
6060
if err != nil {
6161
return upload.UploadResult{}, err
@@ -69,7 +69,7 @@ func (b *FileFormTaskBuilder) Build(labelOpts ...common_task.LabelOpt) common_ta
6969
Token: token,
7070
Status: uploadResult.Status,
7171
}
72-
b.SetupBaseFormField(&field.ParameterFormFieldBase)
72+
b.FormTaskBuilderBase.SetupBaseFormField(&field.ParameterFormFieldBase)
7373

7474
field = setFormHintsFromUploadResult(uploadResult, field)
7575
formFields, found := typedmap.Get(metadata, form_metadata.FormFieldSetMetadataKey)
@@ -78,7 +78,7 @@ func (b *FileFormTaskBuilder) Build(labelOpts ...common_task.LabelOpt) common_ta
7878
}
7979
err = formFields.SetField(field)
8080
if err != nil {
81-
return upload.UploadResult{}, fmt.Errorf("failed to configure the form metadata in task `%s`\n%v", b.id, err)
81+
return upload.UploadResult{}, fmt.Errorf("failed to configure the form metadata in task `%s`\n%v", b.FormTaskBuilderBase.id, err)
8282
}
8383

8484
return uploadResult, nil

pkg/inspection/metadata/progress/conformance_test.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,8 +25,8 @@ import (
2525

2626
func newProgressforConformanceTest() metadata.Metadata {
2727
progress := NewProgress()
28-
progress.GetTaskProgress("foo")
29-
progress.GetTaskProgress("bar")
28+
progress.GetOrCreateTaskProgress("foo")
29+
progress.GetOrCreateTaskProgress("bar")
3030
return progress
3131
}
3232

pkg/inspection/metadata/progress/progress.go

Lines changed: 58 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -22,13 +22,27 @@ import (
2222
"github.com/GoogleCloudPlatform/khi/pkg/inspection/metadata"
2323
)
2424

25+
// ProgressMetadataKey is the key used to store and retrieve Progress metadata
26+
// from a context or metadata map.
2527
var ProgressMetadataKey = metadata.NewMetadataKey[*Progress]("progress")
2628

27-
const TASK_PHASE_RUNNING = "RUNNING"
28-
const TASK_PHASE_DONE = "DONE"
29-
const TASK_PHASE_ERROR = "ERROR"
30-
const TASK_PHASE_CANCELLED = "CANCELLED"
29+
// TaskProgressPhase represents the lifecycle phase of a task's progress.
30+
type TaskProgressPhase string
31+
32+
// Constants defining the possible phases of a task's progress.
33+
const (
34+
// TaskPhaseRunning indicates that the task is currently executing.
35+
TaskPhaseRunning TaskProgressPhase = "RUNNING"
36+
// TaskPhaseDone indicates that the task has completed successfully.
37+
TaskPhaseDone = "DONE"
38+
// TaskPhaseError indicates that the task terminated with an error.
39+
TaskPhaseError = "ERROR"
40+
// TaskPhaseCancelled indicates that the task was cancelled before completion.
41+
TaskPhaseCancelled = "CANCELLED"
42+
)
3143

44+
// TaskProgress represents the progress of a single task within an inspection.
45+
// It includes an ID, a human-readable label, a status message, and completion percentage.
3246
type TaskProgress struct {
3347
Id string `json:"id"`
3448
Label string `json:"label"`
@@ -37,6 +51,7 @@ type TaskProgress struct {
3751
Indeterminate bool `json:"indeterminate"`
3852
}
3953

54+
// NewTaskProgress creates and initializes a new TaskProgress object with the given ID.
4055
func NewTaskProgress(id string) *TaskProgress {
4156
return &TaskProgress{
4257
Id: id,
@@ -60,18 +75,21 @@ func (tp *TaskProgress) MarkIndeterminate() {
6075
tp.Percentage = 0
6176
}
6277

78+
// Progress aggregates the progress of all tasks in an inspection run.
79+
// It tracks the overall phase, total progress, and the progress of individual active tasks.
6380
type Progress struct {
64-
Phase string `json:"phase"`
65-
TotalProgress *TaskProgress `json:"totalProgress"`
66-
TaskProgresses []*TaskProgress `json:"progresses"`
67-
totalTaskCount int `json:"-"`
68-
resolvedTaskCount int `json:"-"`
69-
lock sync.Mutex `json:"-"`
81+
Phase TaskProgressPhase `json:"phase"`
82+
TotalProgress *TaskProgress `json:"totalProgress"`
83+
TaskProgresses []*TaskProgress `json:"progresses"`
84+
totalTaskCount int `json:"-"`
85+
resolvedTaskCount int `json:"-"`
86+
lock sync.Mutex `json:"-"`
7087
}
7188

89+
// NewProgress creates and initializes a new Progress object.
7290
func NewProgress() *Progress {
7391
return &Progress{
74-
Phase: TASK_PHASE_RUNNING,
92+
Phase: TaskPhaseRunning,
7593
TaskProgresses: make([]*TaskProgress, 0),
7694
TotalProgress: NewTaskProgress("Total"),
7795
lock: sync.Mutex{},
@@ -92,15 +110,20 @@ func (p *Progress) ToSerializable() interface{} {
92110
return p
93111
}
94112

113+
// SetTotalTaskCount sets the total number of tasks that will be tracked.
114+
// This is used to calculate the overall progress percentage.
95115
func (p *Progress) SetTotalTaskCount(count int) {
96116
p.totalTaskCount = count
97117
p.updateTotalTaskProgress()
98118
}
99119

100-
func (p *Progress) GetTaskProgress(id string) (*TaskProgress, error) {
120+
// GetOrCreateTaskProgress retrieves the TaskProgress for a given task ID.
121+
// If no progress object exists for the ID, a new one is created and added to the list.
122+
// It returns an error if the overall progress is no longer in the RUNNING phase.
123+
func (p *Progress) GetOrCreateTaskProgress(id string) (*TaskProgress, error) {
101124
p.lock.Lock()
102125
defer p.lock.Unlock()
103-
if p.Phase != TASK_PHASE_RUNNING {
126+
if p.Phase != TaskPhaseRunning {
104127
return nil, fmt.Errorf("the current progress phase is not RUNNING but %s", p.Phase)
105128
}
106129
for _, progress := range p.TaskProgresses {
@@ -113,10 +136,13 @@ func (p *Progress) GetTaskProgress(id string) (*TaskProgress, error) {
113136
return taskProgress, nil
114137
}
115138

139+
// ResolveTask marks a task as resolved by removing it from the active progress list
140+
// and increments the count of resolved tasks.
141+
// It returns an error if the overall progress is no longer in the RUNNING phase.
116142
func (p *Progress) ResolveTask(id string) error {
117143
p.lock.Lock()
118144
defer p.lock.Unlock()
119-
if p.Phase != TASK_PHASE_RUNNING {
145+
if p.Phase != TaskPhaseRunning {
120146
return fmt.Errorf("the current progress phase is not RUNNING but %s", p.Phase)
121147
}
122148
newTaskProgress := make([]*TaskProgress, 0)
@@ -131,37 +157,46 @@ func (p *Progress) ResolveTask(id string) error {
131157
return nil
132158
}
133159

134-
func (p *Progress) Done() error {
160+
// MarkDone transitions the overall progress to the DONE phase.
161+
// It clears all active task progresses and marks the total progress as 100% complete.
162+
// It returns an error if the overall progress is no longer in the RUNNING phase.
163+
func (p *Progress) MarkDone() error {
135164
p.lock.Lock()
136165
defer p.lock.Unlock()
137-
if p.Phase != TASK_PHASE_RUNNING {
166+
if p.Phase != TaskPhaseRunning {
138167
return fmt.Errorf("the current progress phase is not RUNNING but %s", p.Phase)
139168
}
140-
p.Phase = TASK_PHASE_DONE
169+
p.Phase = TaskPhaseDone
141170
p.resolvedTaskCount = p.totalTaskCount
142171
p.TaskProgresses = make([]*TaskProgress, 0)
143172
p.updateTotalTaskProgress()
144173
return nil
145174
}
146175

147-
func (p *Progress) Cancel() error {
176+
// MarkCancelled transitions the overall progress to the CANCELLED phase.
177+
// It clears all active task progresses.
178+
// It returns an error if the overall progress is no longer in the RUNNING phase.
179+
func (p *Progress) MarkCancelled() error {
148180
p.lock.Lock()
149181
defer p.lock.Unlock()
150-
if p.Phase != TASK_PHASE_RUNNING {
182+
if p.Phase != TaskPhaseRunning {
151183
return fmt.Errorf("the current progress phase is not RUNNING but %s", p.Phase)
152184
}
153-
p.Phase = TASK_PHASE_CANCELLED
185+
p.Phase = TaskPhaseCancelled
154186
p.TaskProgresses = make([]*TaskProgress, 0)
155187
return nil
156188
}
157189

158-
func (p *Progress) Error() error {
190+
// MarkError transitions the overall progress to the ERROR phase.
191+
// It clears all active task progresses.
192+
// It returns an error if the overall progress is no longer in the RUNNING phase.
193+
func (p *Progress) MarkError() error {
159194
p.lock.Lock()
160195
defer p.lock.Unlock()
161-
if p.Phase != TASK_PHASE_RUNNING {
196+
if p.Phase != TaskPhaseRunning {
162197
return fmt.Errorf("the current progress phase is not RUNNING but %s", p.Phase)
163198
}
164-
p.Phase = TASK_PHASE_ERROR
199+
p.Phase = TaskPhaseError
165200
p.TaskProgresses = make([]*TaskProgress, 0)
166201
return nil
167202
}

pkg/inspection/metadata/progress/progress_test.go

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ import (
2525

2626
func TestGetTaskProgress(t *testing.T) {
2727
progress := NewProgress()
28-
tp, err := progress.GetTaskProgress("foo")
28+
tp, err := progress.GetOrCreateTaskProgress("foo")
2929
if err != nil {
3030
t.Errorf("unexpected error %s", err)
3131
}
@@ -41,7 +41,7 @@ func TestGetTaskProgress(t *testing.T) {
4141
t.Errorf("generated task progress is not containing the expected state\n%s", diff)
4242
}
4343

44-
tp2, err := progress.GetTaskProgress("foo")
44+
tp2, err := progress.GetOrCreateTaskProgress("foo")
4545
if err != nil {
4646
t.Errorf("unexpected error %s", err)
4747
}
@@ -54,8 +54,8 @@ func TestGetTaskProgress(t *testing.T) {
5454
func TestResolveTasks(t *testing.T) {
5555
progress := NewProgress()
5656
progress.SetTotalTaskCount(2)
57-
progress.GetTaskProgress("foo")
58-
progress.GetTaskProgress("bar")
57+
progress.GetOrCreateTaskProgress("foo")
58+
progress.GetOrCreateTaskProgress("bar")
5959
progress.ResolveTask("foo")
6060

6161
if diff := cmp.Diff(&Progress{
@@ -75,9 +75,9 @@ func TestResolveTasks(t *testing.T) {
7575
func TestDoneClearTasks(t *testing.T) {
7676
progress := NewProgress()
7777
progress.SetTotalTaskCount(2)
78-
progress.GetTaskProgress("foo")
79-
progress.GetTaskProgress("bar")
80-
progress.Done()
78+
progress.GetOrCreateTaskProgress("foo")
79+
progress.GetOrCreateTaskProgress("bar")
80+
progress.MarkDone()
8181

8282
if diff := cmp.Diff(&Progress{
8383
Phase: "DONE",
@@ -91,9 +91,9 @@ func TestDoneClearTasks(t *testing.T) {
9191
func TestCancelClearTasks(t *testing.T) {
9292
progress := NewProgress()
9393
progress.SetTotalTaskCount(2)
94-
progress.GetTaskProgress("foo")
95-
progress.GetTaskProgress("bar")
96-
progress.Cancel()
94+
progress.GetOrCreateTaskProgress("foo")
95+
progress.GetOrCreateTaskProgress("bar")
96+
progress.MarkCancelled()
9797

9898
if diff := cmp.Diff(&Progress{
9999
Phase: "CANCELLED",

pkg/inspection/metadata/progress/indeterminate_updator.go renamed to pkg/inspection/progressutil/indeterminate_updator.go

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,23 +12,29 @@
1212
// See the License for the specific language governing permissions and
1313
// limitations under the License.
1414

15-
package progress
15+
package progressutil
1616

1717
import (
1818
"context"
1919
"fmt"
2020
"time"
21+
22+
"github.com/GoogleCloudPlatform/khi/pkg/inspection/metadata/progress"
2123
)
2224

23-
// IndeterminateUpdator updates progress bar during a procedure can't report its progress.
25+
// IndeterminateUpdator updates a progress bar for a task that cannot report
26+
// its progress as a percentage. It shows a message with an animated indicator
27+
// to signify that the task is running.
2428
type IndeterminateUpdator struct {
25-
Progress *TaskProgress
29+
Progress *progress.TaskProgress
2630
Interval time.Duration
2731
context context.Context
2832
cancel func()
2933
}
3034

31-
func NewIndeterminateUpdator(progress *TaskProgress, interval time.Duration) *IndeterminateUpdator {
35+
// NewIndeterminateUpdator creates and initializes a new IndeterminateUpdator.
36+
// It marks the associated TaskProgress as indeterminate.
37+
func NewIndeterminateUpdator(progress *progress.TaskProgress, interval time.Duration) *IndeterminateUpdator {
3238
progress.Indeterminate = true
3339
return &IndeterminateUpdator{
3440
Progress: progress,

pkg/inspection/metadata/progress/indeterminate_updator_test.go renamed to pkg/inspection/progressutil/indeterminate_updator_test.go

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
// See the License for the specific language governing permissions and
1313
// limitations under the License.
1414

15-
package progress
15+
package progressutil
1616

1717
import (
1818
"testing"
@@ -22,32 +22,33 @@ import (
2222
"github.com/google/go-cmp/cmp/cmpopts"
2323

2424
_ "github.com/GoogleCloudPlatform/khi/internal/testflags"
25+
"github.com/GoogleCloudPlatform/khi/pkg/inspection/metadata/progress"
2526
)
2627

2728
func TestIndeterminateUpdator(t *testing.T) {
28-
progress := NewTaskProgress("foo")
29-
updator := NewIndeterminateUpdator(progress, 1000*time.Millisecond)
29+
tp := progress.NewTaskProgress("foo")
30+
updator := NewIndeterminateUpdator(tp, 1000*time.Millisecond)
3031
err := updator.Start("working")
3132
if err != nil {
3233
t.Errorf("unexpected error %s", err)
3334
}
3435
time.Sleep(1500 * time.Millisecond)
35-
if diff := cmp.Diff(&TaskProgress{
36+
if diff := cmp.Diff(&progress.TaskProgress{
3637
Id: "foo",
3738
Label: "foo",
3839
Message: "working.",
3940
Percentage: 0,
4041
Indeterminate: true,
41-
}, progress, cmpopts.IgnoreUnexported(TaskProgress{})); diff != "" {
42+
}, tp, cmpopts.IgnoreUnexported(progress.TaskProgress{})); diff != "" {
4243
t.Errorf("The result status is not in the expected status\n%s", diff)
4344
}
4445
err = updator.Done()
4546
if err != nil {
4647
t.Errorf("unexpected error %s", err)
4748
}
48-
msg := progress.Message
49+
msg := tp.Message
4950
time.Sleep(1000 * time.Millisecond)
50-
if msg != progress.Message {
51+
if msg != tp.Message {
5152
t.Errorf("The progress is keeping updated")
5253
}
5354
}

0 commit comments

Comments
 (0)