@@ -12,6 +12,7 @@ import {
1212import { CronJob } from "cron" ;
1313import IoC from "@App/app/ioc" ;
1414import ExecScript from "./exec_script" ;
15+ import { BgExecScriptWarp , CATRetryError } from "./exec_warp" ;
1516
1617type SandboxEvent = "enable" | "disable" | "start" | "stop" ;
1718
@@ -28,9 +29,53 @@ export default class SandboxRuntime {
2829
2930 execScripts : Map < number , ExecScript > = new Map ( ) ;
3031
32+ retryList : {
33+ script : ScriptRunResouce ;
34+ retryTime : number ;
35+ } [ ] = [ ] ;
36+
3137 constructor ( message : MessageSandbox ) {
3238 this . message = message ;
3339 this . logger = LoggerCore . getInstance ( ) . logger ( { component : "sandbox" } ) ;
40+ // 重试队列,5s检查一次
41+ setInterval ( ( ) => {
42+ if ( ! this . retryList . length ) {
43+ return ;
44+ }
45+ const now = Date . now ( ) ;
46+ const retryList = [ ] ;
47+ for ( let i = 0 ; i < this . retryList . length ; i += 1 ) {
48+ const item = this . retryList [ i ] ;
49+ if ( item . retryTime < now ) {
50+ this . retryList . splice ( i , 1 ) ;
51+ i -= 1 ;
52+ retryList . push ( item . script ) ;
53+ }
54+ }
55+ retryList . forEach ( ( script ) => {
56+ script . nextruntime = 0 ;
57+ this . execScript ( script ) ;
58+ } ) ;
59+ } , 5000 ) ;
60+ }
61+
62+ joinRetryList ( script : ScriptRunResouce ) {
63+ if ( script . nextruntime ) {
64+ this . retryList . push ( {
65+ script,
66+ retryTime : script . nextruntime ,
67+ } ) ;
68+ this . retryList . sort ( ( a , b ) => a . retryTime - b . retryTime ) ;
69+ }
70+ }
71+
72+ removeRetryList ( scriptId : number ) {
73+ for ( let i = 0 ; i < this . retryList . length ; i += 1 ) {
74+ if ( this . retryList [ i ] . script . id === scriptId ) {
75+ this . retryList . splice ( i , 1 ) ;
76+ i -= 1 ;
77+ }
78+ }
3479 }
3580
3681 listenEvent ( event : SandboxEvent , handler : Handler ) {
@@ -55,7 +100,7 @@ export default class SandboxRuntime {
55100
56101 // 直接运行脚本
57102 start ( script : ScriptRunResouce ) : Promise < boolean > {
58- return this . execScript ( script ) ;
103+ return this . execScript ( script , true ) ;
59104 }
60105
61106 stop ( scriptId : number ) : Promise < boolean > {
@@ -92,11 +137,9 @@ export default class SandboxRuntime {
92137 // 现期对于正在运行的脚本仅仅是在background中判断是否运行
93138 // 未运行的脚本不处理GMApi的请求
94139 this . stopCronJob ( id ) ;
95- const exec = this . execScripts . get ( id ) ;
96- if ( ! exec ) {
97- return Promise . resolve ( false ) ;
98- }
99- return Promise . resolve ( true ) ;
140+ // 移除重试队列
141+ this . removeRetryList ( id ) ;
142+ return this . stop ( id ) ;
100143 }
101144
102145 // 停止计时器
@@ -111,14 +154,14 @@ export default class SandboxRuntime {
111154 }
112155
113156 // 执行脚本
114- execScript ( script : ScriptRunResouce ) {
157+ execScript ( script : ScriptRunResouce , execOnce ?: boolean ) {
115158 const logger = this . logger . with ( { scriptId : script . id , name : script . name } ) ;
116159 if ( this . execScripts . has ( script . id ) ) {
117160 // 释放掉资源
118161 // 暂未实现执行完成后立马释放,会在下一次执行时释放
119162 this . stop ( script . id ) ;
120163 }
121- const exec = new ExecScript ( script , this . message ) ;
164+ const exec = new BgExecScriptWarp ( script , this . message ) ;
122165 this . execScripts . set ( script . id , exec ) ;
123166 this . message . send ( "scriptRunStatus" , [
124167 exec . scriptRes . id ,
@@ -141,11 +184,25 @@ export default class SandboxRuntime {
141184 } )
142185 . catch ( ( err ) => {
143186 // 发送执行完成+错误消息
144- logger . error ( "exec script error" , Logger . E ( err ) ) ;
187+ let errMsg ;
188+ let nextruntime = 0 ;
189+ if ( err instanceof CATRetryError ) {
190+ errMsg = { error : err . msg } ;
191+ if ( ! execOnce ) {
192+ // 下一次执行时间
193+ nextruntime = err . time . getTime ( ) ;
194+ script . nextruntime = nextruntime ;
195+ this . joinRetryList ( script ) ;
196+ }
197+ } else {
198+ errMsg = Logger . E ( err ) ;
199+ }
200+ logger . error ( "exec script error" , errMsg ) ;
145201 this . message . send ( "scriptRunStatus" , [
146202 exec . scriptRes . id ,
147203 SCRIPT_RUN_STATUS_ERROR ,
148- Logger . E ( err ) ,
204+ errMsg ,
205+ nextruntime ,
149206 ] ) ;
150207 // 错误还是抛出,方便排查
151208 throw err ;
@@ -161,6 +218,8 @@ export default class SandboxRuntime {
161218 if ( ! script . metadata . crontab ) {
162219 throw new Error ( "错误的crontab表达式" ) ;
163220 }
221+ // 如果有nextruntime,则加入重试队列
222+ this . joinRetryList ( script ) ;
164223 let flag = false ;
165224 const cronJobList : Array < CronJob > = [ ] ;
166225 script . metadata . crontab . forEach ( ( val ) => {
0 commit comments