Context: контексты выполнения
Что такое Context
Async\Context — это хранилище ключ-значение, привязанное к Scope или корутине.
Контексты образуют иерархию: при чтении значения поиск идёт вверх по дереву скоупов.
Это аналог context.Context в Go или CoroutineContext в Kotlin — механизм передачи данных по иерархии без явной передачи параметров.
Три уровня контекста
TrueAsync предоставляет три функции для доступа к контекстам:
<?php
use function Async\current_context;
use function Async\coroutine_context;
use function Async\root_context;
// Контекст текущего Scope
$scopeCtx = current_context();
// Контекст текущей корутины
$coroCtx = coroutine_context();
// Глобальный корневой контекст
$rootCtx = root_context();
?>
current_context()
Возвращает контекст текущего Scope. Если контекст ещё не создан — создаёт его автоматически.
Значения, установленные здесь, видны всем корутинам в этом Scope.
coroutine_context()
Возвращает контекст текущей корутины. Это приватный контекст, принадлежащий только этой корутине. Другие корутины не видят данные, установленные здесь.
root_context()
Возвращает глобальный контекст, общий для всего запроса. Значения здесь видны через find() из любого контекста.
Ключи
Ключом может быть строка или объект:
<?php
use function Async\current_context;
$ctx = current_context();
// Строковый ключ
$ctx->set('request_id', 'abc-123');
// Объект как ключ (полезно для уникальных токенов)
$key = new stdClass();
$ctx->set($key, 'значение');
?>
Объекты-ключи хранятся по ссылке в контексте, что гарантирует их уникальность.
Чтение: локальное и иерархическое
find() / get() / has() — поиск по иерархии
Ищет значение сначала в текущем контексте, затем в родительском, и так до корня:
<?php
use function Async\root_context;
use function Async\current_context;
use function Async\spawn;
use function Async\await;
root_context()->set('app_name', 'MyApp');
$scope = new Async\Scope();
spawn(function() {
// find() ищет вверх по иерархии
$name = current_context()->find('app_name');
echo $name; // "MyApp" — найдено в root_context
});
?>
findLocal() / getLocal() / hasLocal() — только текущий контекст
Ищет значение только в текущем контексте, не поднимаясь по иерархии:
<?php
use function Async\root_context;
use function Async\current_context;
root_context()->set('app_name', 'MyApp');
$local = current_context()->findLocal('app_name');
// null — в текущем Scope это значение не установлено
$inherited = current_context()->find('app_name');
// "MyApp" — найдено в parent scope
?>
Запись и удаление
set()
<?php
$ctx = current_context();
// Установить значение (по умолчанию replace = false)
$ctx->set('key', 'value');
// Повторная установка без replace — ошибка
$ctx->set('key', 'new_value'); // Error: A context key already exists
// С явным replace = true
$ctx->set('key', 'new_value', replace: true); // OK
Метод set() возвращает $this, позволяя цепочки вызовов:
<?php
current_context()
->set('user_id', 42)
->set('request_id', 'abc-123')
->set('locale', 'ru');
?>
unset()
<?php
$ctx = current_context();
$ctx->unset('key');
Метод unset() также возвращает $this.
Практические примеры
Передача ID запроса
<?php
use function Async\spawn;
use function Async\await;
use function Async\current_context;
// Middleware устанавливает request_id
current_context()->set('request_id', bin2hex(random_bytes(8)));
// Любая корутина в этом скоупе может прочитать
spawn(function() {
$requestId = current_context()->find('request_id');
// Используем в логировании
error_log("[$requestId] Обработка запроса...");
});
?>
Контекст корутины как приватное хранилище
<?php
use function Async\spawn;
use function Async\await;
use function Async\coroutine_context;
$c1 = spawn(function() {
coroutine_context()->set('step', 1);
// ... выполняем работу
$step = coroutine_context()->getLocal('step');
});
$c2 = spawn(function() {
// Не видит 'step' из c1
$step = coroutine_context()->findLocal('step'); // null
});
?>
Конфигурация через root_context
<?php
use function Async\root_context;
use function Async\current_context;
use function Async\spawn;
// Устанавливаем в начале запроса
root_context()
->set('db_host', 'localhost')
->set('cache_ttl', 3600);
// Доступно из любой корутины
spawn(function() {
$dbHost = current_context()->find('db_host'); // "localhost"
});
?>
См. также
- Scope — управление временем жизни корутин
- Корутины — базовая единица конкурентности
- current_context() — получение контекста текущего Scope