This commit is contained in:
@@ -52,28 +52,13 @@ func newOperationCoordinator() operationCoordinator {
|
||||
}
|
||||
}
|
||||
|
||||
// waitForOperation races the stream against the real Bubbles tick command.
|
||||
// Only the stream is read directly, so a losing tick cannot consume an update.
|
||||
func waitForOperation(updates <-chan app.OperationUpdate, tick tea.Cmd) tea.Cmd {
|
||||
func waitForOperation(updates <-chan app.OperationUpdate) tea.Cmd {
|
||||
return func() tea.Msg {
|
||||
if tick == nil {
|
||||
update, ok := <-updates
|
||||
if !ok {
|
||||
return operationProgress{updates: updates, closed: true}
|
||||
}
|
||||
return operationProgress{update: update, updates: updates}
|
||||
}
|
||||
ticks := make(chan tea.Msg, 1)
|
||||
go func() { ticks <- tick() }()
|
||||
select {
|
||||
case update, ok := <-updates:
|
||||
if !ok {
|
||||
return operationProgress{updates: updates, closed: true}
|
||||
}
|
||||
return operationProgress{update: update, updates: updates}
|
||||
case message := <-ticks:
|
||||
return message
|
||||
update, ok := <-updates
|
||||
if !ok {
|
||||
return operationProgress{updates: updates, closed: true}
|
||||
}
|
||||
return operationProgress{update: update, updates: updates}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -81,7 +66,14 @@ func (o operationCoordinator) wait() tea.Cmd {
|
||||
if !o.active || o.updates == nil {
|
||||
return nil
|
||||
}
|
||||
return waitForOperation(o.updates, o.spinner.Tick)
|
||||
return waitForOperation(o.updates)
|
||||
}
|
||||
|
||||
func (o operationCoordinator) commands() tea.Cmd {
|
||||
if !o.active {
|
||||
return nil
|
||||
}
|
||||
return tea.Batch(o.wait(), o.spinner.Tick)
|
||||
}
|
||||
|
||||
func (o *operationCoordinator) start(application app.InteractiveModule, intent app.Intent) (app.Snapshot, tea.Cmd, bool) {
|
||||
@@ -99,7 +91,7 @@ func (o *operationCoordinator) start(application app.InteractiveModule, intent a
|
||||
o.progress[intent.TargetID] = app.TargetProgressRunning
|
||||
}
|
||||
o.status = app.OperationStatus{Kind: app.StatusProgress, Summary: operationStartingSummary(intent.Kind)}
|
||||
return stream.Snapshot, o.wait(), true
|
||||
return stream.Snapshot, o.commands(), true
|
||||
}
|
||||
|
||||
func operationStartingSummary(kind app.IntentKind) string {
|
||||
@@ -119,7 +111,7 @@ func (o *operationCoordinator) tick(message spinner.TickMsg) tea.Cmd {
|
||||
}
|
||||
updated, nextTick := o.spinner.Update(message)
|
||||
o.spinner = updated
|
||||
return waitForOperation(o.updates, nextTick)
|
||||
return nextTick
|
||||
}
|
||||
|
||||
func (o *operationCoordinator) apply(update app.OperationUpdate) (firstFailedTargetID string) {
|
||||
@@ -134,9 +126,7 @@ func (o *operationCoordinator) apply(update app.OperationUpdate) (firstFailedTar
|
||||
case app.OperationSucceeded:
|
||||
o.resolveError(o.intent)
|
||||
case app.OperationFailed:
|
||||
o.currentError = &operationError{status: decoded.Status, detail: errorDetail(decoded.Err), intent: o.intent}
|
||||
o.errorExpanded = false
|
||||
o.errorOffset = 0
|
||||
o.recordError(&operationError{status: decoded.Status, detail: errorDetail(decoded.Err), intent: o.intent})
|
||||
firstFailedTargetID = decoded.FirstFailedTargetID
|
||||
case app.OperationConfirmation:
|
||||
intent := o.intent
|
||||
@@ -157,6 +147,15 @@ func errorDetail(err error) string {
|
||||
return err.Error()
|
||||
}
|
||||
|
||||
func (o *operationCoordinator) recordError(candidate *operationError) {
|
||||
if o.currentError != nil && !relatedResolution(o.currentError.intent, candidate.intent) {
|
||||
return
|
||||
}
|
||||
o.currentError = candidate
|
||||
o.errorExpanded = false
|
||||
o.errorOffset = 0
|
||||
}
|
||||
|
||||
func (o *operationCoordinator) resolveError(success app.Intent) {
|
||||
if o.currentError == nil || !relatedResolution(o.currentError.intent, success) {
|
||||
return
|
||||
@@ -196,13 +195,11 @@ func (o *operationCoordinator) finish() {
|
||||
|
||||
func (o *operationCoordinator) unexpectedClose() {
|
||||
o.status = app.OperationStatus{Kind: app.StatusError, Summary: "Operation ended without a final result"}
|
||||
o.currentError = &operationError{
|
||||
o.recordError(&operationError{
|
||||
status: o.status,
|
||||
detail: "The Application operation stream closed before publishing a terminal result.",
|
||||
intent: o.intent,
|
||||
}
|
||||
o.errorExpanded = false
|
||||
o.errorOffset = 0
|
||||
})
|
||||
o.finish()
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user