Есть много способов сделать это.Какой из них вы используете, будет в значительной степени зависеть от ваших конкретных потребностей и навыков (например, от того, насколько быстро вам нужно завершить фоновый процесс, чтобы он предоставлял вывод пользователю, какие другие технологии являются частью всего вашего приложения, каковы ваши навыкии т. д.)
Я знаю, что это не полный ответ, но я расскажу вам, что я сделал, когда столкнулся с подобной проблемой некоторое время назад.Я надеюсь, что это послужит отправной точкой или, по крайней мере, идеей.
Проблема:
Как и вы, мне нужно, чтобы пользователи могли публиковать некоторые данные.на мой бэкэнд.Такие данные (не большой блок, всего 5-7 полей) при публикации необходимо сначала сохранить в таблице, а затем запустить огромный процесс, который займет около 30 секунд.В течение этих 30 секунд мне нужно было, чтобы пользователь мог продолжать использовать приложение (вместо того, чтобы просто сидеть и ждать, пока контроллер завершит 30-секундный процесс).
Чтобы сделать его немного более сложнымМой клиент попросил, чтобы после публикации пользователь оставался на текущей странице (поэтому не нужно публиковать и затем перерисовывать представление в браузере пользователя).
Подход:
1.- Запрос моего клиента был довольно прост: форма отправляла через Ajax.Не будучи большим поклонником сложных библиотек JS, которые являются излишними для большинства моих проектов (и, будучи немного старомодным человеком), я просто обработал форму с помощью простого ванильного сценария JS, который будет приниматьформировать данные, отправлять их на мой контроллер и при успешном ответе от контроллера (примерно через 100 миллисекунд) уведомлять пользователя о том, что все в порядке, и позволить ему продолжать работу.
Чтобы получить быстрый ответ,контроллер, получающий данные Ajax, должен был сделать следующее:
a.Запустите проверку формы (никогда, никогда не доверяйте вводу пользователя) b.Сохраните данные формы в таблицу c.Запланируйте жесткую обработку так, чтобы это происходило асинхронно.Подробнее об этом в следующем разделе
2.- Асинхронная обработка была немного более сложной.Вот как я это сделал.
Я создал таблицу семафоров, которая ссылалась на данные формы в другой таблице (назовем их semaphore
и user_posts
).Таблица семафоров была довольно простой: поле уникального идентификатора, поле, ссылающееся на уникальный идентификатор user_posts
, в котором находились данные, поле состояния (с возможными статусами pending
, working
, complete
, failed
)дата вставки и дата последнего обновления.
Далее я установил отдельный контроллер (с креативным именем Cron
), который будет работать только при вызове из CLI (документация Codeigniter объясняет, как это сделать) с различнымиметоды, которые будут делать реальную работу.Всякий раз, когда демон cron просыпался и вызывал основной метод manager
, этот метод проверял бы таблицу semaphore
на наличие строк pending
и выбирал самую старую.Затем он передает его в метод worker
, который помечает его как working
и начинает обработку данных.После обработки строка будет помечена как complete
(или failed
, что вызовет другие действия, которые мне здесь объяснять не нужно) и вернется в режим сна.
Дополнительная информация
Демон cron пробуждал manager
каждые 5 минут.Первоначально, когда в приложении моего клиента было мало трафика, этого было более чем достаточно, чтобы справиться с нагрузкой (большую часть времени manager
просыпался, не видел ничего ожидающего и возвращался в спящий режим).По мере роста трафика и того, что семафор становился постоянно растущей очередью ожидающих элементов, мы проделали определенную работу, чтобы разрешить нескольким экземплярам worker
порождаться manager
и запускаться параллельно, каждый из которых работает в отдельной строке семафора.,В итоге объем работы, который был поставлен в очередь между каждым 5-минутным пробуждением демона cron, стал таким, что нам нужно было изменить расписание на 1-минутные интервалы и настроить выделенный сервер cron для обработки нагрузки, не влияя на производительность сайта (помните, каждый набор данных занимал около 30 секунд для обработки).
Ну, это может быть не тот ответ, который вы ожидали (я за этим отвечаю NDA, поэтому не могу предоставить конкретный код), но, как я уже говорил, это может, по крайней мере, дать вам представление о том, как решатьэто.Есть много других способов решения этой проблемы.Это только один из них