mirror of
https://github.com/php/frankenphp.git
synced 2026-03-24 00:52:11 +01:00
adds working implementation.
This commit is contained in:
@@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
19
frankenphp.c
19
frankenphp.c
@@ -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;
|
||||
|
||||
|
||||
@@ -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 {}
|
||||
|
||||
@@ -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
7
testdata/request-receiver.php
vendored
Normal 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
8
testdata/request-sender.php
vendored
Normal file
@@ -0,0 +1,8 @@
|
||||
<?php
|
||||
|
||||
$message = $_GET["message"];
|
||||
$workerName = $_GET["workerName"] ?? '';
|
||||
|
||||
frankenphp_send_request($message, $workerName);
|
||||
|
||||
echo "request sent";
|
||||
@@ -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) {
|
||||
|
||||
46
worker.go
46
worker.go
@@ -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
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user