getNextTransition returns the next eligible transition for the workspace as well as the reason for why it is transitioning. It is possible for this function to return a nil error as well as an empty transition. In such cases it means no provisioning should occur but the workspace may be "transitioni
( user database.User, ws database.Workspace, latestBuild database.WorkspaceBuild, latestJob database.ProvisionerJob, templateSchedule schedule.TemplateScheduleOptions, currentTick time.Time, )
| 539 | // may be "transitioning" to a new state (such as an inactive, stopped |
| 540 | // workspace transitioning to the dormant state). |
| 541 | func getNextTransition( |
| 542 | user database.User, |
| 543 | ws database.Workspace, |
| 544 | latestBuild database.WorkspaceBuild, |
| 545 | latestJob database.ProvisionerJob, |
| 546 | templateSchedule schedule.TemplateScheduleOptions, |
| 547 | currentTick time.Time, |
| 548 | ) ( |
| 549 | database.WorkspaceTransition, |
| 550 | database.BuildReason, |
| 551 | error, |
| 552 | ) { |
| 553 | switch { |
| 554 | case isEligibleForAutostop(user, ws, latestBuild, latestJob, currentTick): |
| 555 | // Use task-specific reason for AI task workspaces. |
| 556 | if ws.TaskID.Valid { |
| 557 | return database.WorkspaceTransitionStop, database.BuildReasonTaskAutoPause, nil |
| 558 | } |
| 559 | return database.WorkspaceTransitionStop, database.BuildReasonAutostop, nil |
| 560 | case isEligibleForAutostart(user, ws, latestBuild, latestJob, templateSchedule, currentTick): |
| 561 | return database.WorkspaceTransitionStart, database.BuildReasonAutostart, nil |
| 562 | case isEligibleForFailedCleanup(latestBuild, latestJob, templateSchedule, currentTick): |
| 563 | // Use task-specific reason for AI task workspaces. |
| 564 | if ws.TaskID.Valid { |
| 565 | return database.WorkspaceTransitionStop, database.BuildReasonTaskAutoPause, nil |
| 566 | } |
| 567 | return database.WorkspaceTransitionStop, database.BuildReasonAutostop, nil |
| 568 | case isEligibleForDormantStop(ws, templateSchedule, currentTick): |
| 569 | // Only stop started workspaces. |
| 570 | if latestBuild.Transition == database.WorkspaceTransitionStart { |
| 571 | return database.WorkspaceTransitionStop, database.BuildReasonDormancy, nil |
| 572 | } |
| 573 | // We shouldn't transition the workspace but we should still |
| 574 | // make it dormant. |
| 575 | return "", database.BuildReasonDormancy, nil |
| 576 | |
| 577 | case isEligibleForDelete(ws, templateSchedule, latestBuild, latestJob, currentTick): |
| 578 | return database.WorkspaceTransitionDelete, database.BuildReasonAutodelete, nil |
| 579 | default: |
| 580 | return "", "", xerrors.Errorf("last transition not valid for autostart or autostop") |
| 581 | } |
| 582 | } |
| 583 | |
| 584 | // isEligibleForAutostart returns true if the workspace should be autostarted. |
| 585 | func isEligibleForAutostart(user database.User, ws database.Workspace, build database.WorkspaceBuild, job database.ProvisionerJob, templateSchedule schedule.TemplateScheduleOptions, currentTick time.Time) bool { |