(например запускается внешний процесс и нужно ждать его ответ) то тут асинхронность вполне реализуется самостоятельно. да конечно есть готовые библиотеки (в зависимости от того можно ли держать очередь в памяти или в базе данных, тот же брокер событий reactPHP вполне можно взять за основу).
Основная идея в том что каждая твоя операция должна иметь несколько состояний (условно их можно реализовывать как одним параметром так и несколькими)
- Ожидает исполнения
- Запущено и ожидает окончания
- Окончено без ошибок
- Окончено с ошибкой и требует повтора
- Окончено с фатальной ошибкой.
Дальше я предполагаю что событие и действие это одно и то же (иначе нужно заводить отдельно очередь действий, например если одно событие это несколько действий друг за другом или одновременно, но обрабатывать их так же можно одним брокером).
Скрипт обработки событий смотрит на текущие события и при необходимости тупо
запускает фоновый процесс на каждое действие (можно считать количество процессов со статусом "Запущено и ожидает окончание" и если их больше лимита - ничего не делать, пропускать, т.е. ждать изменений в очереди или просто сбыдлокодить sleep).
Так же этот скрипт может следить за временем исполнения задач (например повторы), достаточно просто сохранить время последней попытки и где то определить, какие задачи какие временные лимиты (я это определял в коде php, никто не мешает это прямо в базе данных у задачи определять)
Задача фонового процесса отметиться в базе данных, правкой состояния
- Ожидает исполнения -> Запущено и ожидает окончания
- Запущено и ожидает окончания -> Окончено ...
Скрипт может сам следить за pid процессов, отмечая у себя какой процесс был запущен для какой задачи, таким образом можно отлавливать вмешательство администратора или ОС (например из-за нехватки памяти) и как то интерпретировать это (повторить попытку или отвести в статус фатальных).
В итоге, любая задача будет запущена в виде процесса ОС, в linux это делается с помощью
bash ... & а в windows - например start /min. Сам процесс обработки очередей будет занят сном, чтением списка процессов и проверкой pid уже запущенных, на это не требуется никаких особых ресурсов (при необходимости очередью может рулить этот процесс, буквально вместо базы данных слушать сокеты и принимать заявки на исполнение, в phpreact для этого все готово, даже слабые машины могут легко тянуть десятки тысяч запросов, я эксприментировал с websocket)