Skip to content

Commit

Permalink
fix: Avoid unexpected dialog shown. (#2928)
Browse files Browse the repository at this point in the history
* fix: Avoid unexpected dialog shown.

* fix: Use Object.is to check whether is the same process.

* fix: Add annotation
  • Loading branch information
yanguoyu authored Nov 22, 2023
1 parent 170f6e4 commit dffd921
Show file tree
Hide file tree
Showing 9 changed files with 72 additions and 40 deletions.
1 change: 1 addition & 0 deletions packages/neuron-ui/src/components/NervosDAO/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,7 @@ const NervosDAO = () => {
cacheTipBlockNumber,
currentTimestamp: Date.now(),
url: getCurrentUrl(networkID, networks),
networkID,
})

const MemoizedRecords = useMemo(() => {
Expand Down
1 change: 1 addition & 0 deletions packages/neuron-ui/src/states/stateProvider/reducer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -209,6 +209,7 @@ export const reducer = produce((state: Draft<State.AppWithNeuronWallet>, action:
cacheTipBlockNumber: action.payload.cacheTipBlockNumber,
currentTimestamp: Date.now(),
url: getCurrentUrl(state.chain.networkID, state.settings.networks),
networkID: state.chain.networkID,
}),
}
break
Expand Down
12 changes: 11 additions & 1 deletion packages/neuron-ui/src/utils/getSyncStatus.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,24 +5,34 @@ const TEN_MINS = 10 * 60 * 1000
let blockNumber10MinAgo: number = -1
let timestamp10MinAgo: number | undefined
let prevUrl: string | undefined
let prevNetworkID: string | undefined

export const getSyncStatus = ({
bestKnownBlockNumber,
bestKnownBlockTimestamp,
cacheTipBlockNumber,
currentTimestamp,
url,
networkID,
}: {
bestKnownBlockNumber: number
bestKnownBlockTimestamp: number
cacheTipBlockNumber: number
currentTimestamp: number
url: string | undefined
networkID: string
}) => {
if ((!timestamp10MinAgo && bestKnownBlockNumber >= 0) || (prevUrl && url !== prevUrl && bestKnownBlockNumber >= 0)) {
if (
// !timestamp10MinAgo means start sync for the first time
(!timestamp10MinAgo && bestKnownBlockNumber >= 0) ||
// prevUrl for change the network remote(change network or eidt the network)
// prevNetworkID for change the network, sometime change network the remote is same. light client mainnet -> testnet
(((prevUrl && url !== prevUrl) || (prevNetworkID && prevNetworkID !== networkID)) && bestKnownBlockNumber >= 0)
) {
timestamp10MinAgo = currentTimestamp
blockNumber10MinAgo = bestKnownBlockNumber
prevUrl = url
prevNetworkID = networkID
}

const now = Math.floor(currentTimestamp / 1000) * 1000
Expand Down
12 changes: 8 additions & 4 deletions packages/neuron-wallet/src/controllers/export-debug.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import redistCheck from '../utils/redist-check'
import SettingsService from '../services/settings'
import { generateRPC } from '../utils/ckb-rpc'
import { CKBLightRunner } from '../services/light-runner'
import { LIGHT_CLIENT_MAINNET, LIGHT_CLIENT_TESTNET } from '../utils/const'

export default class ExportDebugController {
#I18N_PATH = 'export-debug-info'
Expand Down Expand Up @@ -162,10 +163,13 @@ export default class ExportDebugController {
}

private addBundledCKBLightClientLog() {
const logPath = CKBLightRunner.getInstance().logPath
if (!fs.existsSync(logPath)) {
return
const mainnetLogPath = CKBLightRunner.getInstance().getLogPath(LIGHT_CLIENT_MAINNET)
const testnetLogPath = CKBLightRunner.getInstance().getLogPath(LIGHT_CLIENT_TESTNET)
if (fs.existsSync(mainnetLogPath)) {
this.archive.file(mainnetLogPath, { name: 'bundled-ckb-lignt-client-mainnet.log' })
}
if (fs.existsSync(testnetLogPath)) {
this.archive.file(testnetLogPath, { name: 'bundled-ckb-lignt-client-testnet.log' })
}
this.archive.file(logPath, { name: 'bundled-ckb-lignt-client.log' })
}
}
20 changes: 13 additions & 7 deletions packages/neuron-wallet/src/services/ckb-runner.ts
Original file line number Diff line number Diff line change
Expand Up @@ -119,16 +119,16 @@ export const startCkbNode = async () => {
stdio[1] = 'pipe'
}
logger.info(`CKB:\tckb full node will with rpc port ${rpcPort}, listen port ${listenPort}, with options`, options)
ckb = spawn(ckbBinary(), options, { stdio })
const currentProcess = spawn(ckbBinary(), options, { stdio })

ckb.stderr?.on('data', data => {
currentProcess.stderr?.on('data', data => {
const dataString: string = data.toString()
logger.error('CKB:\trun fail:', dataString)
if (dataString.includes('CKB wants to migrate the data into new format')) {
MigrateSubject.next({ type: 'need-migrate' })
}
})
ckb.stdout?.on('data', data => {
currentProcess.stdout?.on('data', data => {
const dataString: string = data.toString()
if (
dataString.includes(
Expand All @@ -142,18 +142,24 @@ export const startCkbNode = async () => {
}
})

ckb.on('error', error => {
currentProcess.on('error', error => {
logger.error('CKB:\trun fail:', error)
isLookingValidTarget = false
ckb = null
if (Object.is(ckb, currentProcess)) {
ckb = null
}
})

ckb.on('close', () => {
currentProcess.on('close', () => {
logger.info('CKB:\tprocess closed')
isLookingValidTarget = false
ckb = null
if (Object.is(ckb, currentProcess)) {
ckb = null
}
})

ckb = currentProcess

removeOldIndexerIfRunSuccess()
}

Expand Down
31 changes: 19 additions & 12 deletions packages/neuron-wallet/src/services/light-runner.ts
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ abstract class NodeRunner {
async stop() {
return new Promise<void>(resolve => {
if (this.runnerProcess) {
logger.info('Runner:\tkilling node')
logger.info('Runner:\tkilling node', this.runnerProcess.pid)
this.runnerProcess.once('close', () => resolve())
this.runnerProcess.kill()
this.runnerProcess = undefined
Expand All @@ -79,7 +79,7 @@ abstract class NodeRunner {
export class CKBLightRunner extends NodeRunner {
protected networkType: NetworkType = NetworkType.Light
protected binaryName: string = 'ckb-light-client'
protected logStream?: fs.WriteStream
protected logStream: Map<string, fs.WriteStream> = new Map()
protected _port: number = 9000

static getInstance(): CKBLightRunner {
Expand Down Expand Up @@ -143,34 +143,41 @@ export class CKBLightRunner extends NodeRunner {
})
this.runnerProcess = runnerProcess

if (!this.logStream) {
this.logStream = fs.createWriteStream(this.logPath)
const network = NetworksService.getInstance().getCurrent()
if (!this.logStream.get(network.id)) {
this.logStream.set(network.id, fs.createWriteStream(this.getLogPath()))
}
const logStream = this.logStream.get(network.id)

runnerProcess.stderr &&
runnerProcess.stderr.on('data', data => {
const dataString: string = data.toString()
logger.error('CKB Light Runner:\trun fail:', dataString)
this.logStream?.write(data)
logStream?.write(data)
})

runnerProcess.stdout &&
runnerProcess.stdout.on('data', data => {
this.logStream?.write(data)
logStream?.write(data)
})
runnerProcess.on('error', error => {
runnerProcess.once('error', error => {
logger.error('CKB Light Runner:\trun fail:', error)
this.runnerProcess = undefined
if (Object.is(this.runnerProcess, runnerProcess)) {
this.runnerProcess = undefined
}
})

runnerProcess.on('close', () => {
runnerProcess.once('close', () => {
logger.info('CKB Light Runner:\tprocess closed')
this.runnerProcess = undefined
if (Object.is(this.runnerProcess, runnerProcess)) {
this.runnerProcess = undefined
}
})
}

get logPath() {
return path.join(logger.transports.file.getFile().path, '..', 'light_client_run.log')
getLogPath(chain?: string) {
const fileName = chain ?? NetworksService.getInstance().getCurrent().chain
return path.join(logger.transports.file.getFile().path, '..', `${fileName}.log`)
}

async clearNodeCache(): Promise<void> {
Expand Down
21 changes: 13 additions & 8 deletions packages/neuron-wallet/src/services/node.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import path from 'path'
import { BI } from '@ckb-lumos/bi'
import { app as electronApp, dialog, shell, app } from 'electron'
import { t } from 'i18next'
import { interval, BehaviorSubject, merge } from 'rxjs'
import { interval, BehaviorSubject, merge, Subject } from 'rxjs'
import { distinctUntilChanged, sampleTime, flatMap, delay, retry, debounceTime } from 'rxjs/operators'
import env from '../env'
import { ConnectionStatusSubject } from '../models/subjects/node'
Expand Down Expand Up @@ -42,6 +42,7 @@ class NodeService {
public tipNumberSubject = new BehaviorSubject<string>('0')
public connectionStatusSubject = new BehaviorSubject<boolean>(false)

#startNodeSubject = new Subject<void>()
private _tipBlockNumber: string = '0'
#startedBundledNode: boolean = false

Expand All @@ -53,6 +54,7 @@ class NodeService {
this.start()
this.syncConnectionStatus()
CurrentNetworkIDSubject.subscribe(this.whenNetworkUpdate)
this.#startNodeSubject.pipe(debounceTime(1000)).subscribe(this.startNode)
}

public get tipBlockNumber(): string {
Expand All @@ -77,17 +79,19 @@ class NodeService {
}

private whenNetworkUpdate = () => {
this.stop?.()
this.#startedBundledNode = false
this.tipNumberSubject.next('0')
this.connectionStatusSubject.next(false)
}

public start = () => {
const { unsubscribe } = this.tipNumber()
this.stop = unsubscribe
this.stop?.()
const subscribe = this.tipNumber()
this.stop = subscribe.unsubscribe.bind(subscribe)
}

public stop: (() => void) | null = null
public stop?: () => void

public tipNumber = () => {
return interval(this.intervalTime)
Expand Down Expand Up @@ -122,8 +126,7 @@ class NodeService {
if (this.delayTime < 10 * this.intervalTime) {
this.delayTime = 2 * this.intervalTime
}
const { unsubscribe } = this.tipNumber()
this.stop = unsubscribe
this.start()
}
)
}
Expand All @@ -134,11 +137,12 @@ class NodeService {
if (isDefaultCKBNeedStart) {
logger.info('CKB:\texternal RPC on default uri not detected, starting bundled CKB node.')
const redistReady = await redistCheck()
await (redistReady ? this.startNode() : this.showGuideDialog())
await (redistReady ? this.#startNodeSubject.next() : this.showGuideDialog())
await startMonitor()
} else {
logger.info('CKB:\texternal RPC on default uri detected, skip starting bundled CKB node.')
}
this.start()
}

public async verifyExternalCkbNode() {
Expand Down Expand Up @@ -170,7 +174,7 @@ class NodeService {
}
}

public async startNode() {
public startNode = async () => {
try {
const network = NetworksService.getInstance().getCurrent()
if (network.type === NetworkType.Light) {
Expand All @@ -191,6 +195,7 @@ class NodeService {
public async startNodeIgnoreExternal() {
logger.info('CKB:\tignore running external node, and start node with another port')
await stopMonitor('ckb')
this.start()
const redistReady = await redistCheck()
await (redistReady ? this.startNode() : this.showGuideDialog())
await startMonitor()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,9 @@ jest.mock('../../src/services/light-runner', () => {
CKBLightRunner: {
getInstance() {
return {
logPath: '',
getLogPath() {
return ''
},
}
},
},
Expand Down
10 changes: 3 additions & 7 deletions packages/neuron-wallet/tests/services/node.test.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { distinctUntilChanged, sampleTime, flatMap, delay, retry } from 'rxjs/operators'
import { BUNDLED_CKB_URL, START_WITHOUT_INDEXER } from '../../src/utils/const'
import { NetworkType } from '../../src/models/network'
import { scheduler } from 'timers/promises'

describe('NodeService', () => {
let nodeService: any
Expand All @@ -9,7 +10,6 @@ describe('NodeService', () => {
const stubbedStartLightNode = jest.fn()
const stubbedStopLightNode = jest.fn()
const stubbedConnectionStatusSubjectNext = jest.fn()
const stubbedCKBSetNode = jest.fn()
const stubbedGetTipBlockNumber = jest.fn()
const stubbedRxjsDebounceTime = jest.fn()
const stubbedCurrentNetworkIDSubjectSubscribe = jest.fn()
Expand Down Expand Up @@ -37,7 +37,6 @@ describe('NodeService', () => {
stubbedStartCKBNode.mockReset()
stubbedStopCkbNode.mockReset()
stubbedConnectionStatusSubjectNext.mockReset()
stubbedCKBSetNode.mockReset()
stubbedGetTipBlockNumber.mockReset()
stubbedCurrentNetworkIDSubjectSubscribe.mockReset()
stubbedNetworsServiceGet.mockReset()
Expand Down Expand Up @@ -351,19 +350,16 @@ describe('NodeService', () => {
describe('targets to bundled node', () => {
const bundledNodeUrl = 'http://127.0.0.1:8114'
beforeEach(async () => {
stubbedCKBSetNode.mockImplementation(() => {
nodeService.ckb.node.url = bundledNodeUrl
})
stubbedStartCKBNode.mockResolvedValue(true)
redistCheckMock.mockResolvedValue(true)
stubbedNetworsServiceGet.mockReturnValue({ remote: bundledNodeUrl, readonly: true })
getLocalNodeInfoMock.mockRejectedValue('not start')
await nodeService.tryStartNodeOnDefaultURI()

await scheduler.wait(1500)
jest.advanceTimersByTime(10000)
})
it('sets startedBundledNode to true in ConnectionStatusSubject', () => {
expect(stubbedConnectionStatusSubjectNext).toHaveBeenCalledWith({
expect(stubbedConnectionStatusSubjectNext).toHaveBeenLastCalledWith({
url: bundledNodeUrl,
connected: false,
isBundledNode: true,
Expand Down

2 comments on commit dffd921

@github-actions
Copy link
Contributor

Choose a reason for hiding this comment

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

Packaging for test is done in 6951503233

@github-actions
Copy link
Contributor

Choose a reason for hiding this comment

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

Packaging for test is done in 6951504285

Please sign in to comment.