Skip to content

Commit

Permalink
Feat/LIVE-8535: new get-latest-available-firmware action (#4042)
Browse files Browse the repository at this point in the history
Created a getLatestAvailableFirmwareAction and a React adapter with a hook: useGetLatestAvailableFirmware

The need came from having a version of a "get latest available firmware" function that is resilient to Transport race conditions (by catching and retrying).

Also added:
- unit tests on getLatestAvailableFirmwareAction: with a test on the retry mechanism, mocking only the "inner" definition of the task
- a new error (only used in the device SDK): UnresponsiveDeviceError
- propagate the following informations:
  - does the current error that occurred in a task triggered an attemp to retry the task ?
  - what kind of locked device error occurred: 0x5515 (LockedDeviceError) or device "unresponsive"

And chore/fixed:
- rename filename for hook useGetDeviceInfo in device SDK
- how locked device errors are handled in the LLM firmware update
  • Loading branch information
alexandremgo authored Jul 20, 2023
1 parent aba777d commit c7c484a
Show file tree
Hide file tree
Showing 20 changed files with 676 additions and 31 deletions.
5 changes: 5 additions & 0 deletions .changeset/four-spoons-explode.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"live-mobile": patch
---

fix: locked device errors handling in LLM new firmwre update
5 changes: 5 additions & 0 deletions .changeset/tidy-masks-double.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@ledgerhq/errors": patch
---

feat: new error (only used in the device SDK) `UnresponsiveDeviceError`
16 changes: 16 additions & 0 deletions .changeset/witty-pillows-roll.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
---
"@ledgerhq/live-common": patch
---

feat: new get latest available firmware action and hook

Created a getLatestAvailableFirmwareAction and a React adapter with a hook: useGetLatestAvailableFirmware
The need came from having a version of a "get latest available firmware" function that is resilient
to Transport race conditions (by catching and retrying).

Implemented using the new device SDK paradigm.

Also now propagating the following informations:

- does the current error that occurred in a task triggered an attempt to retry the task ?
- what kind of locked device error occurred: 0x5515 (LockedDeviceError) or device "unresponsive"
7 changes: 6 additions & 1 deletion apps/ledger-live-mobile/src/screens/FirmwareUpdate/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -463,7 +463,12 @@ export const FirmwareUpdate = ({
// device actions that use different transport acquisition paradigms
// the action should, however, retry to execute and resolve the error by itself
// no need to present the error to the user
if (error && error.name !== "TransportRaceCondition") {
if (
error &&
!["TransportRaceCondition", "LockedDeviceError", "UnresponsiveDeviceError"].includes(
error.name,
)
) {
return (
<DeviceActionError
device={device}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -127,7 +127,7 @@ export default function DebugFirmwareUpdate() {
) =>
setActionState((oldState: UpdateFirmwareActionState) => ({
...oldState,
error: { type: errorType, name: error, message: error },
error: { type: errorType, name: error, message: error, retrying: false },
})),
[],
);
Expand Down
24 changes: 19 additions & 5 deletions libs/ledger-live-common/src/deviceSDK/actions/core.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,20 @@
import { LockedDeviceError } from "@ledgerhq/errors";
import { LockedDeviceError, UnresponsiveDeviceError } from "@ledgerhq/errors";
import { SharedTaskEvent } from "../tasks/core";

// Represents the state that is shared with any action
// The type of the error prop is specific to the action
export type SharedActionState = {
lockedDevice: boolean;
error: { type: "SharedError"; message: string; name: string } | null;
error: {
type: "SharedError";
message: string;
name: string;

/**
* Informs if the action and its associated task in error is attempting to retry
*/
retrying: boolean;
} | null;
};

// Mix the specific action state with the shared state
Expand All @@ -29,11 +38,15 @@ export function sharedReducer({ event }: { event: SharedTaskEvent }): Partial<Sh
switch (event.type) {
// Handles shared errors coming from a task
case "error": {
const { error } = event;
const { error, retrying } = event;
const { name, message } = error;

if (error instanceof LockedDeviceError) {
return { lockedDevice: true };
if (
error instanceof LockedDeviceError ||
(error as unknown) instanceof UnresponsiveDeviceError
) {
// Propagates the error so the consumer can distinguish locked (from error response) and unresponsive error.
return { lockedDevice: true, error: { type: "SharedError", name, message, retrying } };
}

// Maps any other unhandled error to a SharedError with a specific message
Expand All @@ -42,6 +55,7 @@ export function sharedReducer({ event }: { event: SharedTaskEvent }): Partial<Sh
type: "SharedError",
name,
message,
retrying,
},
};
}
Expand Down
Loading

1 comment on commit c7c484a

@vercel
Copy link

@vercel vercel bot commented on c7c484a Jul 20, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please sign in to comment.