Skip to content

Commit

Permalink
fix(app, app-shell): Support protocol backwards app compatibility (#1…
Browse files Browse the repository at this point in the history
…3518)

Closes RQA-1509

* fix(app-shell): add protocol migration for v7.0.0

Downgrading the app from v7.0.0 to v6.3.1 or earlier causes whitescreening when protcols that use
new modules are present. This migration is a temporary shim to enable backwards compability until
OT-2 and Flex app parity is achieved.

Co-authored-by: Seth Foster <[email protected]>
Co-authored-by: Jethary Rader <[email protected]>

* feat(app): add unknown instrument/module error boundary

Render an error message instead of crashing if a user views a protocol with an instrument or module
that does not yet exist. This behavior is most likely triggered when a user downgrades their app.

Co-authored-by: Seth Foster <[email protected]>
Co-authored-by: Jethary Rader <[email protected]>
  • Loading branch information
3 people authored Sep 12, 2023
1 parent 8abc1ba commit 1dccc06
Show file tree
Hide file tree
Showing 3 changed files with 81 additions and 10 deletions.
9 changes: 7 additions & 2 deletions app-shell/src/protocol-storage/file-system.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,13 @@ import { analyzeProtocolSource } from '../protocol-analysis'
* │ ├─ analysis/
* │ │ ├─ 1646303906.json
*/

export const PROTOCOLS_DIRECTORY_NAME = 'protocols'
// TODO(jh, 2023-09-11): remove OLD_PROTOCOLS_DIRECTORY_PATH after
// OT-2 parity work is completed and move all protocols back to "protocols" directory.
export const OLD_PROTOCOLS_DIRECTORY_PATH = path.join(
app.getPath('userData'),
'protocols'
)
export const PROTOCOLS_DIRECTORY_NAME = 'protocols_v7.0-supported'
export const PROTOCOLS_DIRECTORY_PATH = path.join(
app.getPath('userData'),
PROTOCOLS_DIRECTORY_NAME
Expand Down
54 changes: 54 additions & 0 deletions app-shell/src/protocol-storage/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,11 +42,65 @@ export const getProtocolSrcFilePaths = (
})
}

// TODO(jh, 2023-09-11): remove migrateProtocolsToNewDirectory after
// OT-2 parity work is completed.
const migrateProtocols = migrateProtocolsToNewDirectory()
function migrateProtocolsToNewDirectory(): () => Promise<void> {
let hasCheckedForMigration = false
return function (): Promise<void> {
return new Promise((resolve, reject) => {
if (hasCheckedForMigration) resolve()
hasCheckedForMigration = true
console.log(
`Performing protocol migration to ${FileSystem.PROTOCOLS_DIRECTORY_NAME}...`
)
copyProtocols(
FileSystem.OLD_PROTOCOLS_DIRECTORY_PATH,
FileSystem.PROTOCOLS_DIRECTORY_PATH
)
.then(() => {
console.log('Protocol migration complete.')
resolve()
})
.catch(e => {
console.log(
`Error migrating protocols to ${FileSystem.PROTOCOLS_DIRECTORY_NAME}: ${e}`
)
resolve()
})
})
}

function copyProtocols(src: string, dest: string): Promise<void> {
return fse
.stat(src)
.then(doesSrcExist => {
if (!doesSrcExist.isDirectory()) return Promise.resolve()

return fse.readdir(src).then(items => {
const protocols = items.map(item => {
const srcItem = path.join(src, item)
const destItem = path.join(dest, item)

return fse.copy(srcItem, destItem, {
overwrite: false,
})
})
return Promise.all(protocols).then(() => Promise.resolve())
})
})
.catch(e => {
return Promise.reject(e)
})
}
}

export const fetchProtocols = (
dispatch: Dispatch,
source: ListSource
): Promise<void> => {
return ensureDir(FileSystem.PROTOCOLS_DIRECTORY_PATH)
.then(() => migrateProtocols())
.then(() =>
FileSystem.readDirectoriesWithinDirectory(
FileSystem.PROTOCOLS_DIRECTORY_PATH
Expand Down
28 changes: 20 additions & 8 deletions app/src/organisms/ProtocolsLanding/ProtocolCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { format } from 'date-fns'
import { useTranslation } from 'react-i18next'
import { useSelector } from 'react-redux'
import { useHistory } from 'react-router-dom'
import { ErrorBoundary } from 'react-error-boundary'

import {
getModuleType,
Expand Down Expand Up @@ -55,7 +56,6 @@ interface ProtocolCardProps {
handleSendProtocolToOT3: (storedProtocolData: StoredProtocolData) => void
storedProtocolData: StoredProtocolData
}

export function ProtocolCard(props: ProtocolCardProps): JSX.Element | null {
const history = useHistory()
const {
Expand All @@ -78,6 +78,16 @@ export function ProtocolCard(props: ProtocolCardProps): JSX.Element | null {
mostRecentAnalysis
)

const UNKNOWN_ATTACHMENT_ERROR = `${protocolDisplayName} protocol uses
instruments or modules from a future version of the app. Please update
the app to the most recent version to run this protocol.`

const UnknownAttachmentError = (
<StyledText color={COLORS.errorEnabled}>
{UNKNOWN_ATTACHMENT_ERROR}
</StyledText>
)

return (
<Box
backgroundColor={COLORS.white}
Expand All @@ -89,13 +99,15 @@ export function ProtocolCard(props: ProtocolCardProps): JSX.Element | null {
onClick={() => history.push(`/protocols/${protocolKey}`)}
css={BORDERS.cardOutlineBorder}
>
<AnalysisInfo
protocolKey={protocolKey}
mostRecentAnalysis={mostRecentAnalysis}
protocolDisplayName={protocolDisplayName}
isAnalyzing={isAnalyzing}
modified={modified}
/>
<ErrorBoundary fallback={UnknownAttachmentError}>
<AnalysisInfo
protocolKey={protocolKey}
mostRecentAnalysis={mostRecentAnalysis}
protocolDisplayName={protocolDisplayName}
isAnalyzing={isAnalyzing}
modified={modified}
/>
</ErrorBoundary>
<Box
position={POSITION_ABSOLUTE}
top={SPACING.spacing4}
Expand Down

0 comments on commit 1dccc06

Please sign in to comment.