19
19
20
20
startPort , endPort int64
21
21
nextPort int64
22
+ daemonCtx context.Context
23
+ daemonClose func ()
24
+ daemonWG sync.WaitGroup
22
25
)
23
26
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
+
24
39
func (e * Engine ) getNextPort () int64 {
25
40
if startPort == 0 {
26
41
startPort = 10240
@@ -32,24 +47,52 @@ func (e *Engine) getNextPort() int64 {
32
47
return startPort + nextPort
33
48
}
34
49
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
+
35
71
func (e * Engine ) startDaemon (ctx context.Context , tool types.Tool ) (string , error ) {
36
72
daemonLock .Lock ()
37
73
defer daemonLock .Unlock ()
38
74
75
+ instructions := strings .TrimPrefix (tool .Instructions , types .DaemonPrefix )
76
+ instructions , path := getPath (instructions )
77
+
39
78
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 )
41
80
if ok {
42
81
return url , nil
43
82
}
44
83
84
+ if daemonCtx == nil {
85
+ daemonCtx , daemonClose = context .WithCancel (context .Background ())
86
+ }
87
+
88
+ ctx = daemonCtx
45
89
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 )
47
91
48
- instructions := types .CommandPrefix + strings .TrimPrefix (tool .Instructions , types .DaemonPrefix )
49
92
cmd , close , err := e .newCommand (ctx , []string {
50
93
fmt .Sprintf ("PORT=%d" , port ),
51
94
},
52
- instructions ,
95
+ types . CommandPrefix + instructions ,
53
96
"{}" ,
54
97
)
55
98
if err != nil {
@@ -58,7 +101,7 @@ func (e *Engine) startDaemon(ctx context.Context, tool types.Tool) (string, erro
58
101
59
102
cmd .Stderr = os .Stderr
60
103
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 )
62
105
if err := cmd .Start (); err != nil {
63
106
close ()
64
107
return url , err
@@ -67,6 +110,7 @@ func (e *Engine) startDaemon(ctx context.Context, tool types.Tool) (string, erro
67
110
if daemonPorts == nil {
68
111
daemonPorts = map [string ]int64 {}
69
112
}
113
+ daemonPorts [tool .ID ] = port
70
114
71
115
killedCtx , cancel := context .WithCancelCause (ctx )
72
116
defer cancel (nil )
@@ -85,13 +129,15 @@ func (e *Engine) startDaemon(ctx context.Context, tool types.Tool) (string, erro
85
129
delete (daemonPorts , tool .ID )
86
130
}()
87
131
132
+ daemonWG .Add (1 )
88
133
context .AfterFunc (ctx , func () {
89
134
if err := cmd .Process .Kill (); err != nil {
90
135
log .Errorf ("daemon failed to kill tool [%s] process: %v" , tool .Name , err )
91
136
}
137
+ daemonWG .Done ()
92
138
})
93
139
94
- for range 20 {
140
+ for i := 0 ; i < 20 ; i ++ {
95
141
resp , err := http .Get (url )
96
142
if err == nil && resp .StatusCode == http .StatusOK {
97
143
defer func () {
@@ -112,7 +158,7 @@ func (e *Engine) startDaemon(ctx context.Context, tool types.Tool) (string, erro
112
158
return url , fmt .Errorf ("timeout waiting for 200 response from GET %s" , url )
113
159
}
114
160
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 ) {
116
162
url , err := e .startDaemon (ctx , tool )
117
163
if err != nil {
118
164
return nil , err
@@ -121,5 +167,5 @@ func (e *Engine) runDaemon(ctx context.Context, tool types.Tool, input string) (
121
167
tool .Instructions = strings .Join (append ([]string {
122
168
types .CommandPrefix + url ,
123
169
}, strings .Split (tool .Instructions , "\n " )[1 :]... ), "\n " )
124
- return e .runHTTP (ctx , tool , input )
170
+ return e .runHTTP (ctx , prg , tool , input )
125
171
}
0 commit comments