You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
152 lines
4.3 KiB
152 lines
4.3 KiB
// @flow
|
|
|
|
import '@babel/polyfill'
|
|
import invariant from 'invariant'
|
|
import { fork } from 'child_process'
|
|
import { ipcMain, app } from 'electron'
|
|
import { ipcMainListenReceiveCommands } from 'helpers/ipc'
|
|
import path from 'path'
|
|
import logger from 'logger'
|
|
import sentry, { captureException } from 'sentry/node'
|
|
import user from 'helpers/user'
|
|
import resolveLogsDirectory from 'helpers/resolveLogsDirectory'
|
|
import { deserializeError } from 'helpers/errors'
|
|
|
|
import setupAutoUpdater, { quitAndInstall } from './autoUpdate'
|
|
import { setInternalProcessPID } from './terminator'
|
|
|
|
import { getMainWindow } from './app'
|
|
|
|
logger.setProcessShortName('main')
|
|
|
|
// sqlite files will be located in the app local data folder
|
|
const LEDGER_LIVE_SQLITE_PATH = path.resolve(app.getPath('userData'), 'sqlite')
|
|
const LEDGER_LOGS_DIRECTORY = process.env.LEDGER_LOGS_DIRECTORY || resolveLogsDirectory()
|
|
const LEDGER_CONFIG_DIRECTORY = app.getPath('userData')
|
|
|
|
let internalProcess
|
|
|
|
let sentryEnabled = false
|
|
const userId = user().id
|
|
|
|
sentry(() => sentryEnabled, userId)
|
|
|
|
const killInternalProcess = () => {
|
|
if (internalProcess) {
|
|
logger.log('killing internal process...')
|
|
internalProcess.removeListener('exit', handleExit)
|
|
internalProcess.kill('SIGINT')
|
|
internalProcess = null
|
|
}
|
|
}
|
|
|
|
const forkBundlePath = path.resolve(__dirname, `${__DEV__ ? '../../' : './'}dist/internals`)
|
|
const handleExit = code => {
|
|
logger.warn(`Internal process ended with code ${code}`)
|
|
internalProcess = null
|
|
}
|
|
|
|
const bootInternalProcess = () => {
|
|
logger.log('booting internal process...')
|
|
internalProcess = fork(forkBundlePath, {
|
|
env: {
|
|
...process.env,
|
|
LEDGER_LOGS_DIRECTORY,
|
|
LEDGER_CONFIG_DIRECTORY,
|
|
LEDGER_LIVE_SQLITE_PATH,
|
|
INITIAL_SENTRY_ENABLED: sentryEnabled,
|
|
SENTRY_USER_ID: userId,
|
|
},
|
|
})
|
|
setInternalProcessPID(internalProcess.pid)
|
|
internalProcess.on('message', handleGlobalInternalMessage)
|
|
internalProcess.on('exit', handleExit)
|
|
}
|
|
|
|
process.on('exit', () => {
|
|
killInternalProcess()
|
|
})
|
|
|
|
ipcMain.on('clean-processes', () => {
|
|
killInternalProcess()
|
|
})
|
|
|
|
ipcMainListenReceiveCommands({
|
|
onUnsubscribe: requestId => {
|
|
if (!internalProcess) return
|
|
internalProcess.send({ type: 'command-unsubscribe', requestId })
|
|
},
|
|
onCommand: (command, notifyCommandEvent) => {
|
|
if (!internalProcess) bootInternalProcess()
|
|
const p = internalProcess
|
|
invariant(p, 'internalProcess not started !?')
|
|
|
|
const handleExit = code => {
|
|
p.removeListener('message', handleMessage)
|
|
p.removeListener('exit', handleExit)
|
|
notifyCommandEvent({
|
|
type: 'cmd.ERROR',
|
|
requestId: command.requestId,
|
|
data: { message: `Internal process error (${code})`, name: 'InternalError' },
|
|
})
|
|
}
|
|
|
|
const handleMessage = payload => {
|
|
if (payload.requestId !== command.requestId) return
|
|
notifyCommandEvent(payload)
|
|
if (payload.type === 'cmd.ERROR' || payload.type === 'cmd.COMPLETE') {
|
|
p.removeListener('message', handleMessage)
|
|
p.removeListener('exit', handleExit)
|
|
}
|
|
}
|
|
|
|
p.on('exit', handleExit)
|
|
p.on('message', handleMessage)
|
|
p.send({ type: 'command', command })
|
|
},
|
|
})
|
|
|
|
function handleGlobalInternalMessage(payload) {
|
|
switch (payload.type) {
|
|
case 'uncaughtException': {
|
|
const err = deserializeError(payload.error)
|
|
captureException(err)
|
|
break
|
|
}
|
|
case 'setLibcoreBusy':
|
|
case 'setDeviceBusy':
|
|
case 'executeHttpQueryOnRenderer': {
|
|
const win = getMainWindow && getMainWindow()
|
|
if (!win) {
|
|
logger.warn(`can't ${payload.type} because no renderer`)
|
|
return
|
|
}
|
|
win.webContents.send(payload.type, payload)
|
|
break
|
|
}
|
|
default:
|
|
}
|
|
}
|
|
|
|
ipcMain.on('executeHttpQueryPayload', (event, payload) => {
|
|
const p = internalProcess
|
|
if (!p) return
|
|
p.send({ type: 'executeHttpQueryPayload', payload })
|
|
})
|
|
|
|
ipcMain.on('sentryLogsChanged', (event, payload) => {
|
|
sentryEnabled = payload.value
|
|
const p = internalProcess
|
|
if (!p) return
|
|
p.send({ type: 'sentryLogsChanged', payload })
|
|
})
|
|
|
|
// TODO move this to "command" pattern
|
|
ipcMain.on('updater', (event, { type, data }) => {
|
|
const handler = {
|
|
init: setupAutoUpdater,
|
|
quitAndInstall,
|
|
}[type]
|
|
const send = (type: string, data: *) => event.sender.send('updater', { type, data })
|
|
handler(send, data, type)
|
|
})
|
|
|