-
Notifications
You must be signed in to change notification settings - Fork 480
Expand file tree
/
Copy pathoptions.go
More file actions
345 lines (278 loc) · 8.32 KB
/
Copy pathoptions.go
File metadata and controls
345 lines (278 loc) · 8.32 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
package frankenphp
import (
"context"
"fmt"
"log/slog"
"net/http"
"time"
)
// defaultMaxConsecutiveFailures is the default maximum number of consecutive failures before panicking
const defaultMaxConsecutiveFailures = 6
// Option instances allow to configure FrankenPHP.
type Option func(h *opt) error
// WorkerOption instances allow configuring FrankenPHP worker.
type WorkerOption func(*workerOpt) error
// ServerOption instances allow configuring a server.
type ServerOption func(*Server) error
// opt contains the available options.
//
// If you change this, also update the Caddy module and the documentation.
type opt struct {
hotReloadOpt
ctx context.Context
numThreads int
maxThreads int
workers []workerOpt
logger *slog.Logger
metrics Metrics
phpIni map[string]string
maxWaitTime time.Duration
maxIdleTime time.Duration
maxRequests int
servers []*Server
}
type workerOpt struct {
mercureContext
name string
fileName string
num int
maxThreads int
env PreparedEnv
requestOptions []RequestOption
watch []string
matchRequest func(*http.Request) bool
maxConsecutiveFailures int
extensionWorkers *extensionWorkers
onThreadReady func(int)
onThreadShutdown func(int)
onServerStartup func()
onServerShutdown func()
server *Server
}
// WithContext sets the main context to use.
func WithContext(ctx context.Context) Option {
return func(h *opt) error {
h.ctx = ctx
return nil
}
}
// WithNumThreads configures the number of PHP threads to start.
func WithNumThreads(numThreads int) Option {
return func(o *opt) error {
o.numThreads = numThreads
return nil
}
}
func WithMaxThreads(maxThreads int) Option {
return func(o *opt) error {
o.maxThreads = maxThreads
return nil
}
}
func WithMetrics(m Metrics) Option {
return func(o *opt) error {
o.metrics = m
return nil
}
}
// WithWorkers configures the PHP workers to start
func WithWorkers(name, fileName string, num int, options ...WorkerOption) Option {
return func(o *opt) error {
worker := workerOpt{
name: name,
fileName: fileName,
num: num,
env: PrepareEnv(nil),
watch: []string{},
maxConsecutiveFailures: defaultMaxConsecutiveFailures,
}
for _, option := range options {
if err := option(&worker); err != nil {
return err
}
}
o.workers = append(o.workers, worker)
return nil
}
}
// EXPERIMENTAL: WithExtensionWorkers allow extensions to create workers.
//
// A worker script with the provided name, fileName and thread count will be registered, along with additional
// configuration through WorkerOptions.
//
// Workers are designed to run indefinitely and will be gracefully shut down when FrankenPHP shuts down.
//
// Extension workers receive the lowest priority when determining thread allocations. If the requested number of threads
// cannot be allocated, then FrankenPHP will panic and provide this information to the user (who will need to allocate
// more total threads). Don't be greedy.
func WithExtensionWorkers(name, fileName string, numThreads int, options ...WorkerOption) (Workers, Option) {
w := &extensionWorkers{
name: name,
fileName: fileName,
num: numThreads,
}
w.options = append(options, withExtensionWorkers(w))
return w, WithWorkers(w.name, w.fileName, w.num, w.options...)
}
// WithLogger configures the global logger to use.
func WithLogger(l *slog.Logger) Option {
return func(o *opt) error {
o.logger = l
return nil
}
}
// WithPhpIni configures user defined PHP ini settings.
func WithPhpIni(overrides map[string]string) Option {
return func(o *opt) error {
o.phpIni = overrides
return nil
}
}
// WithMaxWaitTime configures the max time a request may be stalled waiting for a thread.
func WithMaxWaitTime(maxWaitTime time.Duration) Option {
return func(o *opt) error {
o.maxWaitTime = maxWaitTime
return nil
}
}
// WithMaxIdleTime configures the max time an autoscaled thread may be idle before being deactivated.
func WithMaxIdleTime(maxIdleTime time.Duration) Option {
return func(o *opt) error {
o.maxIdleTime = maxIdleTime
return nil
}
}
// EXPERIMENTAL: WithMaxRequests sets the default max requests before restarting a PHP thread (0 = unlimited). Applies to regular and worker threads.
func WithMaxRequests(maxRequests int) Option {
return func(o *opt) error {
o.maxRequests = maxRequests
return nil
}
}
// WithWorkerEnv sets environment variables for the worker
func WithWorkerEnv(env map[string]string) WorkerOption {
return func(w *workerOpt) error {
w.env = PrepareEnv(env)
return nil
}
}
// WithWorkerRequestOptions sets options for the main dummy request created for the worker
func WithWorkerRequestOptions(options ...RequestOption) WorkerOption {
return func(w *workerOpt) error {
w.requestOptions = append(w.requestOptions, options...)
return nil
}
}
// WithWorkerMaxThreads sets the max number of threads for this specific worker
func WithWorkerMaxThreads(num int) WorkerOption {
return func(w *workerOpt) error {
w.maxThreads = num
return nil
}
}
// WithWorkerWatchMode sets directories to watch for file changes
func WithWorkerWatchMode(watch []string) WorkerOption {
return func(w *workerOpt) error {
w.watch = watch
return nil
}
}
// WithWorkerMatcher sets a request matcher for this worker
// if the matcher returns true, the worker will be used to handle the request
// if no request matcher is set, matching happens only by path (filename == root + request path)
func WithWorkerMatcher(matcherFunc func(*http.Request) bool) WorkerOption {
return func(w *workerOpt) error {
w.matchRequest = matcherFunc
return nil
}
}
// WithWorkerServerScope scopes the worker to a server instance.
// Only requests that are handled by the server instance will reach the worker.
func WithWorkerServerScope(s *Server) WorkerOption {
return func(w *workerOpt) error {
w.server = s
return nil
}
}
// WithWorkerMaxFailures sets the maximum number of consecutive failures before panicking
func WithWorkerMaxFailures(maxFailures int) WorkerOption {
return func(w *workerOpt) error {
if maxFailures < -1 {
return fmt.Errorf("max consecutive failures must be >= -1, got %d", maxFailures)
}
w.maxConsecutiveFailures = maxFailures
return nil
}
}
func WithWorkerOnReady(f func(int)) WorkerOption {
return func(w *workerOpt) error {
w.onThreadReady = f
return nil
}
}
func WithWorkerOnShutdown(f func(int)) WorkerOption {
return func(w *workerOpt) error {
w.onThreadShutdown = f
return nil
}
}
// WithWorkerOnServerStartup adds a function to be called right after server startup. Useful for extensions.
func WithWorkerOnServerStartup(f func()) WorkerOption {
return func(w *workerOpt) error {
w.onServerStartup = f
return nil
}
}
// WithWorkerOnServerShutdown adds a function to be called right before server shutdown. Useful for extensions.
func WithWorkerOnServerShutdown(f func()) WorkerOption {
return func(w *workerOpt) error {
w.onServerShutdown = f
return nil
}
}
func withExtensionWorkers(w *extensionWorkers) WorkerOption {
return func(wo *workerOpt) error {
wo.extensionWorkers = w
return nil
}
}
// WithServer starts FrankenPHP with the given Server instance.
// After registering, it will be possible to call Server.ServeHTTP()
func WithServer(s *Server) Option {
return func(o *opt) error {
o.servers = append(o.servers, s)
return nil
}
}
// WithServerName sets the name of the server.
func WithServerName(name string) ServerOption {
return func(s *Server) error {
s.name = name
s.configuredName = name
return nil
}
}
// WithServerLogger sets the logger for the server.
func WithServerLogger(l *slog.Logger) ServerOption {
return func(s *Server) error {
s.logger = l
return nil
}
}
// WIthServerSplitPath sets the split path for the server.
func WithServerSplitPath(splitPath []string) ServerOption {
return func(s *Server) error {
if err := normalizeSplitPath(splitPath); err != nil {
return err
}
s.splitPath = splitPath
return nil
}
}
// WithServerEnv sets the env for the server.
func WithServerEnv(env map[string]string) ServerOption {
return func(s *Server) error {
s.env = PrepareEnv(env)
return nil
}
}