move the core logic of run core to child process, and rerun run child process in daemon process when uncaught error makes process terminated.

This commit is contained in:
geekgeekrun
2024-03-16 01:52:26 +08:00
parent 44aa73e18c
commit f0e7eadfbc
5 changed files with 108 additions and 28 deletions

View File

@@ -6,7 +6,7 @@
"module": "./main/index.mjs",
"type": "module",
"scripts": {
"start": "node ./packages/run-core-of-geek-auto-start-chat-with-boss/index.mjs"
"start": "node ./packages/run-core-of-geek-auto-start-chat-with-boss/daemon-main.mjs"
},
"author": "geekgeekrun",
"license": "ISC",

View File

@@ -0,0 +1,51 @@
import path from 'node:path'
import * as url from 'url'
import { sleep } from '@geekgeekrun/utils/sleep.mjs';
import childProcess from 'node:child_process';
import { AUTO_CHAT_ERROR_EXIT_CODE } from './enums.mjs'
const rerunInterval = (() => {
let v = Number(process.env.MAIN_BOSSGEEKGO_RERUN_INTERVAL)
if (isNaN(v)) {
v = 3000
}
return v
})()
const __dirname = url.fileURLToPath(new URL('.', import.meta.url))
function runWithDaemon () {
const subProcessOfCore = childProcess.spawn(
`node`,
[path.join(
__dirname,
'main.mjs'
)],
{
stdio: ['inherit', 'inherit', 'inherit', 'pipe', 'ipc'],
env: {
...process.env,
MAIN_BOSSGEEKGO_RERUN_INTERVAL: rerunInterval
}
}
)
subProcessOfCore.once(
'exit',
async (exitCode) => {
if (
[
...Object.values(AUTO_CHAT_ERROR_EXIT_CODE)
].filter(it => typeof it === 'number').includes(exitCode)
) {
console.log(`[Run core daemon] Child process exit with reason ${AUTO_CHAT_ERROR_EXIT_CODE[exitCode]}.`)
process.exit(exitCode)
return
}
console.log(`[Run core daemon] Child process exit with code ${exitCode}, an internal may not be caught, and will be restarted in ${rerunInterval}ms.`)
await sleep(rerunInterval)
runWithDaemon()
}
)
}
runWithDaemon()

View File

@@ -0,0 +1,16 @@
export const AUTO_CHAT_ERROR_EXIT_CODE = (() => {
const enums = {
NORMAL: 0,
COOKIE_INVALID: 81,
LOGIN_STATUS_INVALID: 82,
ERR_INTERNET_DISCONNECTED: 83,
ACCESS_IS_DENIED: 84
}
const kvList = Object.entries(enums)
kvList.forEach(([k, v]) => {
enums[v] = k
})
return enums
})()

View File

@@ -10,6 +10,23 @@ import { get__dirname } from '@geekgeekrun/utils/legacy-path.mjs';
import JSON5 from 'json5'
import { readConfigFile, readStorageFile } from '@geekgeekrun/geek-auto-start-chat-with-boss/runtime-file-utils.mjs'
import { sleep } from '@geekgeekrun/utils/sleep.mjs'
import {
AUTO_CHAT_ERROR_EXIT_CODE
} from './enums.mjs'
const rerunInterval = (() => {
let v = Number(process.env.MAIN_BOSSGEEKGO_RERUN_INTERVAL)
if (isNaN(v)) {
v = 3000
}
return v
})()
process.on('disconnect', () => {
process.exit()
})
const bossCookies = readStorageFile('boss-cookies.json')
const { groupRobotAccessToken: dingTalkAccessToken } = readConfigFile('dingtalk.json')
@@ -17,11 +34,6 @@ const initPlugins = (hooks) => {
new DingtalkPlugin(dingTalkAccessToken).apply(hooks)
}
const AUTO_CHAT_ERROR_EXIT_CODE = {
COOKIE_INVALID: 81,
LOGIN_STATUS_INVALID: 82
}
const main = async () => {
if (!bossCookies?.length) {
console.error('There is no cookies. You can save a copy with EditThisCookie extension.')
@@ -42,30 +54,29 @@ const main = async () => {
try {
await mainLoop(hooks)
} catch (err) {
if (err instanceof Error && err.message.includes('LOGIN_STATUS_INVALID')) {
process.exit(AUTO_CHAT_ERROR_EXIT_CODE.LOGIN_STATUS_INVALID)
break
if (err instanceof Error) {
if (err.message.includes('LOGIN_STATUS_INVALID')) {
process.exit(AUTO_CHAT_ERROR_EXIT_CODE.LOGIN_STATUS_INVALID)
break
}
if (err.message.includes('ERR_INTERNET_DISCONNECTED')) {
process.exit(AUTO_CHAT_ERROR_EXIT_CODE.ERR_INTERNET_DISCONNECTED)
break
}
if (err.message.includes('ACCESS_IS_DENIED')) {
process.exit(AUTO_CHAT_ERROR_EXIT_CODE.ACCESS_IS_DENIED)
break
}
}
await sleep(3000)
console.error(err)
console.log(`[Run core main] An internal is caught, and browser will be restarted in ${rerunInterval}ms.`)
await sleep(rerunInterval)
}
}
}
main()
process.on('error', async (error) => {
closeBrowserWindow()
console.error('error')
console.error(error)
await sleep(3000)
main()
})
process.on('unhandledRejection', async (reason, promise) => {
closeBrowserWindow()
console.error('unhandledRejection')
console.error(reason, promise)
await sleep(3000)
main()
});
(async () => {
try {
await main()
} catch {}
})()

View File

@@ -6,6 +6,8 @@
"module": "./index.mjs",
"type": "module",
"scripts": {
"start": "node ./daemon-main.mjs",
"start:bare": "node ./main.mjs"
},
"author": "geekgeekrun",
"license": "ISC",