Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

[update] Add progress status to the update #110

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
mirkoCrobu wants to merge 4 commits into main
base: main
Choose a base branch
Loading
from issue_521_progress_status_update_2
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view

Some comments aren't visible on the classic Files Changed page.

7 changes: 5 additions & 2 deletions cmd/arduino-app-cli/system/system.go
View file Open in desktop
Original file line number Diff line number Diff line change
Expand Up @@ -113,11 +113,14 @@ func newUpdateCmd() *cobra.Command {

events := updater.Subscribe()
for event := range events {
if event.Type == update.ErrorEvent {
switch event.Type {
case update.ErrorEvent:
// TODO: add colors to error messages
err := event.GetError()
feedback.Printf("Error: %s [%s]", err.Error(), update.GetUpdateErrorCode(err))
} else {
case update.ProgressEvent:
feedback.Printf("[%s] %.2f", event.Type.String(), event.GetProgress())
default:
feedback.Printf("[%s] %s", event.Type.String(), event.GetData())
}

Expand Down
10 changes: 8 additions & 2 deletions internal/api/handlers/update.go
View file Open in desktop
Original file line number Diff line number Diff line change
Expand Up @@ -152,7 +152,8 @@ func HandleUpdateEvents(updater *update.Manager) http.HandlerFunc {
slog.Info("APT event channel closed, stopping SSE stream")
return
}
if event.Type == update.ErrorEvent {
switch event.Type {
case update.ErrorEvent:
err := event.GetError()
code := render.InternalServiceErr
if c := update.GetUpdateErrorCode(err); c != update.UnknownErrorCode {
Expand All @@ -162,7 +163,12 @@ func HandleUpdateEvents(updater *update.Manager) http.HandlerFunc {
Code: code,
Message: err.Error(),
})
} else {
case update.ProgressEvent:
sseStream.Send(render.SSEEvent{
Type: event.Type.String(),
Data: event.GetProgress(),
})
default:
sseStream.Send(render.SSEEvent{
Type: event.Type.String(),
Data: event.GetData(),
Expand Down
8 changes: 5 additions & 3 deletions internal/update/apt/service.go
View file Open in desktop
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,6 @@ func (s *Service) UpgradePackages(ctx context.Context, names []string) (<-chan u
return nil, update.ErrOperationAlreadyInProgress
}
eventsCh := make(chan update.Event, 100)

go func() {
defer s.lock.Unlock()
defer close(eventsCh)
Expand All @@ -96,6 +95,7 @@ func (s *Service) UpgradePackages(ctx context.Context, names []string) (<-chan u
}()

eventsCh <- update.NewDataEvent(update.StartEvent, "Upgrade is starting")
eventsCh <- update.NewProgressEvent(0.0)
stream := runUpgradeCommand(ctx, names)
for line, err := range stream {
if err != nil {
Expand All @@ -104,16 +104,17 @@ func (s *Service) UpgradePackages(ctx context.Context, names []string) (<-chan u
}
eventsCh <- update.NewDataEvent(update.UpgradeLineEvent, line)
}

eventsCh <- update.NewDataEvent(update.StartEvent, "apt cleaning cache is starting")
eventsCh <- update.NewProgressEvent(80.0)
for line, err := range runAptCleanCommand(ctx) {
if err != nil {
eventsCh <- update.NewErrorEvent(fmt.Errorf("error running apt clean command: %w", err))
return
}

eventsCh <- update.NewDataEvent(update.UpgradeLineEvent, line)
}

eventsCh <- update.NewProgressEvent(85.0)
eventsCh <- update.NewDataEvent(update.UpgradeLineEvent, "Stop and destroy docker containers and images ....")
streamCleanup := cleanupDockerContainers(ctx)
for line, err := range streamCleanup {
Expand All @@ -125,6 +126,7 @@ func (s *Service) UpgradePackages(ctx context.Context, names []string) (<-chan u
eventsCh <- update.NewDataEvent(update.UpgradeLineEvent, line)
}
}
eventsCh <- update.NewProgressEvent(90.0)

// TODO: Remove this workaround once docker image versions are no longer hardcoded in arduino-app-cli.
// Tracking issue: https://github.com/arduino/arduino-app-cli/issues/600
Expand Down
60 changes: 44 additions & 16 deletions internal/update/arduino/arduino.go
View file Open in desktop
Original file line number Diff line number Diff line change
Expand Up @@ -140,21 +140,41 @@ func (a *ArduinoPlatformUpdater) UpgradePackages(ctx context.Context, names []st
}
eventsCh := make(chan update.Event, 100)

downloadProgressCB := func(curr *rpc.DownloadProgress) {
data := helpers.ArduinoCLIDownloadProgressToString(curr)
slog.Debug("Download progress", slog.String("download_progress", data))
eventsCh <- update.NewDataEvent(update.UpgradeLineEvent, data)
}
taskProgressCB := func(msg *rpc.TaskProgress) {
data := helpers.ArduinoCLITaskProgressToString(msg)
slog.Debug("Task progress", slog.String("task_progress", data))
eventsCh <- update.NewDataEvent(update.UpgradeLineEvent, data)
}

go func() {
defer a.lock.Unlock()
defer close(eventsCh)

const indexBase float32 = 0.0
const indexWeight float32 = 30.0
const upgradeBase float32 = 30.0
const upgradeWeight float32 = 60.0

makeDownloadProgressCallback := func(basePercentage, phaseWeight float32) func(*rpc.DownloadProgress) {
return func(curr *rpc.DownloadProgress) {
data := helpers.ArduinoCLIDownloadProgressToString(curr)
eventsCh <- update.NewDataEvent(update.UpgradeLineEvent, data)
if updateInfo := curr.GetUpdate(); updateInfo != nil {
if updateInfo.GetTotalSize() <= 0 {
return
}
localProgress := (float32(updateInfo.GetDownloaded()) / float32(updateInfo.GetTotalSize())) * 100.0
totalArduinoProgress := basePercentage + (localProgress/100.0)*phaseWeight
eventsCh <- update.NewProgressEvent(totalArduinoProgress)
}
}
}
makeTaskProgressCallback := func(basePercentage, phaseWeight float32) func(*rpc.TaskProgress) {
return func(msg *rpc.TaskProgress) {
data := helpers.ArduinoCLITaskProgressToString(msg)
eventsCh <- update.NewDataEvent(update.UpgradeLineEvent, data)
if !msg.GetCompleted() {
localProgress := msg.GetPercent()
totalArduinoProgress := basePercentage + (localProgress/100.0)*phaseWeight
eventsCh <- update.NewProgressEvent(totalArduinoProgress)
}
}
}

eventsCh <- update.NewDataEvent(update.StartEvent, "Upgrade is starting")

logrus.SetLevel(logrus.ErrorLevel) // Reduce the log level of arduino-cli
Expand All @@ -181,21 +201,28 @@ func (a *ArduinoPlatformUpdater) UpgradePackages(ctx context.Context, names []st
}()

{
stream, _ := commands.UpdateIndexStreamResponseToCallbackFunction(ctx, downloadProgressCB)
updateIndexProgressCB := makeDownloadProgressCallback(indexBase, indexWeight)
stream, _ := commands.UpdateIndexStreamResponseToCallbackFunction(ctx, updateIndexProgressCB)
if err := srv.UpdateIndex(&rpc.UpdateIndexRequest{Instance: inst}, stream); err != nil {
eventsCh <- update.NewErrorEvent(fmt.Errorf("error updating index: %w", err))
return
}

eventsCh <- update.NewProgressEvent(indexBase + indexWeight)

if err := srv.Init(&rpc.InitRequest{Instance: inst}, commands.InitStreamResponseToCallbackFunction(ctx, nil)); err != nil {
eventsCh <- update.NewErrorEvent(fmt.Errorf("error initializing instance: %w", err))
return
}
}

platformDownloadCB := makeDownloadProgressCallback(upgradeBase, upgradeWeight)
platformTaskCB := makeTaskProgressCallback(upgradeBase, upgradeWeight)

stream, respCB := commands.PlatformUpgradeStreamResponseToCallbackFunction(
ctx,
downloadProgressCB,
taskProgressCB,
platformDownloadCB,
platformTaskCB,
)
if err := srv.PlatformUpgrade(
&rpc.PlatformUpgradeRequest{
Expand Down Expand Up @@ -227,8 +254,8 @@ func (a *ArduinoPlatformUpdater) UpgradePackages(ctx context.Context, names []st
},
commands.PlatformInstallStreamResponseToCallbackFunction(
ctx,
downloadProgressCB,
taskProgressCB,
platformDownloadCB,
platformTaskCB,
),
)
if err != nil {
Expand Down Expand Up @@ -256,6 +283,7 @@ func (a *ArduinoPlatformUpdater) UpgradePackages(ctx context.Context, names []st
eventsCh <- update.NewErrorEvent(fmt.Errorf("error burning bootloader: %w", err))
return
}
eventsCh <- update.NewProgressEvent(100.0)
}()

return eventsCh, nil
Expand Down
27 changes: 22 additions & 5 deletions internal/update/event.go
View file Open in desktop
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,9 @@

package update

import "go.bug.st/f"
import (
"go.bug.st/f"
)

// EventType defines the type of upgrade event.
type EventType int
Expand All @@ -24,16 +26,17 @@ const (
UpgradeLineEvent EventType = iota
StartEvent
RestartEvent
ProgressEvent
DoneEvent
ErrorEvent
)

// Event represents a single event in the upgrade process.
type Event struct {
Type EventType

data string
err error // error field for error events
Type EventType
progress float32
data string
err error // error field for error events
}

func (t EventType) String() string {
Expand All @@ -44,6 +47,8 @@ func (t EventType) String() string {
return "restarting"
case StartEvent:
return "starting"
case ProgressEvent:
return "progress"
case DoneEvent:
return "done"
case ErrorEvent:
Expand All @@ -60,6 +65,13 @@ func NewDataEvent(t EventType, data string) Event {
}
}

func NewProgressEvent(progress float32) Event {
return Event{
Type: ProgressEvent,
progress: progress,
}
}

func NewErrorEvent(err error) Event {
return Event{
Type: ErrorEvent,
Expand All @@ -77,6 +89,11 @@ func (e Event) GetError() error {
return e.err
}

func (e Event) GetProgress() float32 {
f.Assert(e.Type == ProgressEvent, "not a progress event")
return e.progress
}

type PackageType string

const (
Expand Down
21 changes: 17 additions & 4 deletions internal/update/update.go
View file Open in desktop
Original file line number Diff line number Diff line change
Expand Up @@ -136,24 +136,37 @@ func (m *Manager) UpgradePackages(ctx context.Context, pkgs []UpgradablePackage)
// update of the cores we will end up with inconsistent state, or
// we need to re run the upgrade because the orchestrator interrupted
// in the middle the upgrade of the cores.

const arduinoWeight float32 = 20.0
const aptWeight float32 = 80.0

arduinoEvents, err := m.arduinoPlatformUpdateService.UpgradePackages(ctx, arduinoPlatform)
if err != nil {
m.broadcast(NewErrorEvent(fmt.Errorf("failed to upgrade Arduino packages: %w", err)))
return
}
for e := range arduinoEvents {
m.broadcast(e)
if e.Type == ProgressEvent {
globalProgress := (e.progress / 100.0) * arduinoWeight
m.broadcast(NewProgressEvent(globalProgress))
} else {
m.broadcast(e)
}
}

aptEvents, err := m.debUpdateService.UpgradePackages(ctx, debPkgs)
if err != nil {
m.broadcast(NewErrorEvent(fmt.Errorf("failed to upgrade APT packages: %w", err)))
return
}
for e := range aptEvents {
m.broadcast(e)
if e.Type == ProgressEvent {
globalProgress := arduinoWeight + (e.progress/100.0)*aptWeight
m.broadcast(NewProgressEvent(globalProgress))
} else {
m.broadcast(e)
}
}

m.broadcast(NewProgressEvent(100.0))
m.broadcast(NewDataEvent(DoneEvent, "Update completed"))
}()
return nil
Expand Down

AltStyle によって変換されたページ (->オリジナル) /