File tree Expand file tree Collapse file tree 4 files changed +32
-17
lines changed
pages/project/instances/instance Expand file tree Collapse file tree 4 files changed +32
-17
lines changed Original file line number Diff line number Diff line change @@ -151,6 +151,24 @@ export function instanceTransitioning({ runState }: Instance) {
151151 )
152152}
153153
154+ /**
155+ * True if instance is failed, auto restart enabled, and either we've never
156+ * restarted or we just expired and we're waiting to get restarted.
157+ *
158+ * There can be a short window (up to a minute) after expiration where the
159+ * instance hasn't been picked up for auto-restart yet.
160+ *
161+ * https://github.com/oxidecomputer/omicron/blob/b6ada022a/nexus/src/app/background/init.rs#L726-L745
162+ * https://github.com/oxidecomputer/omicron/blob/b6ada022a/smf/nexus/multi-sled/config-partial.toml#L70-L71
163+ */
164+ export function instanceAutoRestartingSoon ( i : Instance ) {
165+ return (
166+ i . runState === 'failed' &&
167+ i . autoRestartEnabled &&
168+ ( ! i . autoRestartCooldownExpiration || i . autoRestartCooldownExpiration < new Date ( ) )
169+ )
170+ }
171+
154172const diskActions = {
155173 // this is a weird one because the list of states is dynamic and it includes
156174 // 'creating' in the unwind of the disk create saga, but does not include
Original file line number Diff line number Diff line change @@ -18,6 +18,7 @@ import {
1818} from '@oxide/design-system/icons/react'
1919
2020import type { Instance } from '~/api'
21+ import { instanceAutoRestartingSoon } from '~/api/util'
2122import { useInstanceSelector } from '~/hooks/use-params'
2223import { Badge } from '~/ui/lib/Badge'
2324import { Spinner } from '~/ui/lib/Spinner'
@@ -28,6 +29,7 @@ import { pb } from '~/util/path-builder'
2829 * Appears if and only if the instance is failed.
2930 */
3031export const InstanceAutoRestartPopover = ( { instance } : { instance : Instance } ) => {
32+ const instanceSelector = useInstanceSelector ( )
3133 if ( instance . runState !== 'failed' ) return null // important!
3234
3335 const {
@@ -36,12 +38,7 @@ export const InstanceAutoRestartPopover = ({ instance }: { instance: Instance })
3638 autoRestartEnabled : enabled ,
3739 } = instance
3840
39- const instanceSelector = useInstanceSelector ( )
40-
41- // true if either we've never restarted or we just expired and we're waiting
42- // to get restarted (should always be under a minute because that's how often
43- // the cleanup job runs)
44- const restartingSoon = enabled && ( ! cooldownExpiration || cooldownExpiration < new Date ( ) )
41+ const restartingSoon = instanceAutoRestartingSoon ( instance )
4542
4643 return (
4744 < Popover >
Original file line number Diff line number Diff line change @@ -23,6 +23,7 @@ import { Instances24Icon } from '@oxide/design-system/icons/react'
2323import {
2424 INSTANCE_MAX_CPU ,
2525 INSTANCE_MAX_RAM_GiB ,
26+ instanceAutoRestartingSoon ,
2627 instanceCan ,
2728 instanceTransitioning ,
2829} from '~/api/util'
@@ -152,15 +153,9 @@ export function InstancePage() {
152153 if ( instanceTransitioning ( instance ) ) return POLL_INTERVAL_FAST
153154
154155 if ( instance . runState === 'failed' && instance . autoRestartEnabled ) {
155- // There can be a short window (up to a minute, based on the links
156- // below) after expiration where the instance hasn't been picked up
157- // for auto-restart yet, during which time we still want to poll.
158- // https://github.com/oxidecomputer/omicron/blob/b6ada022a/nexus/src/app/background/init.rs#L726-L745
159- // https://github.com/oxidecomputer/omicron/blob/b6ada022a/smf/nexus/multi-sled/config-partial.toml#L70-L71
160- const restartingSoon =
161- ! instance . autoRestartCooldownExpiration ||
162- instance . autoRestartCooldownExpiration < new Date ( )
163- return restartingSoon ? POLL_INTERVAL_FAST : POLL_INTERVAL_SLOW
156+ return instanceAutoRestartingSoon ( instance )
157+ ? POLL_INTERVAL_FAST
158+ : POLL_INTERVAL_SLOW
164159 }
165160 } ,
166161 }
Original file line number Diff line number Diff line change @@ -11,7 +11,12 @@ import { type ReactNode } from 'react'
1111import { useForm } from 'react-hook-form'
1212import { match } from 'ts-pattern'
1313
14- import { apiQueryClient , useApiMutation , usePrefetchedApiQuery } from '~/api'
14+ import {
15+ apiQueryClient ,
16+ instanceAutoRestartingSoon ,
17+ useApiMutation ,
18+ usePrefetchedApiQuery ,
19+ } from '~/api'
1520import { ListboxField } from '~/components/form/fields/ListboxField'
1621import { useInstanceSelector } from '~/hooks/use-params'
1722import { addToast } from '~/stores/toast'
@@ -111,7 +116,7 @@ export function Component() {
111116 { instance . runState === 'failed' && instance . autoRestartEnabled && (
112117 < span className = "text-tertiary" >
113118 (
114- { instance . autoRestartCooldownExpiration < new Date ( )
119+ { instanceAutoRestartingSoon ( instance )
115120 ? 'restarting soon'
116121 : formatDistanceToNow ( instance . autoRestartCooldownExpiration ) }
117122 )
You can’t perform that action at this time.
0 commit comments