Skip to content

Commit

Permalink
[DDW-329] Show block replay progress (#2110)
Browse files Browse the repository at this point in the history
* [DDW-329] Show block replay progress - INIT

* [DDW-329] Run Translations Manager

* [DDW-329] Fix flow issues and code cleanuo

* [DDW-329] Fix flow issues and code cleanup

* [DDW-329] CHANGELOG update

* [DDW-329] Fix logs path

* [DDW-329] Merges develop and fixes CHANGELOG

* [DDW-329] Coden cleanup and improvements

* [DDW-329] CHANGELOG - PR number update

Co-authored-by: Nikola Glumac <niglumac@gmail.com>
  • Loading branch information
Tomislav Horaček and nikolaglumac committed Jul 29, 2020
1 parent 5121774 commit aba9f98
Show file tree
Hide file tree
Showing 15 changed files with 163 additions and 5 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,10 @@ Changelog

## vNext

### Features

- Show block replay progress ([PR 2110](https://github.com/input-output-hk/daedalus/pull/2110))

### Fixes

- Extended the recovery phrase verification to all possible phrase lengths ([PR 2109](https://github.com/input-output-hk/daedalus/pull/2109))
Expand Down
7 changes: 7 additions & 0 deletions source/common/ipc/api.js
Original file line number Diff line number Diff line change
Expand Up @@ -320,3 +320,10 @@ export type DownloadMainResponse = DownloadResponse;
export const RESUME_DOWNLOAD = 'RESUME_DOWNLOAD';
export type ResumeDownloadRendererRequest = ResumeDownloadRequest;
export type ResumeDownloadMainResponse = ResumeDownloadResponse | void;

/**
* Channel for checking block replay progress
*/
export const GET_BLOCK_REPLAY_STATUS_CHANNEL = 'GetBlockReplayProgressChannel';
export type GetBlockReplayProgressRendererRequest = void;
export type GetBlockReplayProgressMainResponse = number;
2 changes: 2 additions & 0 deletions source/main/config.js
Original file line number Diff line number Diff line change
Expand Up @@ -161,6 +161,8 @@ export const DISK_SPACE_CHECK_MEDIUM_INTERVAL = 60 * 1000; // 1 minute | unit: m
export const DISK_SPACE_CHECK_SHORT_INTERVAL = isTest ? 2000 : 10 * 1000; // 10 seconds | unit: milliseconds
export const DISK_SPACE_RECOMMENDED_PERCENTAGE = 15; // 15% of the total disk space

export const BLOCK_REPLAY_PROGRESS_CHECK_INTERVAL = 1 * 1000; // 1 seconds | unit: milliseconds

// CardanoWallet config
export const STAKE_POOL_REGISTRY_URL = {
itn_selfnode:
Expand Down
3 changes: 3 additions & 0 deletions source/main/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import {
generateWalletMigrationReport,
} from './utils/setupLogging';
import { handleDiskSpace } from './utils/handleDiskSpace';
import { handleCheckBlockReplayProgress } from './utils/handleCheckBlockReplayProgress';
import { createMainWindow } from './windows/main';
import { installChromeExtensions } from './utils/installChromeExtensions';
import { environment } from './environment';
Expand Down Expand Up @@ -164,6 +165,8 @@ const onAppReady = async () => {
mainErrorHandler(onMainError);
await handleCheckDiskSpace();

await handleCheckBlockReplayProgress(mainWindow, launcherConfig.logsPrefix);

cardanoNode = setupCardanoNode(launcherConfig, mainWindow);

if (isWatchMode) {
Expand Down
14 changes: 14 additions & 0 deletions source/main/ipc/get-block-replay-progress.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
// @flow
import { MainIpcChannel } from './lib/MainIpcChannel';
import { GET_BLOCK_REPLAY_STATUS_CHANNEL } from '../../common/ipc/api';
import type {
GetBlockReplayProgressRendererRequest,
GetBlockReplayProgressMainResponse,
} from '../../common/ipc/api';

// IpcChannel<Incoming, Outgoing>

export const getBlockReplayProgressChannel: MainIpcChannel<
GetBlockReplayProgressRendererRequest,
GetBlockReplayProgressMainResponse
> = new MainIpcChannel(GET_BLOCK_REPLAY_STATUS_CHANNEL);
50 changes: 50 additions & 0 deletions source/main/utils/handleCheckBlockReplayProgress.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
// @flow
import { BrowserWindow } from 'electron';
import fs from 'fs';
import readline from 'readline';
import path from 'path';
import { getBlockReplayProgressChannel } from '../ipc/get-block-replay-progress';
import { BLOCK_REPLAY_PROGRESS_CHECK_INTERVAL } from '../config';

export const handleCheckBlockReplayProgress = (
mainWindow: BrowserWindow,
logsDirectoryPath: string
) => {
const checkBlockReplayProgress = async () => {
const filename = 'node.log';
const logFilePath = `${logsDirectoryPath}/pub/`;
const filePath = path.join(logFilePath, filename);
if (!fs.existsSync(filePath)) return;

const fileStream = fs.createReadStream(filePath);
const rl = readline.createInterface({ input: fileStream });
const progress = [];
for await (const line of rl) {
if (line.includes('block replay')) {
progress.push(line);
}
}
if (!progress.length) return;

const finalProgress = progress.slice(-1).pop();
const percentage = finalProgress.split('block replay progress (%) =').pop();
const finalProgressPercentage = parseFloat(percentage);

// Send result to renderer process (NetworkStatusStore)
getBlockReplayProgressChannel.send(
finalProgressPercentage,
mainWindow.webContents
);
};

const setBlockReplayProgressCheckingInterval = () => {
setInterval(async () => {
checkBlockReplayProgress();
}, BLOCK_REPLAY_PROGRESS_CHECK_INTERVAL);
};

// Start default interval
setBlockReplayProgressCheckingInterval();

return checkBlockReplayProgress;
};
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ type State = {

type Props = {
cardanoNodeState: ?CardanoNodeState,
verificationProgress: number,
hasBeenConnected: boolean,
forceConnectivityIssue?: boolean,
isFlight: boolean,
Expand All @@ -46,6 +47,7 @@ type Props = {
disableDownloadLogs: boolean,
showNewsFeedIcon: boolean,
isIncentivizedTestnet: boolean,
isVerifyingBlockchain: boolean,
onIssueClick: Function,
onOpenExternalLink: Function,
onDownloadLogs: Function,
Expand Down Expand Up @@ -75,6 +77,7 @@ export default class SyncingConnecting extends Component<Props, State> {
isNewAppVersionLoaded,
isIncentivizedTestnet,
isFlight,
isVerifyingBlockchain,
} = this.props;
const canResetConnecting = this._connectingTimerShouldStop(isConnected);

Expand All @@ -83,10 +86,11 @@ export default class SyncingConnecting extends Component<Props, State> {
this._resetConnectingTime();
}
const isAppLoadingStuck =
isSyncProgressStalling ||
(!isConnected &&
(connectingTime >= REPORT_ISSUE_TIME_TRIGGER ||
cardanoNodeState === CardanoNodeStates.UNRECOVERABLE));
!isVerifyingBlockchain &&
(isSyncProgressStalling ||
(!isConnected &&
(connectingTime >= REPORT_ISSUE_TIME_TRIGGER ||
cardanoNodeState === CardanoNodeStates.UNRECOVERABLE)));
// If app loading is stuck, check if a newer version is available and set flag (state)
if (
isAppLoadingStuck &&
Expand Down Expand Up @@ -185,6 +189,8 @@ export default class SyncingConnecting extends Component<Props, State> {
onStatusIconClick,
onToggleNewsFeedIconClick,
showNewsFeedIcon,
isVerifyingBlockchain,
verificationProgress,
} = this.props;

const newsFeedIconStyles = classNames([
Expand Down Expand Up @@ -227,6 +233,8 @@ export default class SyncingConnecting extends Component<Props, State> {
isConnected={isConnected}
isNodeStopping={isNodeStopping}
isNodeStopped={isNodeStopped}
isVerifyingBlockchain={isVerifyingBlockchain}
verificationProgress={verificationProgress}
/>
<StatusIcons
onIconClick={onStatusIconClick}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -65,16 +65,25 @@ const messages = defineMessages({
defaultMessage: '!!!TLS certificate is not valid, please restart Daedalus.',
description: 'The TLS cert is not valid and Daedalus should be restarted',
},
verifyingBlockchain: {
id: 'loading.screen.verifyingBlockchainMessage',
defaultMessage:
'!!!Verifying the blockchain ({verificationProgress}% complete)',
description:
'Message "Verifying the blockchain (65% complete) ..." on the loading screen.',
},
});

type Props = {
cardanoNodeState: ?CardanoNodeState,
verificationProgress: number,
hasLoadedCurrentLocale: boolean,
hasBeenConnected: boolean,
isTlsCertInvalid: boolean,
isConnected: boolean,
isNodeStopping: boolean,
isNodeStopped: boolean,
isVerifyingBlockchain: boolean,
};

export default class SyncingConnectingStatus extends Component<Props> {
Expand Down Expand Up @@ -139,6 +148,8 @@ export default class SyncingConnectingStatus extends Component<Props> {
isNodeStopped,
isTlsCertInvalid,
hasLoadedCurrentLocale,
isVerifyingBlockchain,
verificationProgress,
} = this.props;

if (!hasLoadedCurrentLocale) return null;
Expand All @@ -159,7 +170,11 @@ export default class SyncingConnectingStatus extends Component<Props> {
return (
<div className={componentStyles}>
<h1 className={headlineStyles}>
{intl.formatMessage(this._getConnectingMessage())}
{isVerifyingBlockchain
? intl.formatMessage(messages.verifyingBlockchain, {
verificationProgress,
})
: intl.formatMessage(this._getConnectingMessage())}
</h1>
</div>
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@ export default class LoadingSyncingConnectingPage extends Component<Props> {
isNodeStopped,
isNotEnoughDiskSpace,
isTlsCertInvalid,
isVerifyingBlockchain,
verificationProgress,
} = stores.networkStatus;
const {
isNewAppVersionAvailable,
Expand Down Expand Up @@ -75,6 +77,8 @@ export default class LoadingSyncingConnectingPage extends Component<Props> {
onToggleNewsFeedIconClick={toggleNewsFeed.trigger}
disableDownloadLogs={stores.app.isDownloadNotificationVisible}
showNewsFeedIcon={!isNodeStopping && !isNodeStopped}
isVerifyingBlockchain={isVerifyingBlockchain}
verificationProgress={verificationProgress}
/>
);
}
Expand Down
14 changes: 14 additions & 0 deletions source/renderer/app/i18n/locales/defaultMessages.json
Original file line number Diff line number Diff line change
Expand Up @@ -1076,6 +1076,20 @@
"column": 31,
"line": 63
}
},
{
"defaultMessage": "!!!Verifying the blockchain ({verificationProgress}% complete)",
"description": "Message \"Verifying the blockchain (65% complete) ...\" on the loading screen.",
"end": {
"column": 3,
"line": 73
},
"file": "source/renderer/app/components/loading/syncing-connecting/SyncingConnectingStatus.js",
"id": "loading.screen.verifyingBlockchainMessage",
"start": {
"column": 23,
"line": 68
}
}
],
"path": "source/renderer/app/components/loading/syncing-connecting/SyncingConnectingStatus.json"
Expand Down
1 change: 1 addition & 0 deletions source/renderer/app/i18n/locales/en-US.json
Original file line number Diff line number Diff line change
Expand Up @@ -176,6 +176,7 @@
"loading.screen.unrecoverableCardanoMessage": "Unable to start Cardano node. Please submit a support request.",
"loading.screen.updatedCardanoMessage": "Cardano node updated",
"loading.screen.updatingCardanoMessage": "Updating Cardano node",
"loading.screen.verifyingBlockchainMessage": "Verifying the blockchain ({verificationProgress}% complete) ",
"manualUpdate.button.label": "Follow instructions and manually update",
"manualUpdate.button.url": "https://iohk.zendesk.com/hc/en-us/articles/360023850634",
"manualUpdate.description1": "You are experiencing network connection issues, and you are not running the latest Daedalus version. Automatic updates are unavailable while Daedalus is not connected to Cardano network.",
Expand Down
1 change: 1 addition & 0 deletions source/renderer/app/i18n/locales/ja-JP.json
Original file line number Diff line number Diff line change
Expand Up @@ -176,6 +176,7 @@
"loading.screen.unrecoverableCardanoMessage": "Cardanoノードを起動できません。サポートリクエストを送信してください。",
"loading.screen.updatedCardanoMessage": "Cardanoノードが更新されました",
"loading.screen.updatingCardanoMessage": "Cardanoノードを更新しています",
"loading.screen.verifyingBlockchainMessage": "ブロックチェーンを検証しています({verificationProgress}%完了)",
"manualUpdate.button.label": "指示に従って手動で更新してください",
"manualUpdate.button.url": "https://iohk.zendesk.com/hc/ja/articles/360023850634",
"manualUpdate.description1": "ネットワークへの接続に不具合があり、Daedalusウォレットの最新バージョンが実行されていません。DaedalusがCardanoネットワークに接続されていない間、自動更新は実行できません。",
Expand Down
13 changes: 13 additions & 0 deletions source/renderer/app/ipc/getBlockReplayChannel.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
// @flow
import { GET_BLOCK_REPLAY_STATUS_CHANNEL } from '../../../common/ipc/api';
import type {
GetBlockReplayProgressRendererRequest,
GetBlockReplayProgressMainResponse,
} from '../../../common/ipc/api';
import { RendererIpcChannel } from './lib/RendererIpcChannel';

export const getBlockReplayProgressChannel: // IpcChannel<Incoming, Outgoing>
RendererIpcChannel<
GetBlockReplayProgressMainResponse,
GetBlockReplayProgressRendererRequest
> = new RendererIpcChannel(GET_BLOCK_REPLAY_STATUS_CHANNEL);
16 changes: 16 additions & 0 deletions source/renderer/app/stores/NetworkStatusStore.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import {
} from '../ipc/cardano.ipc';
import { CardanoNodeStates } from '../../../common/types/cardano-node.types';
import { getDiskSpaceStatusChannel } from '../ipc/getDiskSpaceChannel.js';
import { getBlockReplayProgressChannel } from '../ipc/getBlockReplayChannel.js';
import { getStateDirectoryPathChannel } from '../ipc/getStateDirectoryPathChannel';
import type {
GetNetworkInfoResponse,
Expand Down Expand Up @@ -121,6 +122,7 @@ export default class NetworkStatusStore extends Store {
@observable isShelleyActivated: boolean = false;
@observable isShelleyPending: boolean = false;
@observable shelleyActivationTime: string = '';
@observable verificationProgress: number = 0;

// DEFINE STORE METHODS
setup() {
Expand Down Expand Up @@ -164,6 +166,9 @@ export default class NetworkStatusStore extends Store {
this._checkDiskSpace();

this._getStateDirectoryPath();

// Blockchain verification checking
getBlockReplayProgressChannel.onReceive(this._onCheckVerificationProgress);
}

_restartNode = async () => {
Expand Down Expand Up @@ -641,6 +646,13 @@ export default class NetworkStatusStore extends Store {
return Promise.resolve();
};

@action _onCheckVerificationProgress = (
verificationProgress: number
): Promise<void> => {
this.verificationProgress = verificationProgress;
return Promise.resolve();
};

@action _onReceiveStateDirectoryPath = (stateDirectoryPath: string) => {
this.stateDirectoryPath = stateDirectoryPath;
};
Expand Down Expand Up @@ -685,4 +697,8 @@ export default class NetworkStatusStore extends Store {
get(networkTip, 'slot', null) !== null
);
}

@computed get isVerifyingBlockchain(): boolean {
return !this.isConnected && this.verificationProgress < 100;
}
}
6 changes: 6 additions & 0 deletions storybook/stories/nodes/syncing/SyncingConnecting.stories.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ export const DefaultSyncingConnectingStory = (props: {
currentTheme: string,
}) => (
<SyncingConnecting
isVerifyingBlockchain={false}
verificationProgress={0}
hasUnreadAlerts={false}
hasUnreadAnnouncements={false}
hasUnreadNews={false}
Expand Down Expand Up @@ -56,6 +58,8 @@ export const ConnectivityIssuesSyncingConnectingStory = (props: {
currentTheme: string,
}) => (
<SyncingConnecting
isVerifyingBlockchain={false}
verificationProgress={0}
hasUnreadAlerts={false}
hasUnreadAnnouncements={false}
hasUnreadNews={false}
Expand Down Expand Up @@ -97,6 +101,8 @@ export const LoadingWalletDataSyncingConnectingStory = (props: {
currentTheme: string,
}) => (
<SyncingConnecting
isVerifyingBlockchain={false}
verificationProgress={0}
hasUnreadAlerts={false}
hasUnreadAnnouncements={false}
hasUnreadNews={false}
Expand Down

0 comments on commit aba9f98

Please sign in to comment.