Javascript NodeJS子进程偶尔停止

Javascript NodeJS子进程偶尔停止,javascript,node.js,child-process,Javascript,Node.js,Child Process,我的应用程序是一个体育博彩机器人。这是一个运行在DO box上的容器化应用程序,它可以“使用”启动多个NodeJS进程。每个子流程在多个博彩交易(Betfair、Smarkets和Matchbook)中监控单个体育赛事 主进程是这些子进程的编排器。在interval上,主进程获取每个活动事件的状态。如果事件已结束,它将向监视该事件的子进程/工作进程发送一条消息 该应用程序相互下注2次,以覆盖所有结果。这两个赌注应该同时下注,但不幸的是,情况并非总是如此。如果发生这种情况,则有一个流程来纠正此位置

我的应用程序是一个体育博彩机器人。这是一个运行在DO box上的容器化应用程序,它可以“使用”启动多个NodeJS进程。每个子流程在多个博彩交易(Betfair、Smarkets和Matchbook)中监控单个体育赛事

主进程是这些子进程的编排器。在interval上,主进程获取每个活动事件的状态。如果事件已结束,它将向监视该事件的子进程/工作进程发送一条消息

该应用程序相互下注2次,以覆盖所有结果。这两个赌注应该同时下注,但不幸的是,情况并非总是如此。如果发生这种情况,则有一个流程来纠正此位置(“纠正流程”)。这就是问题所在。偶尔,子进程会停止。在某个时间点之后,该进程没有日志。校正过程在递归的设置超时上工作:

src/correct.js

const logError=require(“./log error”)
常量记录器=需要(“./logger/winston”)
常量助手={
必发:{
权衡:要求(“./betfair/trade out”),
重试:要求(“./betfair/retry”)
},
smarkets:{
权衡:要求(“./smarkets/trade out”),
重试:要求('./smarkets/retry'),
},
火柴盒:{
折衷:要求('./火柴盒/折衷'),
重试:需要(“./matchbook/retry”)
}
}
让ResolutionAttents=0
module.exports=异步函数(bet、runner){
试一试{
const_promise=新承诺((解决、拒绝)=>{
异步函数{
试一试{
const[lowEx,upEx]=[runner.exchange.toLowerCase(),runner.exchange.toUpperCase()]
溶解剂++
常量isAttemptTradeOut=解析尝试%2==0
const\u trunt=isAttemptTradeOut?'TradeOut':'RETRY'
const_lossmssg=`${(resolutionLossAllowed*100)。toFixed(2)}%允许的损失`
logger.info(`[Testing${{{U Attention}FOR${upEx}和${U lossmssg}(进程:${Process.pid})]`)
常数={
匹配:{…},
不匹配:{…}
}
const result=isAttemptTradeOut
?等待帮助者[lowEx]。权衡(下注,跑步者)
:等待帮助者[lowEx]。重试(下注,跑步者)
如果(结果){
返回解析(结果)
}
setTimeout(校正,10000)//10秒
}捕捉(错误){
日志错误(错误,文件名)
退货拒绝(err)
}
}
纠正
})
常数=等待承诺
返回\u res
}捕捉(错误){
日志错误(错误,文件名)
失误
}
})
Matchbook的
retry.js
文件之一示例(这些文件在整个交换过程中都是相同的):

src/matchbook/retry.js

const bettingApi=require(“../api/betting”)
常量{writeParams}=require('../../../../lib/logger/writer')
const logger=require('../../../../lib/logger/winston')
常量utils={
isArbStillValid:require(“../../../utils/is arb仍然有效”),
getFormattedArb:require('../../../utils/get-formatted arb'),
logJsonError:require(“../../../utils/log json错误”)
}
常数套利={
getBackBackArbTrade:require('../../../strategies/arb套利/拿回arb trade'),
getBackLayArbTrade:require(“../../../strategies/套利/get-BacklayArbTrade”)
}
const PlaceReturns=require('../../../../lib/consts/place returns')
const placeKeepBet=require(“./place keep bet”)
const placeImmediateBet=require(“./placeImmediateBet”)
const isNotFoundError=require('./未找到错误')
异步函数重试(arb、配置、运行程序、lossAllowed=0、isKeep){
试一试{
if(process.env.NODE_env===‘development’){
writeParams('exchanges/matchbook/helpers/retry arb',{arb,config,runner,lossAllowed})
}
常数betId=arb.\u id.toString()
const{eventId,marketId,runnerId}=runners.unmatched
const response=wait bettingApi.getPrices(eventId、marketId、runnerId)
const{prices}=response.data
如果(价格?长度){
const samePrice=prices.find(_price=>{
return\u price.side==runners.unmatched.side
})
if(samePrice){
常量赔率=samePrice[十进制赔率]| | samePrice.赔率
常数newArb={
…arb,
跑步者:[……]
}
const isValidArb=utils.isArbStillValid(newArb,lossAllowed)
if(isValidArb){
const formattedArb=utils.getFormattedArb(newArb)
const\u newArb=arb.subType=='BackLay'
?套利。getBackLayArbTrade(格式化的Arb,配置,损失)
:套利。getBackBackArbTrade(格式化的Arb,配置,lossAllowed)
如果(_newArb){
const unmatchedRunner=\u newArb.runners.find(runner=>{
return runner.exchange==runners.unmatched.exchange
})
if(不匹配的drunner){
常量placeParams={…}
const result=isKeep
?等待placeKeepBet(placeParams)
:等待placeImmediateBet(placeParams)
如果(结果){
返回结果
}
{"message":"[ATTEMPTING RETRY FOR MATCHBOOK WITH 30.20% LOSS ALLOWED (Process: 174)]","level":"info","timestamp":"2020-12-29 17:38:16"}
{"message":"[EVENT HAS ENDED (Process: 174)]","level":"info","timestamp":"2020-12-29 18:25:01"}
#!/bin/bash
while :
do
    ps aux | grep node | grep -v "grep" | sed "s#^#$(date +%Y/%m/%d/%H:%M) #" >> process_log
    sleep 1
done