1919
2020 startPort , endPort int64
2121 nextPort int64
22+ daemonCtx context.Context
23+ daemonClose func ()
24+ daemonWG sync.WaitGroup
2225)
2326
27+ func CloseDaemons () {
28+ daemonLock .Lock ()
29+ if daemonCtx == nil {
30+ daemonLock .Unlock ()
31+ return
32+ }
33+ daemonLock .Unlock ()
34+
35+ daemonClose ()
36+ daemonWG .Wait ()
37+ }
38+
2439func (e * Engine ) getNextPort () int64 {
2540 if startPort == 0 {
2641 startPort = 10240
@@ -32,24 +47,52 @@ func (e *Engine) getNextPort() int64 {
3247 return startPort + nextPort
3348}
3449
50+ func getPath (instructions string ) (string , string ) {
51+ instructions = strings .TrimSpace (instructions )
52+ line := strings .TrimSpace (instructions )
53+
54+ if ! strings .HasPrefix (line , "(" ) {
55+ return instructions , ""
56+ }
57+
58+ line , rest , ok := strings .Cut (line [1 :], ")" )
59+ if ! ok {
60+ return instructions , ""
61+ }
62+
63+ path , value , ok := strings .Cut (strings .TrimSpace (line ), "=" )
64+ if ! ok || strings .TrimSpace (path ) != "path" {
65+ return instructions , ""
66+ }
67+
68+ return strings .TrimSpace (rest ), strings .TrimSpace (value )
69+ }
70+
3571func (e * Engine ) startDaemon (ctx context.Context , tool types.Tool ) (string , error ) {
3672 daemonLock .Lock ()
3773 defer daemonLock .Unlock ()
3874
75+ instructions := strings .TrimPrefix (tool .Instructions , types .DaemonPrefix )
76+ instructions , path := getPath (instructions )
77+
3978 port , ok := daemonPorts [tool .ID ]
40- url := fmt .Sprintf ("http://127.0.0.1:%d" , port )
79+ url := fmt .Sprintf ("http://127.0.0.1:%d%s " , port , path )
4180 if ok {
4281 return url , nil
4382 }
4483
84+ if daemonCtx == nil {
85+ daemonCtx , daemonClose = context .WithCancel (context .Background ())
86+ }
87+
88+ ctx = daemonCtx
4589 port = e .getNextPort ()
46- url = fmt .Sprintf ("http://127.0.0.1:%d" , port )
90+ url = fmt .Sprintf ("http://127.0.0.1:%d%s " , port , path )
4791
48- instructions := types .CommandPrefix + strings .TrimPrefix (tool .Instructions , types .DaemonPrefix )
4992 cmd , close , err := e .newCommand (ctx , []string {
5093 fmt .Sprintf ("PORT=%d" , port ),
5194 },
52- instructions ,
95+ types . CommandPrefix + instructions ,
5396 "{}" ,
5497 )
5598 if err != nil {
@@ -58,7 +101,7 @@ func (e *Engine) startDaemon(ctx context.Context, tool types.Tool) (string, erro
58101
59102 cmd .Stderr = os .Stderr
60103 cmd .Stdout = os .Stdout
61- log .Infof ("launched [%s] port [%d] %v" , tool .Name , port , cmd .Args )
104+ log .Infof ("launched [%s][%s] port [%d] %v" , tool .Name , tool . ID , port , cmd .Args )
62105 if err := cmd .Start (); err != nil {
63106 close ()
64107 return url , err
@@ -67,6 +110,7 @@ func (e *Engine) startDaemon(ctx context.Context, tool types.Tool) (string, erro
67110 if daemonPorts == nil {
68111 daemonPorts = map [string ]int64 {}
69112 }
113+ daemonPorts [tool .ID ] = port
70114
71115 killedCtx , cancel := context .WithCancelCause (ctx )
72116 defer cancel (nil )
@@ -85,13 +129,15 @@ func (e *Engine) startDaemon(ctx context.Context, tool types.Tool) (string, erro
85129 delete (daemonPorts , tool .ID )
86130 }()
87131
132+ daemonWG .Add (1 )
88133 context .AfterFunc (ctx , func () {
89134 if err := cmd .Process .Kill (); err != nil {
90135 log .Errorf ("daemon failed to kill tool [%s] process: %v" , tool .Name , err )
91136 }
137+ daemonWG .Done ()
92138 })
93139
94- for range 20 {
140+ for i := 0 ; i < 20 ; i ++ {
95141 resp , err := http .Get (url )
96142 if err == nil && resp .StatusCode == http .StatusOK {
97143 defer func () {
@@ -112,7 +158,7 @@ func (e *Engine) startDaemon(ctx context.Context, tool types.Tool) (string, erro
112158 return url , fmt .Errorf ("timeout waiting for 200 response from GET %s" , url )
113159}
114160
115- func (e * Engine ) runDaemon (ctx context.Context , tool types.Tool , input string ) (cmdRet * Return , cmdErr error ) {
161+ func (e * Engine ) runDaemon (ctx context.Context , prg * types. Program , tool types.Tool , input string ) (cmdRet * Return , cmdErr error ) {
116162 url , err := e .startDaemon (ctx , tool )
117163 if err != nil {
118164 return nil , err
@@ -121,5 +167,5 @@ func (e *Engine) runDaemon(ctx context.Context, tool types.Tool, input string) (
121167 tool .Instructions = strings .Join (append ([]string {
122168 types .CommandPrefix + url ,
123169 }, strings .Split (tool .Instructions , "\n " )[1 :]... ), "\n " )
124- return e .runHTTP (ctx , tool , input )
170+ return e .runHTTP (ctx , prg , tool , input )
125171}
0 commit comments