Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: Avoid unexpected dialog shown. #2928

Merged
merged 3 commits into from
Nov 22, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Keith-CY marked this conversation as resolved.
Show resolved Hide resolved
}
})

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