Skip to content

Commit

Permalink
refactor(app): Use run loaded labware defs in Error Recovery (#17074)
Browse files Browse the repository at this point in the history
Closes EXEC-761 and EXEC-1050

This PR wires up the GET /run/:runId/loaded_labware_definitions to Error Recovery, cutting down on command scanning just a little bit further. Some additional error handling is added to the existing getLabwareDefURI.
  • Loading branch information
mjhuff authored Dec 10, 2024
1 parent 2694b4a commit 5f1b637
Show file tree
Hide file tree
Showing 5 changed files with 80 additions and 25 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ import {
RUN_STATUS_RUNNING,
RUN_STATUS_STOP_REQUESTED,
} from '@opentrons/api-client'
import { getLoadedLabwareDefinitionsByUri } from '@opentrons/shared-data'

import { renderWithProviders } from '/app/__testing-utils__'
import { i18n } from '/app/i18n'
Expand All @@ -23,6 +22,7 @@ import { useRecoveryAnalytics } from '/app/redux-resources/analytics'
import { getIsOnDevice } from '/app/redux/config'
import { useERWizard, ErrorRecoveryWizard } from '../ErrorRecoveryWizard'
import { useRecoverySplash, RecoverySplash } from '../RecoverySplash'
import { useRunLoadedLabwareDefinitionsByUri } from '/app/resources/runs'

import type { RunStatus } from '@opentrons/api-client'

Expand All @@ -33,13 +33,7 @@ vi.mock('/app/redux/config')
vi.mock('../RecoverySplash')
vi.mock('/app/redux-resources/analytics')
vi.mock('@opentrons/react-api-client')
vi.mock('@opentrons/shared-data', async () => {
const actual = await vi.importActual('@opentrons/shared-data')
return {
...actual,
getLoadedLabwareDefinitionsByUri: vi.fn(),
}
})
vi.mock('/app/resources/runs')
vi.mock('react-redux', async () => {
const actual = await vi.importActual('react-redux')
return {
Expand Down Expand Up @@ -173,7 +167,7 @@ describe('ErrorRecoveryFlows', () => {
intent: 'recovering',
showTakeover: false,
})
vi.mocked(getLoadedLabwareDefinitionsByUri).mockReturnValue({})
vi.mocked(useRunLoadedLabwareDefinitionsByUri).mockReturnValue({})
})

it('renders the wizard when showERWizard is true', () => {
Expand Down
21 changes: 5 additions & 16 deletions app/src/organisms/ErrorRecoveryFlows/index.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { useMemo, useLayoutEffect, useState } from 'react'
import { useLayoutEffect, useState } from 'react'
import { useSelector } from 'react-redux'

import {
Expand All @@ -15,10 +15,7 @@ import {
RUN_STATUS_STOPPED,
RUN_STATUS_SUCCEEDED,
} from '@opentrons/api-client'
import {
getLoadedLabwareDefinitionsByUri,
OT2_ROBOT_TYPE,
} from '@opentrons/shared-data'
import { OT2_ROBOT_TYPE } from '@opentrons/shared-data'
import { useHost } from '@opentrons/react-api-client'

import { getIsOnDevice } from '/app/redux/config'
Expand All @@ -35,6 +32,7 @@ import {
import type { RunStatus } from '@opentrons/api-client'
import type { CompletedProtocolAnalysis } from '@opentrons/shared-data'
import type { FailedCommand } from './types'
import { useRunLoadedLabwareDefinitionsByUri } from '/app/resources/runs'

const VALID_ER_RUN_STATUSES: RunStatus[] = [
RUN_STATUS_AWAITING_RECOVERY,
Expand Down Expand Up @@ -118,7 +116,7 @@ export interface ErrorRecoveryFlowsProps {
export function ErrorRecoveryFlows(
props: ErrorRecoveryFlowsProps
): JSX.Element | null {
const { protocolAnalysis, runStatus, unvalidatedFailedCommand } = props
const { protocolAnalysis, runStatus, unvalidatedFailedCommand, runId } = props

const failedCommandBySource = useRetainedFailedCommandBySource(
unvalidatedFailedCommand,
Expand All @@ -130,16 +128,7 @@ export function ErrorRecoveryFlows(
const robotType = protocolAnalysis?.robotType ?? OT2_ROBOT_TYPE
const robotName = useHost()?.robotName ?? 'robot'

const isValidRobotSideAnalysis = protocolAnalysis != null

// TODO(jh, 10-22-24): EXEC-769.
const labwareDefinitionsByUri = useMemo(
() =>
protocolAnalysis != null
? getLoadedLabwareDefinitionsByUri(protocolAnalysis?.commands)
: null,
[isValidRobotSideAnalysis]
)
const labwareDefinitionsByUri = useRunLoadedLabwareDefinitionsByUri(runId)
const allRunDefs =
labwareDefinitionsByUri != null
? Object.values(labwareDefinitionsByUri)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import { describe, expect, it, beforeEach, vi } from 'vitest'
import { renderHook } from '@testing-library/react'

import { useRunLoadedLabwareDefinitions } from '@opentrons/react-api-client'
import { fixture96Plate } from '@opentrons/shared-data'

import { useRunLoadedLabwareDefinitionsByUri } from '/app/resources/runs'

import type { LabwareDefinition2 } from '@opentrons/shared-data'

vi.mock('@opentrons/react-api-client')

const mockLabwareDef = fixture96Plate as LabwareDefinition2

describe('useRunLoadedLabwareDefinitionsByUri', () => {
beforeEach(() => {
vi.mocked(useRunLoadedLabwareDefinitions).mockReturnValue({
data: { data: [mockLabwareDef] },
} as any)
})

it('returns a record of labware definitions keyed by URI', () => {
const { result } = renderHook(() =>
useRunLoadedLabwareDefinitionsByUri('mockId')
)

expect(result.current).toEqual({
'fixture/fixture_96_plate/1': mockLabwareDef,
})
})
})
1 change: 1 addition & 0 deletions app/src/resources/runs/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,3 +30,4 @@ export * from './useProtocolAnalysisErrors'
export * from './useLastRunCommand'
export * from './useRunStatuses'
export * from './useUpdateRecoveryPolicyWithStrategy'
export * from './useRunLoadedLabwareDefinitionsByUri'
40 changes: 40 additions & 0 deletions app/src/resources/runs/useRunLoadedLabwareDefinitionsByUri.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import { useMemo } from 'react'

import { useRunLoadedLabwareDefinitions } from '@opentrons/react-api-client'
import { getLabwareDefURI } from '@opentrons/shared-data'

import type { UseQueryOptions } from 'react-query'
import type { AxiosError } from 'axios'
import type {
HostConfig,
RunLoadedLabwareDefinitions,
} from '@opentrons/api-client'
import type { LabwareDefinition2 } from '@opentrons/shared-data'

export type RunLoadedLabwareDefinitionsByUri = Record<
string,
LabwareDefinition2
>

// Returns a record of labware definitions keyed by URI for the labware that
// has been loaded with a "loadLabware" command. Errors if the run is not the current run.
export function useRunLoadedLabwareDefinitionsByUri(
runId: string | null,
options: UseQueryOptions<RunLoadedLabwareDefinitions, AxiosError> = {},
hostOverride?: HostConfig
): RunLoadedLabwareDefinitionsByUri {
const { data } = useRunLoadedLabwareDefinitions(runId, options, hostOverride)

return useMemo(() => {
const result: Record<string, LabwareDefinition2> = {}
// @ts-expect-error TODO(jh, 10-12-24): Update the app's typing to support LabwareDefinition3.
data?.data.forEach((def: LabwareDefinition2) => {
if ('schemaVersion' in def) {
const lwUri = getLabwareDefURI(def)
result[lwUri] = def
}
})

return result
}, [data])
}

0 comments on commit 5f1b637

Please sign in to comment.