mirror of
https://github.com/php/frankenphp.git
synced 2026-03-24 00:52:11 +01:00
docs: update translations (#2216)
Translation updates for: extension-workers.md . --------- Co-authored-by: alexandre-daubois <2144837+alexandre-daubois@users.noreply.github.com> Co-authored-by: Alexandre Daubois <alex.daubois@gmail.com>
This commit is contained in:
committed by
GitHub
parent
d72a9ee9cb
commit
c1e30cd638
172
docs/cn/extension-workers.md
Normal file
172
docs/cn/extension-workers.md
Normal file
@@ -0,0 +1,172 @@
|
||||
# 扩展 Worker
|
||||
|
||||
扩展 Worker 使您的 [FrankenPHP 扩展](https://frankenphp.dev/docs/extensions/) 能够管理专用的 PHP 线程池,用于执行后台任务、处理异步事件或实现自定义协议。适用于队列系统、事件监听器、调度器等。
|
||||
|
||||
## 注册 Worker
|
||||
|
||||
### 静态注册
|
||||
|
||||
如果您的 worker 不需要用户配置(固定的脚本路径、固定的线程数),您可以直接在 `init()` 函数中注册 worker。
|
||||
|
||||
```go
|
||||
package myextension
|
||||
|
||||
import (
|
||||
"github.com/dunglas/frankenphp"
|
||||
"github.com/dunglas/frankenphp/caddy"
|
||||
)
|
||||
|
||||
// 与 worker 池通信的全局句柄
|
||||
var worker frankenphp.Workers
|
||||
|
||||
func init() {
|
||||
// 模块加载时注册 worker。
|
||||
worker = caddy.RegisterWorkers(
|
||||
"my-internal-worker", // 唯一名称
|
||||
"worker.php", // 脚本路径(相对于执行目录或绝对路径)
|
||||
2, // 固定线程数
|
||||
// 可选的生命周期钩子
|
||||
frankenphp.WithWorkerOnServerStartup(func() {
|
||||
// 全局设置逻辑...
|
||||
}),
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
### 在 Caddy 模块中(用户可配置)
|
||||
|
||||
如果您计划共享您的扩展(例如通用的队列或事件监听器),您应该将其封装在一个 Caddy 模块中。这允许用户通过 `Caddyfile` 配置脚本路径和线程数。这需要实现 `caddy.Provisioner` 接口并解析 Caddyfile ([查看示例](https://github.com/dunglas/frankenphp-queue/blob/989120d394d66dd6c8e2101cac73dd622fade334/caddy.go))。
|
||||
|
||||
### 在纯 Go 应用程序中(嵌入式)
|
||||
|
||||
如果您 [在没有 Caddy 的标准 Go 应用程序中嵌入 FrankenPHP](https://pkg.go.dev/github.com/dunglas/frankenphp#example-ServeHTTP),您可以在初始化选项时使用 `frankenphp.WithExtensionWorkers` 注册扩展 worker。
|
||||
|
||||
## 与 Worker 交互
|
||||
|
||||
一旦 worker 池激活,您就可以向其分派任务。这可以在 [导出到 PHP 的原生函数](https://frankenphp.dev/docs/extensions/#writing-the-extension) 中完成,也可以从任何 Go 逻辑中完成,例如 cron 调度器、事件监听器 (MQTT、Kafka) 或任何其他 goroutine。
|
||||
|
||||
### 无头模式:`SendMessage`
|
||||
|
||||
使用 `SendMessage` 将原始数据直接传递给您的 worker 脚本。这非常适合队列或简单命令。
|
||||
|
||||
#### 示例:一个异步队列扩展
|
||||
|
||||
```go
|
||||
// #include <Zend/zend_types.h>
|
||||
import "C"
|
||||
import (
|
||||
"context"
|
||||
"unsafe"
|
||||
"github.com/dunglas/frankenphp"
|
||||
)
|
||||
|
||||
//export_php:function my_queue_push(mixed $data): bool
|
||||
func my_queue_push(data *C.zval) bool {
|
||||
// 1. 确保 worker 已准备就绪
|
||||
if worker == nil {
|
||||
return false
|
||||
}
|
||||
|
||||
// 2. 分派给后台 worker
|
||||
_, err := worker.SendMessage(
|
||||
context.Background(), // 标准 Go 上下文
|
||||
unsafe.Pointer(data), // 要传递给 worker 的数据
|
||||
nil, // 可选的 http.ResponseWriter
|
||||
)
|
||||
|
||||
return err == nil
|
||||
}
|
||||
```
|
||||
|
||||
### HTTP 模拟:`SendRequest`
|
||||
|
||||
如果您的扩展需要调用一个期望标准 Web 环境(填充 `$_SERVER`、`$_GET` 等)的 PHP 脚本,请使用 `SendRequest`。
|
||||
|
||||
```go
|
||||
// #include <Zend/zend_types.h>
|
||||
import "C"
|
||||
import (
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"unsafe"
|
||||
"github.com/dunglas/frankenphp"
|
||||
)
|
||||
|
||||
//export_php:function my_worker_http_request(string $path): string
|
||||
func my_worker_http_request(path *C.zend_string) unsafe.Pointer {
|
||||
// 1. 准备请求和记录器
|
||||
url := frankenphp.GoString(unsafe.Pointer(path))
|
||||
req, _ := http.NewRequest("GET", url, http.NoBody)
|
||||
rr := httptest.NewRecorder()
|
||||
|
||||
// 2. 分派给 worker
|
||||
if err := worker.SendRequest(rr, req); err != nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
// 3. 返回捕获的响应
|
||||
return frankenphp.PHPString(rr.Body.String(), false)
|
||||
}
|
||||
```
|
||||
|
||||
## Worker 脚本
|
||||
|
||||
PHP worker 脚本在一个循环中运行,可以处理原始消息和 HTTP 请求。
|
||||
|
||||
```php
|
||||
<?php
|
||||
// 在同一个循环中处理原始消息和 HTTP 请求
|
||||
$handler = function ($payload = null) {
|
||||
// 情况 1:消息模式
|
||||
if ($payload !== null) {
|
||||
return "Received payload: " . $payload;
|
||||
}
|
||||
|
||||
// 情况 2:HTTP 模式(标准 PHP 超全局变量会被填充)
|
||||
echo "Hello from page: " . $_SERVER['REQUEST_URI'];
|
||||
};
|
||||
|
||||
while (frankenphp_handle_request($handler)) {
|
||||
gc_collect_cycles();
|
||||
}
|
||||
```
|
||||
|
||||
## 生命周期钩子
|
||||
|
||||
FrankenPHP 提供了钩子,用于在生命周期的特定点执行 Go 代码。
|
||||
|
||||
| 钩子类型 | 选项名称 | 签名 | 上下文与用例 |
|
||||
| :------- | :--------------------------- | :----------------------- | :--------------------------------------------------- |
|
||||
| **服务器** | `WithWorkerOnServerStartup` | `func()` | 全局设置。**只运行一次**。示例:连接到 NATS/Redis。 |
|
||||
| **服务器** | `WithWorkerOnServerShutdown` | `func()` | 全局清理。**只运行一次**。示例:关闭共享连接。 |
|
||||
| **线程** | `WithWorkerOnReady` | `func(threadID int)` | 每线程设置。在线程启动时调用。接收线程 ID。 |
|
||||
| **线程** | `WithWorkerOnShutdown` | `func(threadID int)` | 每线程清理。接收线程 ID。 |
|
||||
|
||||
### 示例
|
||||
|
||||
```go
|
||||
package myextension
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/dunglas/frankenphp"
|
||||
frankenphpCaddy "github.com/dunglas/frankenphp/caddy"
|
||||
)
|
||||
|
||||
func init() {
|
||||
workerHandle = frankenphpCaddy.RegisterWorkers(
|
||||
"my-worker", "worker.php", 2,
|
||||
|
||||
// 服务器启动(全局)
|
||||
frankenphp.WithWorkerOnServerStartup(func() {
|
||||
fmt.Println("扩展:服务器正在启动...")
|
||||
}),
|
||||
|
||||
// 线程就绪(每线程)
|
||||
// 注意:此函数接受一个表示线程 ID 的整数
|
||||
frankenphp.WithWorkerOnReady(func(id int) {
|
||||
fmt.Printf("扩展:Worker 线程 #%d 已就绪。\n", id)
|
||||
}),
|
||||
)
|
||||
}
|
||||
```
|
||||
172
docs/fr/extension-workers.md
Normal file
172
docs/fr/extension-workers.md
Normal file
@@ -0,0 +1,172 @@
|
||||
# Workers d'extension
|
||||
|
||||
Les Workers d'extension permettent à votre [extension FrankenPHP](https://frankenphp.dev/docs/extensions/) de gérer un pool dédié de threads PHP pour exécuter des tâches en arrière-plan, gérer des événements asynchrones ou implémenter des protocoles personnalisés. Cela se révèle utile pour les systèmes de files d'attente, les event listeners, les planificateurs, etc.
|
||||
|
||||
## Enregistrement du Worker
|
||||
|
||||
### Enregistrement statique
|
||||
|
||||
Si vous n'avez pas besoin de rendre le worker configurable par l'utilisateur (chemin de script fixe, nombre de threads fixe), vous pouvez simplement enregistrer le worker dans la fonction `init()`.
|
||||
|
||||
```go
|
||||
package myextension
|
||||
|
||||
import (
|
||||
"github.com/dunglas/frankenphp"
|
||||
"github.com/dunglas/frankenphp/caddy"
|
||||
)
|
||||
|
||||
// Handle global pour communiquer avec le pool de workers
|
||||
var worker frankenphp.Workers
|
||||
|
||||
func init() {
|
||||
// Enregistre le worker lorsque le module est chargé.
|
||||
worker = caddy.RegisterWorkers(
|
||||
"my-internal-worker", // Nom unique
|
||||
"worker.php", // Chemin du script (relatif à l'exécution ou absolu)
|
||||
2, // Nombre de threads fixe
|
||||
// Hooks de cycle de vie optionnels
|
||||
frankenphp.WithWorkerOnServerStartup(func() {
|
||||
// Logique de configuration globale...
|
||||
}),
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
### Dans un module Caddy (configurable par l'utilisateur)
|
||||
|
||||
Si vous prévoyez de partager votre extension (comme une file d'attente générique ou un écouteur d'événements), vous devriez l'envelopper dans un module Caddy. Cela permet aux utilisateurs de configurer le chemin du script et le nombre de threads via leur `Caddyfile`. Cela nécessite d'implémenter l'interface `caddy.Provisioner` et de parser le Caddyfile ([voir un exemple](https://github.com/dunglas/frankenphp-queue/blob/989120d394d66dd6c8e2101cac73dd622fade334/caddy.go)).
|
||||
|
||||
### Dans une application Go pure (intégration)
|
||||
|
||||
Si vous [intégrez FrankenPHP dans une application Go standard sans Caddy](https://pkg.go.dev/github.com/dunglas/frankenphp#example-ServeHTTP), vous pouvez enregistrer des workers d'extension en utilisant `frankenphp.WithExtensionWorkers` lors de l'initialisation des options.
|
||||
|
||||
## Interaction avec les Workers
|
||||
|
||||
Une fois le pool de workers actif, vous pouvez lui envoyer des tâches. Cela peut être fait à l'intérieur de [fonctions natives exportées vers PHP](https://frankenphp.dev/docs/extensions/#writing-the-extension), ou à partir de toute logique Go telle qu'un planificateur cron, un écouteur d'événements (MQTT, Kafka), ou toute autre goroutine.
|
||||
|
||||
### Mode sans tête : `SendMessage`
|
||||
|
||||
Utilisez `SendMessage` pour passer des données brutes directement à votre script worker. C'est idéal pour les files d'attente ou les commandes simples.
|
||||
|
||||
#### Exemple : Une extension de file d'attente asynchrone
|
||||
|
||||
```go
|
||||
// #include <Zend/zend_types.h>
|
||||
import "C"
|
||||
import (
|
||||
"context"
|
||||
"unsafe"
|
||||
"github.com/dunglas/frankenphp"
|
||||
)
|
||||
|
||||
//export_php:function my_queue_push(mixed $data): bool
|
||||
func my_queue_push(data *C.zval) bool {
|
||||
// 1. S'assurer que le worker est prêt
|
||||
if worker == nil {
|
||||
return false
|
||||
}
|
||||
|
||||
// 2. Envoyer au worker en arrière-plan
|
||||
_, err := worker.SendMessage(
|
||||
context.Background(), // Contexte Go standard
|
||||
unsafe.Pointer(data), // Données à passer au worker
|
||||
nil, // http.ResponseWriter optionnel
|
||||
)
|
||||
|
||||
return err == nil
|
||||
}
|
||||
```
|
||||
|
||||
### Émulation HTTP : `SendRequest`
|
||||
|
||||
Utilisez `SendRequest` si votre extension doit invoquer un script PHP qui s'attend à un environnement web standard (remplir `$_SERVER`, `$_GET`, etc.).
|
||||
|
||||
```go
|
||||
// #include <Zend/zend_types.h>
|
||||
import "C"
|
||||
import (
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"unsafe"
|
||||
"github.com/dunglas/frankenphp"
|
||||
)
|
||||
|
||||
//export_php:function my_worker_http_request(string $path): string
|
||||
func my_worker_http_request(path *C.zend_string) unsafe.Pointer {
|
||||
// 1. Préparer la requête et l'enregistreur
|
||||
url := frankenphp.GoString(unsafe.Pointer(path))
|
||||
req, _ := http.NewRequest("GET", url, http.NoBody)
|
||||
rr := httptest.NewRecorder()
|
||||
|
||||
// 2. Envoyer au worker
|
||||
if err := worker.SendRequest(rr, req); err != nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
// 3. Retourner la réponse capturée
|
||||
return frankenphp.PHPString(rr.Body.String(), false)
|
||||
}
|
||||
```
|
||||
|
||||
## Script Worker
|
||||
|
||||
Le script worker PHP s'exécute dans une boucle et peut gérer à la fois les messages bruts et les requêtes HTTP.
|
||||
|
||||
```php
|
||||
<?php
|
||||
// Gérer à la fois les messages bruts et les requêtes HTTP dans la même boucle
|
||||
$handler = function ($payload = null) {
|
||||
// Cas 1 : Mode Message
|
||||
if ($payload !== null) {
|
||||
return "Received payload: " . $payload;
|
||||
}
|
||||
|
||||
// Cas 2 : Mode HTTP (les superglobales PHP standards sont peuplées)
|
||||
echo "Hello from page: " . $_SERVER['REQUEST_URI'];
|
||||
};
|
||||
|
||||
while (frankenphp_handle_request($handler)) {
|
||||
gc_collect_cycles();
|
||||
}
|
||||
```
|
||||
|
||||
## Hooks de Cycle de Vie
|
||||
|
||||
FrankenPHP fournit des hooks pour exécuter du code Go à des points spécifiques du cycle de vie.
|
||||
|
||||
| Type de Hook | Nom de l'Option | Signature | Contexte et Cas d'Utilisation |
|
||||
| :--------- | :--------------------------- | :------------------- | :--------------------------------------------------------------------- |
|
||||
| **Serveur** | `WithWorkerOnServerStartup` | `func()` | Configuration globale. Exécuté **Une fois**. Exemple : Connexion à NATS/Redis. |
|
||||
| **Serveur** | `WithWorkerOnServerShutdown` | `func()` | Nettoyage global. Exécuté **Une fois**. Exemple : Fermeture des connexions partagées. |
|
||||
| **Thread** | `WithWorkerOnReady` | `func(threadID int)` | Configuration par thread. Appelé lorsqu'un thread démarre. Reçoit l'ID du Thread. |
|
||||
| **Thread** | `WithWorkerOnShutdown` | `func(threadID int)` | Nettoyage par thread. Reçoit l'ID du Thread. |
|
||||
|
||||
### Exemple
|
||||
|
||||
```go
|
||||
package myextension
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/dunglas/frankenphp"
|
||||
frankenphpCaddy "github.com/dunglas/frankenphp/caddy"
|
||||
)
|
||||
|
||||
func init() {
|
||||
workerHandle = frankenphpCaddy.RegisterWorkers(
|
||||
"my-worker", "worker.php", 2,
|
||||
|
||||
// Démarrage du Serveur (Global)
|
||||
frankenphp.WithWorkerOnServerStartup(func() {
|
||||
fmt.Println("Extension : Démarrage du serveur...")
|
||||
}),
|
||||
|
||||
// Thread Prêt (Par Thread)
|
||||
// Note : La fonction accepte un entier représentant l'ID du Thread
|
||||
frankenphp.WithWorkerOnReady(func(id int) {
|
||||
fmt.Printf("Extension : Le thread worker #%d est prêt.\n", id)
|
||||
}),
|
||||
)
|
||||
}
|
||||
```
|
||||
172
docs/ja/extension-workers.md
Normal file
172
docs/ja/extension-workers.md
Normal file
@@ -0,0 +1,172 @@
|
||||
# 拡張ワーカー
|
||||
|
||||
拡張ワーカーは、[FrankenPHP拡張機能](https://frankenphp.dev/docs/extensions/)がバックグラウンドタスクの実行、非同期イベントの処理、またはカスタムプロトコルの実装のために、PHPスレッドの専用プールを管理できるようにします。キューシステム、イベントリスナー、スケジューラーなどに役立ちます。
|
||||
|
||||
## ワーカーの登録
|
||||
|
||||
### 静的登録
|
||||
|
||||
ワーカーをユーザーが構成可能にする必要がない場合(固定スクリプトパス、固定スレッド数)、`init()` 関数でワーカーを登録するだけです。
|
||||
|
||||
```go
|
||||
package myextension
|
||||
|
||||
import (
|
||||
"github.com/dunglas/frankenphp"
|
||||
"github.com/dunglas/frankenphp/caddy"
|
||||
)
|
||||
|
||||
// ワーカープールと通信するためのグローバルハンドル
|
||||
var worker frankenphp.Workers
|
||||
|
||||
func init() {
|
||||
// モジュールがロードされたときにワーカーを登録します。
|
||||
worker = caddy.RegisterWorkers(
|
||||
"my-internal-worker", // ユニークな名前
|
||||
"worker.php", // スクリプトパス(実行場所からの相対パス、または絶対パス)
|
||||
2, // 固定スレッド数
|
||||
// オプションのライフサイクルフック
|
||||
frankenphp.WithWorkerOnServerStartup(func() {
|
||||
// グローバルなセットアップロジック...
|
||||
}),
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
### Caddyモジュール内 (ユーザーが構成可能)
|
||||
|
||||
拡張機能を共有する予定がある場合(一般的なキューやイベントリスナーなど)、Caddyモジュールにラップする必要があります。これにより、ユーザーは `Caddyfile` を介してスクリプトパスとスレッド数を構成できます([例を見る](https://github.com/dunglas/frankenphp-queue/blob/989120d394d66dd6c8e2101cac73dd622fade334/caddy.go))。
|
||||
|
||||
### 純粋なGoアプリケーション内 (組み込み)
|
||||
|
||||
[Caddyなしで標準GoアプリケーションにFrankenPHPを組み込む](https://pkg.go.dev/github.com/dunglas/frankenphp#example-ServeHTTP)場合、初期化オプションで `frankenphp.WithExtensionWorkers` を使用して拡張ワーカーを登録できます。
|
||||
|
||||
## ワーカーとの対話
|
||||
|
||||
ワーカープールがアクティブになったら、タスクをディスパッチできます。これは、[PHPにエクスポートされたネイティブ関数](https://frankenphp.dev/docs/extensions/#writing-the-extension)内、またはGoのロジック(cronスケジューラー、イベントリスナー(MQTT、Kafka)、その他のゴルーチンなど)から実行できます。
|
||||
|
||||
### ヘッドレスモード: `SendMessage`
|
||||
|
||||
`SendMessage` を使用して、生データをワーカーのスクリプトに直接渡します。これはキューや単純なコマンドに最適です。
|
||||
|
||||
#### 例: 非同期キュー拡張機能
|
||||
|
||||
```go
|
||||
// #include <Zend/zend_types.h>
|
||||
import "C"
|
||||
import (
|
||||
"context"
|
||||
"unsafe"
|
||||
"github.com/dunglas/frankenphp"
|
||||
)
|
||||
|
||||
//export_php:function my_queue_push(mixed $data): bool
|
||||
func my_queue_push(data *C.zval) bool {
|
||||
// 1. ワーカーが準備できていることを確認する
|
||||
if worker == nil {
|
||||
return false
|
||||
}
|
||||
|
||||
// 2. バックグラウンドワーカーにディスパッチする
|
||||
_, err := worker.SendMessage(
|
||||
context.Background(), // 標準のGoコンテキスト
|
||||
unsafe.Pointer(data), // ワーカーに渡すデータ
|
||||
nil, // オプションのhttp.ResponseWriter
|
||||
)
|
||||
|
||||
return err == nil
|
||||
}
|
||||
```
|
||||
|
||||
### HTTPエミュレーション: `SendRequest`
|
||||
|
||||
拡張機能が標準のウェブ環境(`$_SERVER`、`$_GET` など)を期待するPHPスクリプトを呼び出す必要がある場合は、`SendRequest` を使用します。
|
||||
|
||||
```go
|
||||
// #include <Zend/zend_types.h>
|
||||
import "C"
|
||||
import (
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"unsafe"
|
||||
"github.com/dunglas/frankenphp"
|
||||
)
|
||||
|
||||
//export_php:function my_worker_http_request(string $path): string
|
||||
func my_worker_http_request(path *C.zend_string) unsafe.Pointer {
|
||||
// 1. リクエストとレコーダーを準備する
|
||||
url := frankenphp.GoString(unsafe.Pointer(path))
|
||||
req, _ := http.NewRequest("GET", url, http.NoBody)
|
||||
rr := httptest.NewRecorder()
|
||||
|
||||
// 2. ワーカーにディスパッチする
|
||||
if err := worker.SendRequest(rr, req); err != nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
// 3. キャプチャされたレスポンスを返す
|
||||
return frankenphp.PHPString(rr.Body.String(), false)
|
||||
}
|
||||
```
|
||||
|
||||
## ワーカーのスクリプト
|
||||
|
||||
PHPワーカーのスクリプトはループで実行され、生メッセージとHTTPリクエストの両方を処理できます。
|
||||
|
||||
```php
|
||||
<?php
|
||||
// 同じループで生のメッセージとHTTPリクエストの両方を処理する
|
||||
$handler = function ($payload = null) {
|
||||
// ケース1: メッセージモード
|
||||
if ($payload !== null) {
|
||||
return "Received payload: " . $payload;
|
||||
}
|
||||
|
||||
// ケース2: HTTPモード(標準のPHPスーパーグローバルが設定される)
|
||||
echo "Hello from page: " . $_SERVER['REQUEST_URI'];
|
||||
};
|
||||
|
||||
while (frankenphp_handle_request($handler)) {
|
||||
gc_collect_cycles();
|
||||
}
|
||||
```
|
||||
|
||||
## ライフサイクルフック
|
||||
|
||||
FrankenPHPは、ライフサイクルの特定の時点でGoコードを実行するためのフックを提供します。
|
||||
|
||||
| フックタイプ | オプション名 | シグネチャ | コンテキストと使用例 |
|
||||
| :--------- | :-------------------------- | :------------------ | :--------------------------------------------------------------------- |
|
||||
| **サーバー** | `WithWorkerOnServerStartup` | `func()` | グローバルなセットアップ。**一度だけ**実行されます。例: NATS/Redisへの接続。 |
|
||||
| **サーバー** | `WithWorkerOnServerShutdown` | `func()` | グローバルなクリーンアップ。**一度だけ**実行されます。例: 共有接続のクローズ。 |
|
||||
| **スレッド** | `WithWorkerOnReady` | `func(threadID int)` | スレッドごとのセットアップ。スレッドが開始したときに呼び出されます。スレッドIDを受け取ります。 |
|
||||
| **スレッド** | `WithWorkerOnShutdown` | `func(threadID int)` | スレッドごとのクリーンアップ。スレッドIDを受け取ります。 |
|
||||
|
||||
### 例
|
||||
|
||||
```go
|
||||
package myextension
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/dunglas/frankenphp"
|
||||
frankenphpCaddy "github.com/dunglas/frankenphp/caddy"
|
||||
)
|
||||
|
||||
func init() {
|
||||
workerHandle = frankenphpCaddy.RegisterWorkers(
|
||||
"my-worker", "worker.php", 2,
|
||||
|
||||
// サーバー起動時 (グローバル)
|
||||
frankenphp.WithWorkerOnServerStartup(func() {
|
||||
fmt.Println("Extension: Server starting up...")
|
||||
}),
|
||||
|
||||
// スレッド準備完了時 (スレッドごと)
|
||||
// 注: この関数はスレッドIDを表す整数を受け入れます
|
||||
frankenphp.WithWorkerOnReady(func(id int) {
|
||||
fmt.Printf("Extension: Worker thread #%d is ready.\n", id)
|
||||
}),
|
||||
)
|
||||
}
|
||||
```
|
||||
172
docs/pt-br/extension-workers.md
Normal file
172
docs/pt-br/extension-workers.md
Normal file
@@ -0,0 +1,172 @@
|
||||
# Workers de Extensão
|
||||
|
||||
Os Workers de Extensão permitem que sua [extensão FrankenPHP](https://frankenphp.dev/docs/extensions/) gerencie um pool dedicado de threads PHP para executar tarefas em segundo plano, lidar com eventos assíncronos ou implementar protocolos personalizados. Útil para sistemas de fila, listeners de eventos, agendadores, etc.
|
||||
|
||||
## Registrando o Worker
|
||||
|
||||
### Registro Estático
|
||||
|
||||
Se você não precisa que o worker seja configurável pelo usuário (caminho de script fixo, número de threads fixo), você pode simplesmente registrar o worker na função `init()`.
|
||||
|
||||
```go
|
||||
package myextension
|
||||
|
||||
import (
|
||||
"github.com/dunglas/frankenphp"
|
||||
"github.com/dunglas/frankenphp/caddy"
|
||||
)
|
||||
|
||||
// Handle global para comunicar com o pool de workers
|
||||
var worker frankenphp.Workers
|
||||
|
||||
func init() {
|
||||
// Registra o worker quando o módulo é carregado.
|
||||
worker = caddy.RegisterWorkers(
|
||||
"my-internal-worker", // Nome único
|
||||
"worker.php", // Caminho do script (relativo à execução ou absoluto)
|
||||
2, // Contagem fixa de threads
|
||||
// Hooks de ciclo de vida opcionais
|
||||
frankenphp.WithWorkerOnServerStartup(func() {
|
||||
// Lógica de configuração global...
|
||||
}),
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
### Em um Módulo Caddy (Configurável pelo usuário)
|
||||
|
||||
Se você planeja compartilhar sua extensão (como uma fila genérica ou um listener de eventos), você deve encapsulá-la em um módulo Caddy. Isso permite que os usuários configurem o caminho do script e a contagem de threads através do seu `Caddyfile`. Isso exige a implementação da interface `caddy.Provisioner` e a análise do Caddyfile ([veja um exemplo](https://github.com/dunglas/frankenphp-queue/blob/989120d394d66dd6c8e2101cac73dd622fade334/caddy.go)).
|
||||
|
||||
### Em uma Aplicação Go Pura (Embedagem)
|
||||
|
||||
Se você está [embedando o FrankenPHP em uma aplicação Go padrão sem caddy](https://pkg.go.dev/github.com/dunglas/frankenphp#example-ServeHTTP), você pode registrar workers de extensão usando `frankenphp.WithExtensionWorkers` ao inicializar as opções.
|
||||
|
||||
## Interagindo com Workers
|
||||
|
||||
Assim que o pool de workers estiver ativo, você pode despachar tarefas para ele. Isso pode ser feito dentro de [funções nativas exportadas para PHP](https://frankenphp.dev/docs/extensions/#writing-the-extension), ou de qualquer lógica Go, como um agendador cron, um listener de eventos (MQTT, Kafka), ou qualquer outra goroutine.
|
||||
|
||||
### Modo Headless: `SendMessage`
|
||||
|
||||
Use `SendMessage` para passar dados brutos diretamente para o seu script worker. Isso é ideal para filas ou comandos simples.
|
||||
|
||||
#### Exemplo: Uma Extensão de Fila Assíncrona
|
||||
|
||||
```go
|
||||
// #include <Zend/zend_types.h>
|
||||
import "C"
|
||||
import (
|
||||
"context"
|
||||
"unsafe"
|
||||
"github.com/dunglas/frankenphp"
|
||||
)
|
||||
|
||||
//export_php:function my_queue_push(mixed $data): bool
|
||||
func my_queue_push(data *C.zval) bool {
|
||||
// 1. Garante que o worker esteja pronto
|
||||
if worker == nil {
|
||||
return false
|
||||
}
|
||||
|
||||
// 2. Despacha para o worker em segundo plano
|
||||
_, err := worker.SendMessage(
|
||||
context.Background(), // Contexto Go padrão
|
||||
unsafe.Pointer(data), // Dados a serem passados para o worker
|
||||
nil, // http.ResponseWriter opcional
|
||||
)
|
||||
|
||||
return err == nil
|
||||
}
|
||||
```
|
||||
|
||||
### Emulação HTTP: `SendRequest`
|
||||
|
||||
Use `SendRequest` se sua extensão precisar invocar um script PHP que espera um ambiente web padrão (populando `$_SERVER`, `$_GET`, etc.).
|
||||
|
||||
```go
|
||||
// #include <Zend/zend_types.h>
|
||||
import "C"
|
||||
import (
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"unsafe"
|
||||
"github.com/dunglas/frankenphp"
|
||||
)
|
||||
|
||||
//export_php:function my_worker_http_request(string $path): string
|
||||
func my_worker_http_request(path *C.zend_string) unsafe.Pointer {
|
||||
// 1. Prepara a requisição e o gravador
|
||||
url := frankenphp.GoString(unsafe.Pointer(path))
|
||||
req, _ := http.NewRequest("GET", url, http.NoBody)
|
||||
rr := httptest.NewRecorder()
|
||||
|
||||
// 2. Despacha para o worker
|
||||
if err := worker.SendRequest(rr, req); err != nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
// 3. Retorna a resposta capturada
|
||||
return frankenphp.PHPString(rr.Body.String(), false)
|
||||
}
|
||||
```
|
||||
|
||||
## Script do Worker
|
||||
|
||||
O script PHP do worker é executado em um loop e pode lidar tanto com mensagens brutas quanto com requisições HTTP.
|
||||
|
||||
```php
|
||||
<?php
|
||||
// Lida tanto com mensagens brutas quanto com requisições HTTP no mesmo loop
|
||||
$handler = function ($payload = null) {
|
||||
// Caso 1: Modo de Mensagem
|
||||
if ($payload !== null) {
|
||||
return "Received payload: " . $payload;
|
||||
}
|
||||
|
||||
// Caso 2: Modo HTTP (superglobais PHP padrão são populadas)
|
||||
echo "Hello from page: " . $_SERVER['REQUEST_URI'];
|
||||
};
|
||||
|
||||
while (frankenphp_handle_request($handler)) {
|
||||
gc_collect_cycles();
|
||||
}
|
||||
```
|
||||
|
||||
## Hooks de Ciclo de Vida
|
||||
|
||||
FrankenPHP oferece hooks para executar código Go em pontos específicos do ciclo de vida.
|
||||
|
||||
| Tipo de Hook | Nome da Opção | Assinatura | Contexto e Caso de Uso |
|
||||
| :--------- | :--------------------------- | :------------------- | :------------------------------------------------------------------------- |
|
||||
| **Servidor** | `WithWorkerOnServerStartup` | `func()` | Configuração global. Executado **Uma Vez**. Exemplo: Conectar ao NATS/Redis. |
|
||||
| **Servidor** | `WithWorkerOnServerShutdown` | `func()` | Limpeza global. Executado **Uma Vez**. Exemplo: Fechar conexões compartilhadas. |
|
||||
| **Thread** | `WithWorkerOnReady` | `func(threadID int)` | Configuração por thread. Chamado quando um thread inicia. Recebe o ID do Thread. |
|
||||
| **Thread** | `WithWorkerOnShutdown` | `func(threadID int)` | Limpeza por thread. Recebe o ID do Thread. |
|
||||
|
||||
### Exemplo
|
||||
|
||||
```go
|
||||
package myextension
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/dunglas/frankenphp"
|
||||
frankenphpCaddy "github.com/dunglas/frankenphp/caddy"
|
||||
)
|
||||
|
||||
func init() {
|
||||
workerHandle = frankenphpCaddy.RegisterWorkers(
|
||||
"my-worker", "worker.php", 2,
|
||||
|
||||
// Inicialização do Servidor (Global)
|
||||
frankenphp.WithWorkerOnServerStartup(func() {
|
||||
fmt.Println("Extensão: Servidor iniciando...")
|
||||
}),
|
||||
|
||||
// Thread Pronta (Por Thread)
|
||||
// Nota: A função aceita um inteiro representando o ID do Thread
|
||||
frankenphp.WithWorkerOnReady(func(id int) {
|
||||
fmt.Printf("Extensão: Thread worker #%d está pronta.\n", id)
|
||||
}),
|
||||
)
|
||||
}
|
||||
```
|
||||
172
docs/ru/extension-workers.md
Normal file
172
docs/ru/extension-workers.md
Normal file
@@ -0,0 +1,172 @@
|
||||
# Расширение Workers
|
||||
|
||||
Расширение Workers позволяет вашему [расширению FrankenPHP](https://frankenphp.dev/docs/extensions/) управлять выделенным пулом PHP-потоков для выполнения фоновых задач, обработки асинхронных событий или реализации пользовательских протоколов. Полезно для систем очередей, слушателей событий, планировщиков и т. д.
|
||||
|
||||
## Регистрация Worker-а
|
||||
|
||||
### Статическая регистрация
|
||||
|
||||
Если вам не нужно делать Worker-а настраиваемым пользователем (фиксированный путь к скрипту, фиксированное количество потоков), вы можете просто зарегистрировать Worker в функции `init()`.
|
||||
|
||||
```go
|
||||
package myextension
|
||||
|
||||
import (
|
||||
"github.com/dunglas/frankenphp"
|
||||
"github.com/dunglas/frankenphp/caddy"
|
||||
)
|
||||
|
||||
// Глобальный дескриптор для связи с пулом Worker-ов
|
||||
var worker frankenphp.Workers
|
||||
|
||||
func init() {
|
||||
// Зарегистрировать Worker при загрузке модуля.
|
||||
worker = caddy.RegisterWorkers(
|
||||
"my-internal-worker", // Уникальное имя
|
||||
"worker.php", // Путь к скрипту (относительный или абсолютный)
|
||||
2, // Фиксированное количество потоков
|
||||
// Дополнительные хуки жизненного цикла
|
||||
frankenphp.WithWorkerOnServerStartup(func() {
|
||||
// Глобальная логика настройки...
|
||||
}),
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
### В модуле Caddy (настраивается пользователем)
|
||||
|
||||
Если вы планируете делиться своим расширением (например, универсальной очередью или слушателем событий), вам следует обернуть его в модуль Caddy. Это позволит пользователям настраивать путь к скрипту и количество потоков через свой `Caddyfile`. Это требует реализации интерфейса `caddy.Provisioner` и парсинга Caddyfile ([см. пример](https://github.com/dunglas/frankenphp-queue/blob/989120d394d66dd6c8e2101cac73dd622fade334/caddy.go)).
|
||||
|
||||
### В чистом Go-приложении (встраивание)
|
||||
|
||||
Если вы [встраиваете FrankenPHP в стандартное Go-приложение без Caddy](https://pkg.go.dev/github.com/dunglas/frankenphp#example-ServeHTTP), вы можете зарегистрировать Worker-ы расширения, используя `frankenphp.WithExtensionWorkers` при инициализации опций.
|
||||
|
||||
## Взаимодействие с Worker-ами
|
||||
|
||||
Как только пул Worker-ов активен, вы можете отправлять ему задачи. Это можно сделать внутри [нативных функций, экспортированных в PHP](https://frankenphp.dev/docs/extensions/#writing-the-extension), или из любой Go-логики, такой как планировщик cron, слушатель событий (MQTT, Kafka) или любая другая горутина.
|
||||
|
||||
### Безголовый режим: `SendMessage`
|
||||
|
||||
Используйте `SendMessage` для прямой передачи необработанных данных вашему скрипту Worker-а. Это идеально подходит для очередей или простых команд.
|
||||
|
||||
#### Пример: Расширение асинхронной очереди
|
||||
|
||||
```go
|
||||
// #include <Zend/zend_types.h>
|
||||
import "C"
|
||||
import (
|
||||
"context"
|
||||
"unsafe"
|
||||
"github.com/dunglas/frankenphp"
|
||||
)
|
||||
|
||||
//export_php:function my_queue_push(mixed $data): bool
|
||||
func my_queue_push(data *C.zval) bool {
|
||||
// 1. Убедитесь, что Worker готов
|
||||
if worker == nil {
|
||||
return false
|
||||
}
|
||||
|
||||
// 2. Отправить фоновому Worker-у
|
||||
_, err := worker.SendMessage(
|
||||
context.Background(), // Стандартный Go-контекст
|
||||
unsafe.Pointer(data), // Данные для передачи Worker-у
|
||||
nil, // Опциональный http.ResponseWriter
|
||||
)
|
||||
|
||||
return err == nil
|
||||
}
|
||||
```
|
||||
|
||||
### Эмуляция HTTP: `SendRequest`
|
||||
|
||||
Используйте `SendRequest`, если ваше расширение должно вызвать PHP-скрипт, который ожидает стандартную веб-среду (заполнение `$_SERVER`, `$_GET` и т. д.).
|
||||
|
||||
```go
|
||||
// #include <Zend/zend_types.h>
|
||||
import "C"
|
||||
import (
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"unsafe"
|
||||
"github.com/dunglas/frankenphp"
|
||||
)
|
||||
|
||||
//export_php:function my_worker_http_request(string $path): string
|
||||
func my_worker_http_request(path *C.zend_string) unsafe.Pointer {
|
||||
// 1. Подготовьте запрос и рекордер
|
||||
url := frankenphp.GoString(unsafe.Pointer(path))
|
||||
req, _ := http.NewRequest("GET", url, http.NoBody)
|
||||
rr := httptest.NewRecorder()
|
||||
|
||||
// 2. Отправить Worker-у
|
||||
if err := worker.SendRequest(rr, req); err != nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
// 3. Вернуть захваченный ответ
|
||||
return frankenphp.PHPString(rr.Body.String(), false)
|
||||
}
|
||||
```
|
||||
|
||||
## Скрипт Worker-а
|
||||
|
||||
PHP-скрипт Worker-а выполняется в цикле и может обрабатывать как необработанные сообщения, так и HTTP-запросы.
|
||||
|
||||
```php
|
||||
<?php
|
||||
// Обрабатывать как необработанные сообщения, так и HTTP-запросы в одном цикле
|
||||
$handler = function ($payload = null) {
|
||||
// Случай 1: Режим сообщений
|
||||
if ($payload !== null) {
|
||||
return "Received payload: " . $payload;
|
||||
}
|
||||
|
||||
// Случай 2: Режим HTTP (заполняются стандартные суперглобальные переменные PHP)
|
||||
echo "Hello from page: " . $_SERVER['REQUEST_URI'];
|
||||
};
|
||||
|
||||
while (frankenphp_handle_request($handler)) {
|
||||
gc_collect_cycles();
|
||||
}
|
||||
```
|
||||
|
||||
## Хуки жизненного цикла
|
||||
|
||||
FrankenPHP предоставляет хуки для выполнения Go-кода в определенные моменты жизненного цикла.
|
||||
|
||||
| Тип хука | Имя опции | Подпись | Контекст и вариант использования |
|
||||
| :-------- | :--------------------------- | :------------------- | :-------------------------------------------------------------------- |
|
||||
| **Сервер** | `WithWorkerOnServerStartup` | `func()` | Глобальная настройка. Выполняется **один раз**. Пример: Подключение к NATS/Redis. |
|
||||
| **Сервер** | `WithWorkerOnServerShutdown` | `func()` | Глобальная очистка. Выполняется **один раз**. Пример: Закрытие общих соединений. |
|
||||
| **Поток** | `WithWorkerOnReady` | `func(threadID int)` | Настройка для каждого потока. Вызывается при запуске потока. Получает ID потока. |
|
||||
| **Поток** | `WithWorkerOnShutdown` | `func(threadID int)` | Очистка для каждого потока. Получает ID потока. |
|
||||
|
||||
### Пример
|
||||
|
||||
```go
|
||||
package myextension
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/dunglas/frankenphp"
|
||||
frankenphpCaddy "github.com/dunglas/frankenphp/caddy"
|
||||
)
|
||||
|
||||
func init() {
|
||||
workerHandle = frankenphpCaddy.RegisterWorkers(
|
||||
"my-worker", "worker.php", 2,
|
||||
|
||||
// Запуск сервера (Глобальный)
|
||||
frankenphp.WithWorkerOnServerStartup(func() {
|
||||
fmt.Println("Extension: Server starting up...")
|
||||
}),
|
||||
|
||||
// Поток готов (Для каждого потока)
|
||||
// Примечание: Функция принимает целое число, представляющее ID потока
|
||||
frankenphp.WithWorkerOnReady(func(id int) {
|
||||
fmt.Printf("Extension: Worker thread #%d is ready.\n", id)
|
||||
}),
|
||||
)
|
||||
}
|
||||
```
|
||||
171
docs/tr/extension-workers.md
Normal file
171
docs/tr/extension-workers.md
Normal file
@@ -0,0 +1,171 @@
|
||||
# Uzantı İşçileri
|
||||
|
||||
Uzantı İşçileri, [FrankenPHP uzantınızın](https://frankenphp.dev/docs/extensions/) arka plan görevlerini yürütmek, eşzamansız olayları işlemek veya özel protokolleri uygulamak için özel bir PHP iş parçacığı havuzunu yönetmesini sağlar. Kuyruk sistemleri, olay dinleyicileri, zamanlayıcılar vb. için kullanışlıdır.
|
||||
|
||||
## İşçiyi Kaydetme
|
||||
|
||||
### Statik Kayıt
|
||||
|
||||
İşçiyi kullanıcı tarafından yapılandırılabilir hale getirmeniz gerekmiyorsa (sabit komut dosyası yolu, sabit iş parçacığı sayısı), işçiyi `init()` fonksiyonunda basitçe kaydedebilirsiniz.
|
||||
|
||||
```go
|
||||
package myextension
|
||||
|
||||
import (
|
||||
"github.com/dunglas/frankenphp"
|
||||
"github.com/dunglas/frankenphp/caddy"
|
||||
)
|
||||
|
||||
// İşçi havuzuyla iletişim kurmak için genel tanıtıcı
|
||||
var worker frankenphp.Workers
|
||||
|
||||
func init() {
|
||||
// Modül yüklendiğinde işçiyi kaydet.
|
||||
worker = caddy.RegisterWorkers(
|
||||
"my-internal-worker", // Benzersiz isim
|
||||
"worker.php", // Komut dosyası yolu (çalışmaya göre veya mutlak)
|
||||
2, // Sabit iş parçacığı sayısı
|
||||
// İsteğe bağlı Yaşam Döngüsü Kancaları
|
||||
frankenphp.WithWorkerOnServerStartup(func() {
|
||||
// Genel kurulum mantığı...
|
||||
}),
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
### Bir Caddy Modülünde (Kullanıcı tarafından yapılandırılabilir)
|
||||
|
||||
Uzantınızı paylaşmayı planlıyorsanız (genel bir kuyruk veya olay dinleyici gibi), onu bir Caddy modülüne sarmalısınız. Bu, kullanıcıların `Caddyfile` aracılığıyla komut dosyası yolunu ve iş parçacığı sayısını yapılandırmasına olanak tanır. Bu, `caddy.Provisioner` arayüzünü uygulamayı ve Caddyfile'ı ayrıştırmayı gerektirir ([bir örnek görmek için](https://github.com/dunglas/frankenphp-queue/blob/989120d394d66dd6c8e2101cac73dd622fade334/caddy.go)).
|
||||
|
||||
### Saf Bir Go Uygulamasında (Gömme)
|
||||
|
||||
FrankenPHP'yi [Caddy olmadan standart bir Go uygulamasına gömüyorsanız](https://pkg.go.dev/github.com/dunglas/frankenphp#example-ServeHTTP), seçenekleri başlatırken `frankenphp.WithExtensionWorkers` kullanarak uzantı işçilerini kaydedebilirsiniz.
|
||||
|
||||
## İşçilerle Etkileşim Kurma
|
||||
|
||||
İşçi havuzu aktif hale geldiğinde, ona görevler gönderebilirsiniz. Bu, [PHP'ye dışa aktarılan yerel fonksiyonlar](https://frankenphp.dev/docs/extensions/#writing-the-extension) içinde veya bir cron zamanlayıcı, bir olay dinleyicisi (MQTT, Kafka) veya herhangi başka bir goroutine gibi herhangi bir Go mantığından yapılabilir.
|
||||
|
||||
### Başsız Mod : `SendMessage`
|
||||
|
||||
Doğrudan işçi komut dosyanıza ham veri geçirmek için `SendMessage` kullanın. Bu, kuyruklar veya basit komutlar için idealdir.
|
||||
|
||||
#### Örnek: Asenkron Bir Kuyruk Uzantısı
|
||||
|
||||
```go
|
||||
// #include <Zend/zend_types.h>
|
||||
import "C"
|
||||
import (
|
||||
"context"
|
||||
"unsafe"
|
||||
"github.com/dunglas/frankenphp"
|
||||
)
|
||||
|
||||
//export_php:function my_queue_push(mixed $data): bool
|
||||
func my_queue_push(data *C.zval) bool {
|
||||
// 1. İşçinin hazır olduğundan emin olun
|
||||
if worker == nil {
|
||||
return false
|
||||
}
|
||||
|
||||
// 2. Arka plan işçisine gönder
|
||||
_, err := worker.SendMessage(
|
||||
context.Background(), // Standart Go bağlamı
|
||||
unsafe.Pointer(data), // İşçiye iletilecek veri
|
||||
nil, // İsteğe bağlı http.ResponseWriter
|
||||
)
|
||||
|
||||
return err == nil
|
||||
}
|
||||
```
|
||||
|
||||
### HTTP Emülasyonu :`SendRequest`
|
||||
|
||||
Uzantınızın standart bir web ortamı bekleyen ( `$_SERVER`, `$_GET` vb. dolduran) bir PHP komut dosyasını çağırması gerekiyorsa `SendRequest` kullanın.
|
||||
|
||||
```go
|
||||
// #include <Zend/zend_types.h>
|
||||
import "C"
|
||||
import (
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"unsafe"
|
||||
"github.com/dunglas/frankenphp"
|
||||
)
|
||||
|
||||
//export_php:function my_worker_http_request(string $path): string
|
||||
func my_worker_http_request(path *C.zend_string) unsafe.Pointer {
|
||||
// 1. İsteği ve kaydediciyi hazırla
|
||||
url := frankenphp.GoString(unsafe.Pointer(path))
|
||||
req, _ := http.NewRequest("GET", url, http.NoBody)
|
||||
rr := httptest.NewRecorder()
|
||||
|
||||
// 2. İşçiye gönder
|
||||
if err := worker.SendRequest(rr, req); err != nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
// 3. Yakalanan yanıtı döndür
|
||||
return frankenphp.PHPString(rr.Body.String(), false)
|
||||
}
|
||||
```
|
||||
|
||||
## İşçi Komut Dosyası
|
||||
|
||||
PHP işçi komut dosyası bir döngüde çalışır ve hem ham mesajları hem de HTTP isteklerini işleyebilir.
|
||||
|
||||
```php
|
||||
<?php
|
||||
// Hem ham mesajları hem de HTTP isteklerini aynı döngüde işle
|
||||
$handler = function ($payload = null) {
|
||||
// Durum 1: Mesaj Modu
|
||||
if ($payload !== null) {
|
||||
return "Received payload: " . $payload;
|
||||
}
|
||||
|
||||
// Durum 2: HTTP Modu (standart PHP süper küreselleri doldurulur)
|
||||
echo "Hello from page: " . $_SERVER['REQUEST_URI'];
|
||||
};
|
||||
|
||||
while (frankenphp_handle_request($handler)) {
|
||||
gc_collect_cycles();
|
||||
}
|
||||
```
|
||||
|
||||
## Yaşam Döngüsü Kancaları
|
||||
|
||||
FrankenPHP, yaşam döngüsünün belirli noktalarında Go kodunu yürütmek için kancalar sağlar.
|
||||
|
||||
| Kanca Türü | Seçenek Adı | İmza | Bağlam ve Kullanım Durumu |
|
||||
| :--------- | :--------------------------- | :------------------- | :--------------------------------------------------------------------- |
|
||||
| **Sunucu** | `WithWorkerOnServerStartup` | `func()` | Genel kurulum. **Bir Kez** çalışır. Örnek: NATS/Redis'e bağlanma. |
|
||||
| **Sunucu** | `WithWorkerOnServerShutdown` | `func()` | Genel temizleme. **Bir Kez** çalışır. Örnek: Paylaşılan bağlantıları kapatma. |
|
||||
| **İş Parçacığı** | `WithWorkerOnReady` | `func(threadID int)` | İş parçacığı başına kurulum. Bir iş parçacığı başladığında çağrılır. İş Parçacığı Kimliğini alır. |
|
||||
| **İş Parçacığı** | `WithWorkerOnShutdown` | `func(threadID int)` | İş parçacığı başına temizleme. İş Parçacığı Kimliğini alır. |
|
||||
|
||||
### Örnek
|
||||
|
||||
```go
|
||||
package myextension
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/dunglas/frankenphp"
|
||||
frankenphpCaddy "github.com/dunglas/frankenphp/caddy"
|
||||
)
|
||||
|
||||
func init() {
|
||||
workerHandle = frankenphpCaddy.RegisterWorkers(
|
||||
"my-worker", "worker.php", 2,
|
||||
|
||||
// Sunucu Başlatma (Genel)
|
||||
frankenphp.WithWorkerOnServerStartup(func() {
|
||||
fmt.Println("Uzantı: Sunucu başlıyor...")
|
||||
}),
|
||||
|
||||
// İş Parçacığı Hazır (İş Parçacığı Başına)
|
||||
// Not: Fonksiyon, İş Parçacığı Kimliğini temsil eden bir tamsayı kabul eder
|
||||
frankenphp.WithWorkerOnReady(func(id int) {
|
||||
fmt.Printf("Uzantı: İşçi iş parçacığı #%d hazır.\n", id)
|
||||
}),
|
||||
)
|
||||
}
|
||||
Reference in New Issue
Block a user