Skip to content

Commit 9b8d215

Browse files
committed
refactor: improve Worker public API and docs
1 parent 94e58eb commit 9b8d215

File tree

4 files changed

+57
-39
lines changed

4 files changed

+57
-39
lines changed

frankenphp.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -216,7 +216,7 @@ func Init(options ...Option) error {
216216

217217
// add registered external workers
218218
for _, ew := range extensionWorkers {
219-
options = append(options, WithWorkers(ew.Name(), ew.FileName(), ew.GetMinThreads(), WithWorkerEnv(ew.Env())))
219+
options = append(options, WithWorkers(ew.Name(), ew.FileName(), ew.MinThreads(), WithWorkerEnv(ew.Env())))
220220
}
221221

222222
opt := &opt{}

threadworker.go

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -47,26 +47,26 @@ func (handler *workerThread) beforeScriptExecution() string {
4747
switch handler.state.get() {
4848
case stateTransitionRequested:
4949
if handler.externalWorker != nil {
50-
handler.externalWorker.ThreadDeactivatedNotification(handler.thread.threadIndex)
50+
handler.externalWorker.OnServerShutdown(handler.thread.threadIndex)
5151
}
5252
handler.worker.detachThread(handler.thread)
5353
return handler.thread.transitionToNewHandler()
5454
case stateRestarting:
5555
if handler.externalWorker != nil {
56-
handler.externalWorker.ThreadDrainNotification(handler.thread.threadIndex)
56+
handler.externalWorker.OnShutdown(handler.thread.threadIndex)
5757
}
5858
handler.state.set(stateYielding)
5959
handler.state.waitFor(stateReady, stateShuttingDown)
6060
return handler.beforeScriptExecution()
6161
case stateReady, stateTransitionComplete:
6262
if handler.externalWorker != nil {
63-
handler.externalWorker.ThreadActivatedNotification(handler.thread.threadIndex)
63+
handler.externalWorker.OnReady(handler.thread.threadIndex)
6464
}
6565
setupWorkerScript(handler, handler.worker)
6666
return handler.worker.fileName
6767
case stateShuttingDown:
6868
if handler.externalWorker != nil {
69-
handler.externalWorker.ThreadDeactivatedNotification(handler.thread.threadIndex)
69+
handler.externalWorker.OnServerShutdown(handler.thread.threadIndex)
7070
}
7171
handler.worker.detachThread(handler.thread)
7272
// signal to stop

workerextension.go

Lines changed: 46 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -8,46 +8,57 @@ import (
88
"sync/atomic"
99
)
1010

11-
// EXPERIMENTAL: Worker allows you to register a worker where instead of calling FrankenPHP handlers on
12-
// frankenphp_handle_request(), the ProvideRequest method is called. You may provide a standard
13-
// http.Request that will be conferred to the underlying worker script.
11+
// EXPERIMENTAL: Worker allows you to register a worker where, instead of calling FrankenPHP handlers on
12+
// frankenphp_handle_request(), the GetRequest method is called.
13+
//
14+
// You may provide an http.Request that will be conferred to the underlying worker script,
15+
// or custom parameters that will be passed to frankenphp_handle_request().
16+
//
17+
// After the execution of frankenphp_handle_request(), the return value WorkerRequest.AfterFunc will be called,
18+
// with the optional return value of the callback passed as parameter.
1419
//
1520
// A worker script with the provided Name and FileName will be registered, along with the provided
16-
// configuration. You can also provide any environment variables that you want through Env. GetMinThreads allows you to
17-
// reserve a minimum number of threads from the frankenphp thread pool. This number must be positive.
18-
// These methods are only called once at startup, so register them in an init() function.
21+
// configuration. You can also provide any environment variables that you want through Env.
1922
//
20-
// When a thread is activated and nearly ready, ThreadActivatedNotification will be called with an opaque threadId;
21-
// this is a time for setting up any per-thread resources. When a thread is about to be returned to the thread pool,
22-
// you will receive a call to ThreadDrainNotification that will inform you of the threadId.
23-
// After the thread is returned to the thread pool, ThreadDeactivatedNotification will be called.
23+
// Name() and FileName() are only called once at startup, so register them in an init() function.
2424
//
25-
// Once you have at least one thread activated, you will receive calls to ProvideRequest where you should respond with
26-
// a request. FrankenPHP will automatically pipe these requests to the worker script and handle the response.
27-
// The piping process is designed to run indefinitely and will be gracefully shut down when FrankenPHP shuts down.
25+
// Workers are designed to run indefinitely and will be gracefully shut down when FrankenPHP shuts down.
2826
//
29-
// Note: External workers receive the lowest priority when determining thread allocations. If GetMinThreads cannot be
30-
// allocated, then frankenphp will panic and provide this information to the user (who will need to allocate more
27+
// Extension workers receive the lowest priority when determining thread allocations. If MinThreads cannot be
28+
// allocated, then FrankenPHP will panic and provide this information to the user (who will need to allocate more
3129
// total threads). Don't be greedy.
3230
type Worker interface {
31+
// Name returns the worker name
3332
Name() string
33+
// FileName returns the PHP script filename
3434
FileName() string
35+
// Env returns the environment variables available in the worker script.
3536
Env() PreparedEnv
36-
GetMinThreads() int
37-
ThreadActivatedNotification(threadId int)
38-
ThreadDrainNotification(threadId int)
39-
ThreadDeactivatedNotification(threadId int)
40-
ProvideRequest() *WorkerRequest
41-
InjectRequest(r *WorkerRequest)
37+
// MinThreads returns the minimum number of threads to reserve from the FrankenPHP thread pool.
38+
// This number must be positive.
39+
MinThreads() int
40+
// OnReady is called when the worker is assigned to a thread and receives an opaque thread ID as parameter.
41+
// This is a time for setting up any per-thread resources.
42+
OnReady(threadId int)
43+
// OnShutdown is called when the worker is shutting down and receives an opaque thread ID as parameter.
44+
// This is a time for cleaning up any per-thread resources.
45+
OnShutdown(threadId int)
46+
// OnServerShutdown is called when FrankenPHP is shutting down.
47+
OnServerShutdown(threadId int)
48+
// GetRequest is called once at least one thread is ready.
49+
// The returned request will be passed to the worker script.
50+
GetRequest() *WorkerRequest
51+
// SendRequest sends a request to the worker script. The callback function of frankenphp_handle_request() will be called.
52+
SendRequest(r *WorkerRequest)
4253
}
4354

44-
// EXPERIMENTAL
55+
// EXPERIMENTAL: WorkerRequest represents a request to pass to a worker script.
4556
type WorkerRequest struct {
46-
// The request for your worker script to handle
57+
// Request is an optional HTTP request for your worker script to handle
4758
Request *http.Request
48-
// Response is a response writer that provides the output of the provided request, it must not be nil to access the request body
59+
// Response is an optional response writer that provides the output of the provided request, it must not be nil to access the request body
4960
Response http.ResponseWriter
50-
// CallbackParameters is an optional field that will be converted in PHP types and passed as parameter to the PHP callback
61+
// CallbackParameters is an optional field that will be converted in PHP types or left as-is if it's an unsafe.Pointer and passed as parameter to the PHP callback
5162
CallbackParameters any
5263
// AfterFunc is an optional function that will be called after the request is processed with the original value, the return of the PHP callback, converted in Go types, is passed as parameter
5364
AfterFunc func(callbackReturn any)
@@ -56,7 +67,7 @@ type WorkerRequest struct {
5667
var extensionWorkers = make(map[string]Worker)
5768
var extensionWorkersMutex sync.Mutex
5869

59-
// EXPERIMENTAL
70+
// EXPERIMENTAL: RegisterWorker registers a custom worker script.
6071
func RegisterWorker(worker Worker) {
6172
extensionWorkersMutex.Lock()
6273
defer extensionWorkersMutex.Unlock()
@@ -67,7 +78,7 @@ func RegisterWorker(worker Worker) {
6778
// startWorker creates a pipe from a worker to the main worker.
6879
func startWorker(w *worker, extensionWorker Worker, thread *phpThread) {
6980
for {
70-
rq := extensionWorker.ProvideRequest()
81+
rq := extensionWorker.GetRequest()
7182

7283
var fc *frankenPHPContext
7384
if rq.Request == nil {
@@ -107,6 +118,8 @@ func startWorker(w *worker, extensionWorker Worker, thread *phpThread) {
107118
}
108119
}
109120

121+
// EXPERIMENTAL: NewWorker creates a Worker instance to embed in a custom struct implementing the Worker interface.
122+
// The returned instance may be sufficient on its own for simple use cases.
110123
func NewWorker(name, fileName string, minThreads int, env PreparedEnv) Worker {
111124
return &defaultWorker{
112125
name: name,
@@ -141,27 +154,27 @@ func (w *defaultWorker) Env() PreparedEnv {
141154
return w.env
142155
}
143156

144-
func (w *defaultWorker) GetMinThreads() int {
157+
func (w *defaultWorker) MinThreads() int {
145158
return w.minThreads
146159
}
147160

148-
func (w *defaultWorker) ThreadActivatedNotification(_ int) {
161+
func (w *defaultWorker) OnReady(_ int) {
149162
w.activatedCount.Add(1)
150163
}
151164

152-
func (w *defaultWorker) ThreadDrainNotification(_ int) {
165+
func (w *defaultWorker) OnShutdown(_ int) {
153166
w.drainCount.Add(1)
154167
}
155168

156-
func (w *defaultWorker) ThreadDeactivatedNotification(_ int) {
169+
func (w *defaultWorker) OnServerShutdown(_ int) {
157170
w.drainCount.Add(-1)
158171
w.activatedCount.Add(-1)
159172
}
160173

161-
func (w *defaultWorker) ProvideRequest() *WorkerRequest {
174+
func (w *defaultWorker) GetRequest() *WorkerRequest {
162175
return <-w.requestChan
163176
}
164177

165-
func (w *defaultWorker) InjectRequest(r *WorkerRequest) {
178+
func (w *defaultWorker) SendRequest(r *WorkerRequest) {
166179
w.requestChan <- r
167180
}

workerextension_test.go

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,11 @@ type mockWorker struct {
1515
Worker
1616
}
1717

18+
func (*mockWorker) OnShutdown(threadId int) {
19+
//TODO implement me
20+
panic("implement me")
21+
}
22+
1823
func TestWorkerExtension(t *testing.T) {
1924
// Create a mock worker extension
2025
mockExt := &mockWorker{
@@ -50,7 +55,7 @@ func TestWorkerExtension(t *testing.T) {
5055
done := make(chan struct{})
5156

5257
// Inject the request into the worker through the extension
53-
mockExt.InjectRequest(&WorkerRequest{
58+
mockExt.SendRequest(&WorkerRequest{
5459
Request: req,
5560
Response: w,
5661
AfterFunc: func(callbackReturn any) {

0 commit comments

Comments
 (0)