Skip to content

Commit ac3d224

Browse files
authored
fix(app): During stacker error recovery use Protocol Engine labware quantity (#18667)
Covers RQA-4290 Switches to using the Protocol Engine stacker labware count instead of iterating over the stacker retrieve and store commands
1 parent 0fa8547 commit ac3d224

File tree

3 files changed

+127
-251
lines changed

3 files changed

+127
-251
lines changed

app/src/organisms/ErrorRecoveryFlows/hooks/__tests__/useFailedLabwareUtils.test.tsx

Lines changed: 100 additions & 185 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ import {
1313
useRelevantFailedLwLocations,
1414
} from '../useFailedLabwareUtils'
1515

16-
import type { RunCommandSummary } from '@opentrons/api-client'
16+
import type { RunCurrentState } from '@opentrons/api-client'
1717

1818
vi.mock('@opentrons/shared-data', async () => {
1919
const actual = await vi.importActual('@opentrons/shared-data')
@@ -279,61 +279,6 @@ describe('getFailedLabwareQuantity', () => {
279279
},
280280
} as any
281281

282-
const failedRetriveCommand = {
283-
...failedCommand,
284-
commandType: 'flexStacker/retrieve',
285-
error: {
286-
isDefined: true,
287-
errorType: DEFINED_ERROR_TYPES.STACKER_STALL,
288-
},
289-
}
290-
291-
const runCommands = {
292-
data: [
293-
{
294-
id: 'set-stored-labware-1',
295-
commandType: 'flexStacker/setStoredLabware',
296-
params: {
297-
initialCount: 2,
298-
},
299-
} as any,
300-
{
301-
id: 'retrive-id-1',
302-
commandType: 'flexStacker/retrieve',
303-
params: {
304-
moduleId: 'module-id',
305-
},
306-
} as any,
307-
{
308-
id: 'retrive-id-2',
309-
commandType: 'flexStacker/retrieve',
310-
params: {
311-
moduleId: 'module-id',
312-
},
313-
} as any,
314-
{
315-
id: 'set-stored-labware',
316-
commandType: 'flexStacker/setStoredLabware',
317-
params: {
318-
initialCount: 5,
319-
},
320-
} as any,
321-
{
322-
id: 'retrive-id',
323-
commandType: 'flexStacker/retrieve',
324-
params: {
325-
moduleId: 'module-id',
326-
},
327-
} as any,
328-
{ ...failedRetriveCommand },
329-
] as RunCommandSummary[],
330-
meta: {
331-
totalLength: 10,
332-
pageLength: 1,
333-
},
334-
links: {},
335-
}
336-
337282
it('should return the quantity for stacker error kinds', () => {
338283
const errors = [
339284
ERROR_KINDS.STACKER_SHUTTLE_MISSING,
@@ -342,62 +287,44 @@ describe('getFailedLabwareQuantity', () => {
342287
]
343288
errors.forEach(errorType => {
344289
const failedLocalRetriveCommand = {
345-
...failedCommand,
346-
commandType: 'flexStacker/retrieve',
347-
error: {
348-
isDefined: true,
349-
errorType,
290+
byRunRecord: {
291+
...failedCommand,
292+
error: { errorType: 'SOME_UNHANDLED_ERROR' },
293+
},
294+
byAnalysis: {
295+
...failedCommand,
296+
error: { errorType: 'SOME_UNHANDLED_ERROR' },
350297
},
351298
}
352-
const localRunCommands = {
353-
data: [
354-
{
355-
id: 'set-stored-labware-1',
356-
commandType: 'flexStacker/setStoredLabware',
357-
params: {
358-
initialCount: 2,
359-
},
360-
} as any,
361-
{
362-
id: 'retrive-id-1',
363-
commandType: 'flexStacker/retrieve',
364-
params: {
365-
moduleId: 'module-id',
366-
},
367-
} as any,
368-
{
369-
id: 'retrive-id-2',
370-
commandType: 'flexStacker/retrieve',
371-
params: {
372-
moduleId: 'module-id',
373-
},
374-
} as any,
375-
{
376-
id: 'set-stored-labware',
377-
commandType: 'flexStacker/setStoredLabware',
378-
params: {
379-
initialCount: 5,
299+
300+
const currentRunState = {
301+
data: {
302+
estopEngaged: false,
303+
activeNozzleLayouts: {
304+
abc: {
305+
startingNozzle: 'A1',
306+
activeNozzles: ['A1'],
307+
config: 'single',
380308
},
381-
} as any,
382-
{
383-
id: 'retrive-id',
384-
commandType: 'flexStacker/retrieve',
385-
params: {
386-
moduleId: 'module-id',
309+
},
310+
tipStates: { abc: { hasTip: false } },
311+
placeLabwareState: undefined,
312+
flexStackerStates: {
313+
'module-id': {
314+
primaryLabwareURI: 'huh',
315+
adapterLabwareURI: 'whu',
316+
lidLabwareURI: 'buh',
317+
count: 4,
318+
maxCount: 5,
387319
},
388-
} as any,
389-
{ ...failedLocalRetriveCommand },
390-
] as RunCommandSummary[],
391-
meta: {
392-
totalLength: 10,
393-
pageLength: 1,
320+
},
394321
},
395-
links: {},
322+
links: { lastCompleted: { id: 'test', href: 'test2' } },
396323
}
324+
397325
const result = getFailedLabwareQuantity(
398-
localRunCommands,
399326
failedLocalRetriveCommand,
400-
errorType
327+
currentRunState as RunCurrentState
401328
)
402329
expect(result).toEqual(4)
403330
})
@@ -409,112 +336,100 @@ describe('getFailedLabwareQuantity', () => {
409336
ERROR_KINDS.STACKER_HOPPER_EMPTY,
410337
ERROR_KINDS.STACKER_STALLED,
411338
]
412-
errors.forEach(errorType => {
339+
errors.forEach(errorKind => {
413340
const failedLocalRetriveCommand = {
414-
...failedCommand,
415-
commandType: 'flexStacker/retrieve',
416-
error: {
417-
isDefined: true,
418-
errorType,
341+
byRunRecord: {
342+
...failedCommand,
343+
error: { errorType: errorKind },
344+
},
345+
byAnalysis: {
346+
...failedCommand,
347+
error: { errorType: errorKind },
419348
},
420349
}
421-
const localRunCommands = {
422-
data: [
423-
{
424-
id: 'set-stored-labware-1',
425-
commandType: 'flexStacker/setStoredLabware',
426-
params: {
427-
initialCount: 2,
428-
},
429-
} as any,
430-
{
431-
id: 'retrive-id-1',
432-
commandType: 'flexStacker/retrieve',
433-
params: {
434-
moduleId: 'module-id',
435-
},
436-
} as any,
437-
{
438-
id: 'retrive-id-2',
439-
commandType: 'flexStacker/retrieve',
440-
params: {
441-
moduleId: 'module-id',
442-
},
443-
} as any,
444-
{
445-
id: 'set-stored-labware',
446-
commandType: 'flexStacker/setStoredLabware',
447-
params: {
448-
initialCount: 5,
449-
},
450-
} as any,
451-
{
452-
id: 'retrive-id',
453-
commandType: 'flexStacker/retrieve',
454-
params: {
455-
moduleId: 'module-id',
350+
351+
const currentRunState = {
352+
data: {
353+
estopEngaged: false,
354+
activeNozzleLayouts: {
355+
abc: {
356+
startingNozzle: 'A1',
357+
activeNozzles: ['A1'],
358+
config: 'single',
456359
},
457-
result: {
458-
primaryLocationSequence: [1, 2, 3, 4],
360+
},
361+
tipStates: { abc: { hasTip: false } },
362+
placeLabwareState: undefined,
363+
flexStackerStates: {
364+
'module-id': {
365+
primaryLabwareURI: 'huh',
366+
adapterLabwareURI: 'whu',
367+
lidLabwareURI: 'buh',
368+
count: 4,
369+
maxCount: 5,
459370
},
460-
} as any,
461-
{ ...failedLocalRetriveCommand },
462-
] as RunCommandSummary[],
463-
meta: {
464-
totalLength: 10,
465-
pageLength: 1,
371+
},
466372
},
467-
links: {},
373+
links: { lastCompleted: { id: 'test', href: 'test2' } },
468374
}
469375
const result = getFailedLabwareQuantity(
470-
localRunCommands,
471376
failedLocalRetriveCommand,
472-
errorType
377+
currentRunState as RunCurrentState
473378
)
474379
expect(result).toEqual(4)
475380
})
476381
})
477382

478383
it('should return 0 if there is no commands in list', () => {
479-
const emptyRunCommands = {
480-
data: [{ ...failedRetriveCommand }] as RunCommandSummary[],
481-
meta: {
482-
totalLength: 10,
483-
pageLength: 1,
384+
const failedLocalRetriveCommand = {
385+
byRunRecord: {
386+
...failedCommand,
387+
error: { errorType: ERROR_KINDS.STACKER_STALLED },
388+
},
389+
byAnalysis: {
390+
...failedCommand,
391+
error: { errorType: ERROR_KINDS.STACKER_STALLED },
484392
},
485-
links: {},
393+
}
394+
395+
const currentRunState = {
396+
data: {
397+
estopEngaged: false,
398+
activeNozzleLayouts: {
399+
abc: {
400+
startingNozzle: 'A1',
401+
activeNozzles: ['A1'],
402+
config: 'single',
403+
},
404+
},
405+
tipStates: { abc: { hasTip: false } },
406+
placeLabwareState: undefined,
407+
flexStackerStates: {
408+
'module-id': {
409+
primaryLabwareURI: 'huh',
410+
adapterLabwareURI: 'whu',
411+
lidLabwareURI: 'buh',
412+
count: 0,
413+
maxCount: 5,
414+
},
415+
},
416+
},
417+
links: { lastCompleted: { id: 'test', href: 'test2' } },
486418
}
487419
const result = getFailedLabwareQuantity(
488-
emptyRunCommands,
489-
failedRetriveCommand,
490-
ERROR_KINDS.STACKER_STALLED
420+
failedLocalRetriveCommand,
421+
currentRunState as RunCurrentState
491422
)
492423
expect(result).toEqual(0)
493424
})
494425

495426
it('should return null if there is no runCommands', () => {
496-
const result = getFailedLabwareQuantity(
497-
undefined,
498-
failedRetriveCommand,
499-
ERROR_KINDS.STACKER_STALLED
500-
)
501-
expect(result).toBeNull()
502-
})
503-
504-
it('should return null for unhandled error kinds', () => {
505-
const failedMoveLabwareCommand = {
506-
...failedCommand,
507-
commandType: 'flexStacker/moveLabware',
508-
error: {
509-
isDefined: true,
510-
errorType: DEFINED_ERROR_TYPES.GRIPPER_MOVEMENT,
511-
},
512-
}
427+
const failedLocalRetriveCommand = null
513428

429+
const currentRunState = undefined
514430
const result = getFailedLabwareQuantity(
515-
runCommands,
516-
failedMoveLabwareCommand,
517-
ERROR_KINDS.GRIPPER_ERROR
431+
failedLocalRetriveCommand,
432+
currentRunState
518433
)
519434
expect(result).toBeNull()
520435
})

app/src/organisms/ErrorRecoveryFlows/hooks/useERUtils.ts

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
import { useMemo } from 'react'
22

3-
import { useInstrumentsQuery } from '@opentrons/react-api-client'
3+
import {
4+
useInstrumentsQuery,
5+
useRunCurrentState,
6+
} from '@opentrons/react-api-client'
47

58
import { useRecoveryAnalytics } from '/app/redux-resources/analytics'
69
import { getRunningStepCountsFrom } from '/app/resources/protocols'
@@ -90,6 +93,7 @@ export function useERUtils({
9093
}: ERUtilsProps): ERUtilsResults {
9194
const { data: attachedInstruments } = useInstrumentsQuery()
9295
const { data: runRecord } = useNotifyRunQuery(runId)
96+
const { data: runCurrentState } = useRunCurrentState(runId)
9397
// TODO(jh, 06-04-24): Refactor the utilities that derive info
9498
// from runCommands once the server yields that info directly on an existing/new endpoint. We'll still need this with a
9599
// pageLength of 1 though for stepCount things.
@@ -162,6 +166,7 @@ export function useERUtils({
162166
failedPipetteInfo,
163167
runRecord,
164168
runCommands,
169+
runCurrentState,
165170
})
166171

167172
const recoveryCommands = useRecoveryCommands({

0 commit comments

Comments
 (0)