adds working implementation.

This commit is contained in:
Alliballibaba
2025-12-01 23:37:35 +01:00
parent 4969a4bdb6
commit 75f658bc8e
8 changed files with 96 additions and 1 deletions

View File

@@ -147,7 +147,7 @@ func parseWorkerConfig(d *caddyfile.Dispenser) (workerConfig, error) {
wc.MaxConsecutiveFailures = v
default:
return wc, wrongSubDirectiveError("worker", "name, file, num, env, watch, match, max_consecutive_failures, max_threads", v)
return wc, wrongSubDirectiveError("worker", "name, file, num, env, watch, match, max_consecutive_failures, max_threads, http_disabled", v)
}
}

View File

@@ -494,6 +494,25 @@ PHP_FUNCTION(frankenphp_handle_request) {
RETURN_TRUE;
}
PHP_FUNCTION(frankenphp_send_request) {
zval *zv;
char *worker_name = NULL;
size_t worker_name_len = 0;
ZEND_PARSE_PARAMETERS_START(1, 2);
Z_PARAM_ZVAL(zv);
Z_PARAM_OPTIONAL
Z_PARAM_STRING(worker_name, worker_name_len);
ZEND_PARSE_PARAMETERS_END();
char *error = go_frankenphp_send_request(thread_index, zv, worker_name,
worker_name_len);
if (error) {
zend_throw_exception(spl_ce_RuntimeException, error, 0);
RETURN_THROWS();
}
}
PHP_FUNCTION(headers_send) {
zend_long response_code = 200;

View File

@@ -4,6 +4,8 @@
function frankenphp_handle_request(callable $callback): bool {}
function frankenphp_send_request(mixed $message, string $workerName = ""): bool {}
function headers_send(int $status = 200): int {}
function frankenphp_finish_request(): bool {}

View File

@@ -5,6 +5,11 @@ ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_frankenphp_handle_request, 0, 1,
ZEND_ARG_TYPE_INFO(0, callback, IS_CALLABLE, 0)
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_frankenphp_send_request, 0, 1, IS_VOID, 0)
ZEND_ARG_TYPE_INFO(0, message, IS_MIXED, 0)
ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, worker_name, IS_STRING, 0, "\"\"")
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_headers_send, 0, 0, IS_LONG, 0)
ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, status, IS_LONG, 0, "200")
ZEND_END_ARG_INFO()
@@ -37,6 +42,7 @@ ZEND_END_ARG_INFO()
ZEND_FUNCTION(frankenphp_handle_request);
ZEND_FUNCTION(frankenphp_send_request);
ZEND_FUNCTION(headers_send);
ZEND_FUNCTION(frankenphp_finish_request);
ZEND_FUNCTION(frankenphp_request_headers);
@@ -46,6 +52,7 @@ ZEND_FUNCTION(mercure_publish);
static const zend_function_entry ext_functions[] = {
ZEND_FE(frankenphp_handle_request, arginfo_frankenphp_handle_request)
ZEND_FE(frankenphp_send_request, arginfo_frankenphp_send_request)
ZEND_FE(headers_send, arginfo_headers_send)
ZEND_FE(frankenphp_finish_request, arginfo_frankenphp_finish_request)
ZEND_FALIAS(fastcgi_finish_request, frankenphp_finish_request, arginfo_fastcgi_finish_request)

7
testdata/request-receiver.php vendored Normal file
View File

@@ -0,0 +1,7 @@
<?php
while (frankenphp_handle_request(function ($message) {
echo $message;
})) {
// keep handling requests
}

8
testdata/request-sender.php vendored Normal file
View File

@@ -0,0 +1,8 @@
<?php
$message = $_GET["message"];
$workerName = $_GET["workerName"] ?? '';
frankenphp_send_request($message, $workerName);
echo "request sent";

View File

@@ -125,6 +125,12 @@ func setupWorkerScript(handler *workerThread, worker *worker) {
if globalLogger.Enabled(ctx, slog.LevelDebug) {
globalLogger.LogAttrs(ctx, slog.LevelDebug, "starting", slog.String("worker", worker.name), slog.Int("thread", handler.thread.threadIndex))
}
// non-http worker: instantly mark as ready
if !worker.httpEnabled {
handler.isBootingScript = false
handler.thread.state.Set(state.Ready)
}
}
func tearDownWorkerScript(handler *workerThread, exitStatus int) {

View File

@@ -4,6 +4,7 @@ package frankenphp
import "C"
import (
"fmt"
"log/slog"
"os"
"path/filepath"
"runtime"
@@ -324,3 +325,48 @@ func (worker *worker) handleRequest(ch contextHolder) error {
}
}
}
//export go_frankenphp_send_request
func go_frankenphp_send_request(threadIndex C.uintptr_t, zv *C.zval, name *C.char, nameLen C.size_t) *C.char {
var w *worker
if nameLen != 0 {
w = getWorkerByName(C.GoStringN(name, C.int(nameLen)))
} else {
for _, worker := range workers {
if !worker.httpEnabled {
w = worker
break
}
}
}
if w == nil {
return phpThreads[threadIndex].pinCString("No worker found to handle this task: " + C.GoStringN(name, C.int(nameLen)))
}
message, err := goValue[any](zv)
if err != nil {
return phpThreads[threadIndex].pinCString("Failed to convert frankenphp_send_request() argument: " + err.Error())
}
fc := newFrankenPHPContext()
fc.logger = globalLogger
fc.worker = w
fc.responseWriter = nil
fc.handlerParameters = message
go func() {
err := w.handleRequest(contextHolder{phpThreads[threadIndex].context(), fc})
if err != nil && globalLogger.Enabled(globalCtx, slog.LevelError) {
globalLogger.LogAttrs(
globalCtx,
slog.LevelError,
"error while handling non-http message",
slog.String("error", err.Error()),
slog.String("worker", w.name),
)
}
}()
return nil
}