mirror of
https://github.com/geekgeekrun/geekgeekrun.git
synced 2026-09-07 00:17:17 +08:00
simplify communication on auto start chat process being launched
This commit is contained in:
@@ -11,6 +11,7 @@ import { initDb } from '@geekgeekrun/sqlite-plugin'
|
|||||||
import { getPublicDbFilePath } from '@geekgeekrun/geek-auto-start-chat-with-boss/runtime-file-utils.mjs'
|
import { getPublicDbFilePath } from '@geekgeekrun/geek-auto-start-chat-with-boss/runtime-file-utils.mjs'
|
||||||
import { AutoStartChatRunRecord } from '@geekgeekrun/sqlite-plugin/dist/entity/AutoStartChatRunRecord'
|
import { AutoStartChatRunRecord } from '@geekgeekrun/sqlite-plugin/dist/entity/AutoStartChatRunRecord'
|
||||||
import minimist from 'minimist'
|
import minimist from 'minimist'
|
||||||
|
import attachListenerForKillSelfOnParentExited from '../../utils/attachListenerForKillSelfOnParentExited'
|
||||||
|
|
||||||
const rerunInterval = (() => {
|
const rerunInterval = (() => {
|
||||||
let v = Number(process.env.MAIN_BOSSGEEKGO_RERUN_INTERVAL)
|
let v = Number(process.env.MAIN_BOSSGEEKGO_RERUN_INTERVAL)
|
||||||
@@ -20,7 +21,7 @@ const rerunInterval = (() => {
|
|||||||
|
|
||||||
return v
|
return v
|
||||||
})()
|
})()
|
||||||
function runWithDaemon({ runRecordId, runMode }) {
|
function runWithDaemon({ runRecordId, runMode, parentProcessPipe }) {
|
||||||
const subProcessOfCore = childProcess.spawn(
|
const subProcessOfCore = childProcess.spawn(
|
||||||
process.argv[0],
|
process.argv[0],
|
||||||
[...process.argv.slice(1), `--run-record-id=${runRecordId}`],
|
[...process.argv.slice(1), `--run-record-id=${runRecordId}`],
|
||||||
@@ -36,11 +37,11 @@ function runWithDaemon({ runRecordId, runMode }) {
|
|||||||
subProcessOfCore!.stdio[3]!.pipe(JSONStream.parse()).on('data', async (raw) => {
|
subProcessOfCore!.stdio[3]!.pipe(JSONStream.parse()).on('data', async (raw) => {
|
||||||
const data = raw
|
const data = raw
|
||||||
switch (data.type) {
|
switch (data.type) {
|
||||||
case 'AUTO_START_CHAT_MAIN_PROCESS_STARTUP': {
|
case 'GEEK_AUTO_START_CHAT_WITH_BOSS_STARTED': {
|
||||||
pipeWriteRegardlessError(
|
pipeWriteRegardlessError(
|
||||||
subProcessOfCore!.stdio[3]! as WriteStream,
|
parentProcessPipe as WriteStream,
|
||||||
JSON.stringify({
|
JSON.stringify({
|
||||||
type: 'GEEK_AUTO_START_CHAT_CAN_BE_RUN'
|
type: data.type
|
||||||
})
|
})
|
||||||
)
|
)
|
||||||
break
|
break
|
||||||
@@ -67,23 +68,10 @@ function runWithDaemon({ runRecordId, runMode }) {
|
|||||||
`[Run core daemon] Child process exit with code ${exitCode}, an internal error may not be caught, and will be restarted in ${rerunInterval}ms.`
|
`[Run core daemon] Child process exit with code ${exitCode}, an internal error may not be caught, and will be restarted in ${rerunInterval}ms.`
|
||||||
)
|
)
|
||||||
await sleep(rerunInterval)
|
await sleep(rerunInterval)
|
||||||
runWithDaemon({ runRecordId, runMode })
|
runWithDaemon({ runRecordId, runMode, parentProcessPipe })
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// suicide timer for parent and child process don't have any communication after child process spawned.
|
|
||||||
let suicideTimer: NodeJS.Timeout | null = null
|
|
||||||
const setSuicideTimer = () =>
|
|
||||||
(suicideTimer = setTimeout(() => {
|
|
||||||
app.exit(AUTO_CHAT_ERROR_EXIT_CODE.AUTO_START_CHAT_DAEMON_PROCESS_SUICIDE)
|
|
||||||
}, 10000))
|
|
||||||
const clearSuicideTimer = () => {
|
|
||||||
if (suicideTimer) {
|
|
||||||
clearTimeout(suicideTimer)
|
|
||||||
}
|
|
||||||
suicideTimer = null
|
|
||||||
}
|
|
||||||
|
|
||||||
export async function runAutoChatWithDaemon() {
|
export async function runAutoChatWithDaemon() {
|
||||||
const commandlineArgs = minimist(process.argv.slice(2))
|
const commandlineArgs = minimist(process.argv.slice(2))
|
||||||
if (!['geekAutoStartWithBossMain'].includes(commandlineArgs['mode-to-daemon'])) {
|
if (!['geekAutoStartWithBossMain'].includes(commandlineArgs['mode-to-daemon'])) {
|
||||||
@@ -103,7 +91,6 @@ export async function runAutoChatWithDaemon() {
|
|||||||
process.on('disconnect', () => {
|
process.on('disconnect', () => {
|
||||||
app.exit()
|
app.exit()
|
||||||
})
|
})
|
||||||
setSuicideTimer()
|
|
||||||
|
|
||||||
let pipe: null | fs.WriteStream = null
|
let pipe: null | fs.WriteStream = null
|
||||||
try {
|
try {
|
||||||
@@ -116,27 +103,21 @@ export async function runAutoChatWithDaemon() {
|
|||||||
const disposePowerSaveBlocker = initPowerSaveBlocker()
|
const disposePowerSaveBlocker = initPowerSaveBlocker()
|
||||||
app.once('quit', disposePowerSaveBlocker)
|
app.once('quit', disposePowerSaveBlocker)
|
||||||
|
|
||||||
const pipeForRead: fs.ReadStream = fs.createReadStream(null, { fd: 3 })
|
|
||||||
const pipeForReadWithJsonParser = pipeForRead.pipe(JSONStream.parse())
|
|
||||||
pipeForReadWithJsonParser?.on('data', async function waitForCanRun(data) {
|
|
||||||
if (data.type === 'GEEK_AUTO_START_CHAT_CAN_BE_RUN') {
|
|
||||||
pipeForReadWithJsonParser.off('data', waitForCanRun)
|
|
||||||
clearSuicideTimer()
|
|
||||||
// if don't call close, when kill child process, child process will ANR.
|
|
||||||
pipeForRead.close()
|
|
||||||
|
|
||||||
const ds = await initDb(getPublicDbFilePath())
|
|
||||||
const autoStartChatRunRecord = new AutoStartChatRunRecord()
|
|
||||||
autoStartChatRunRecord.date = new Date()
|
|
||||||
const autoStartChatRunRecordRepository = ds.getRepository(AutoStartChatRunRecord)
|
|
||||||
const result = await autoStartChatRunRecordRepository.save(autoStartChatRunRecord)
|
|
||||||
runWithDaemon({ runRecordId: result.id, runMode })
|
|
||||||
}
|
|
||||||
})
|
|
||||||
process.on('SIGINT', () => {
|
process.on('SIGINT', () => {
|
||||||
process.exit()
|
process.exit()
|
||||||
})
|
})
|
||||||
|
|
||||||
|
const ds = await initDb(getPublicDbFilePath())
|
||||||
|
const autoStartChatRunRecord = new AutoStartChatRunRecord()
|
||||||
|
autoStartChatRunRecord.date = new Date()
|
||||||
|
const autoStartChatRunRecordRepository = ds.getRepository(AutoStartChatRunRecord)
|
||||||
|
const result = await autoStartChatRunRecordRepository.save(autoStartChatRunRecord)
|
||||||
|
runWithDaemon({
|
||||||
|
runRecordId: result.id,
|
||||||
|
runMode: commandlineArgs['mode-to-daemon'],
|
||||||
|
parentProcessPipe: pipe
|
||||||
|
})
|
||||||
|
|
||||||
pipeWriteRegardlessError(
|
pipeWriteRegardlessError(
|
||||||
pipe,
|
pipe,
|
||||||
JSON.stringify({
|
JSON.stringify({
|
||||||
@@ -146,3 +127,5 @@ export async function runAutoChatWithDaemon() {
|
|||||||
|
|
||||||
gtag('run_auto_chat_with_boss_daemon_ready')
|
gtag('run_auto_chat_with_boss_daemon_ready')
|
||||||
}
|
}
|
||||||
|
|
||||||
|
attachListenerForKillSelfOnParentExited()
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ import { pipeWriteRegardlessError } from '../utils/pipe'
|
|||||||
import { getAnyAvailablePuppeteerExecutable } from '../CHECK_AND_DOWNLOAD_DEPENDENCIES/utils/puppeteer-executable'
|
import { getAnyAvailablePuppeteerExecutable } from '../CHECK_AND_DOWNLOAD_DEPENDENCIES/utils/puppeteer-executable'
|
||||||
import { sleep } from '@geekgeekrun/utils/sleep.mjs'
|
import { sleep } from '@geekgeekrun/utils/sleep.mjs'
|
||||||
import { AUTO_CHAT_ERROR_EXIT_CODE } from '../../../common/enums/auto-start-chat'
|
import { AUTO_CHAT_ERROR_EXIT_CODE } from '../../../common/enums/auto-start-chat'
|
||||||
import * as JSONStream from 'JSONStream'
|
import attachListenerForKillSelfOnParentExited from '../../utils/attachListenerForKillSelfOnParentExited'
|
||||||
|
|
||||||
import SqlitePluginModule from '@geekgeekrun/sqlite-plugin'
|
import SqlitePluginModule from '@geekgeekrun/sqlite-plugin'
|
||||||
import gtag from '../../utils/gtag'
|
import gtag from '../../utils/gtag'
|
||||||
@@ -140,38 +140,8 @@ const runAutoChat = async () => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// suicide timer for parent and child process don't have any communication after child process spawned.
|
|
||||||
let suicideTimer: NodeJS.Timeout | null = null
|
|
||||||
const setSuicideTimer = () =>
|
|
||||||
(suicideTimer = setTimeout(() => {
|
|
||||||
app.exit(AUTO_CHAT_ERROR_EXIT_CODE.AUTO_START_CHAT_MAIN_PROCESS_SUICIDE)
|
|
||||||
}, 10000))
|
|
||||||
const clearSuicideTimer = () => {
|
|
||||||
if (suicideTimer) {
|
|
||||||
clearTimeout(suicideTimer)
|
|
||||||
}
|
|
||||||
suicideTimer = null
|
|
||||||
}
|
|
||||||
|
|
||||||
export const waitForProcessHandShakeAndRunAutoChat = () => {
|
export const waitForProcessHandShakeAndRunAutoChat = () => {
|
||||||
setSuicideTimer()
|
|
||||||
|
|
||||||
const pipeForRead: fs.ReadStream = fs.createReadStream(null, { fd: 3 })
|
|
||||||
pipeForRead.on('error', () => {
|
|
||||||
return
|
|
||||||
})
|
|
||||||
const pipeForReadWithJsonParser = pipeForRead.pipe(JSONStream.parse())
|
|
||||||
pipeForReadWithJsonParser?.on('data', function waitForCanRun(data) {
|
|
||||||
if (data.type === 'GEEK_AUTO_START_CHAT_CAN_BE_RUN') {
|
|
||||||
pipeForReadWithJsonParser.off('data', waitForCanRun)
|
|
||||||
clearSuicideTimer()
|
|
||||||
runAutoChat()
|
|
||||||
|
|
||||||
// if don't call close, when kill child process, child process will ANR.
|
|
||||||
pipeForRead.close()
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
let pipe: null | fs.WriteStream = null
|
let pipe: null | fs.WriteStream = null
|
||||||
try {
|
try {
|
||||||
pipe = fs.createWriteStream(null, { fd: 3 })
|
pipe = fs.createWriteStream(null, { fd: 3 })
|
||||||
@@ -179,10 +149,7 @@ export const waitForProcessHandShakeAndRunAutoChat = () => {
|
|||||||
console.error('pipe is not available')
|
console.error('pipe is not available')
|
||||||
app.exit(1)
|
app.exit(1)
|
||||||
}
|
}
|
||||||
pipeWriteRegardlessError(
|
runAutoChat()
|
||||||
pipe,
|
|
||||||
JSON.stringify({
|
|
||||||
type: 'AUTO_START_CHAT_MAIN_PROCESS_STARTUP'
|
|
||||||
})
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
attachListenerForKillSelfOnParentExited()
|
||||||
|
|||||||
@@ -117,14 +117,6 @@ export default function initIpc() {
|
|||||||
subProcessOfPuppeteer!.stdio[3]!.pipe(JSONStream.parse()).on('data', async (raw) => {
|
subProcessOfPuppeteer!.stdio[3]!.pipe(JSONStream.parse()).on('data', async (raw) => {
|
||||||
const data = raw
|
const data = raw
|
||||||
switch (data.type) {
|
switch (data.type) {
|
||||||
case 'AUTO_START_CHAT_DAEMON_PROCESS_STARTUP': {
|
|
||||||
subProcessOfPuppeteer!.stdio[3]!.write(
|
|
||||||
JSON.stringify({
|
|
||||||
type: 'GEEK_AUTO_START_CHAT_CAN_BE_RUN'
|
|
||||||
})
|
|
||||||
)
|
|
||||||
break
|
|
||||||
}
|
|
||||||
case 'GEEK_AUTO_START_CHAT_WITH_BOSS_STARTED': {
|
case 'GEEK_AUTO_START_CHAT_WITH_BOSS_STARTED': {
|
||||||
resolve(data)
|
resolve(data)
|
||||||
break
|
break
|
||||||
|
|||||||
Reference in New Issue
Block a user