Обработка топора ios запросов, которые занимают более 10 секунд - PullRequest
2 голосов
/ 18 января 2020

Я надеюсь, что этот вопрос не слишком общий, но у меня есть запрос на публикацию, который загружает изображение в высоком разрешении, а затем на стороне сервера выполняется несколько операций с этим изображением для создания миниатюр и водяных знаков. Серверу требуется 10-20 секунд, прежде чем он, наконец, вернет ответ. Должен ли я вернуть какой-то промежуточный ответ? Есть ли здесь лучшая практика?

Для иллюстрации приведем примерную схему кода на стороне клиента:

axios.post('/upload', hugePhoto, { headers: { 'Content-Type': 'multipart/form-data' } })
.then(res => { /* takes 10-20 seconds before I get a response here */ })
.catch(err => { /* handle error */ })

И код на стороне сервера, обратите внимание, что я создаю здесь куча изображений разных размеров и загрузка их на S3, что занимает так много времени:

router.post('/upload', upload.single('file'), (req, res) => {
  sharp(req.file.path).metadata()
  .then(m => /* reading metadata */)
  .then(() => /* some db operations */)
  .then(() => /* uploading original file to S3 */)
  .then(() => /* resizing the file with sharp */)
  .then(() => /* uploading that to S3 */)
  .then(() => /* resizing the file with sharp */)
  .then(() => /* uploading that to S3 */)
  .then(() => /* resizing the file with sharp */)
  .then(() => /* uploading that to S3 */)
  .then(() => res.json({ success: true }))
  .catch(err => res.status(400).send(err.message))
})

Спасибо!

1 Ответ

1 голос
/ 18 января 2020

Это идеальный вариант использования безсерверной управляемой событиями архитектуры. Клиенту не нужно ждать, пока вы создадите и загрузите изображения с различным разрешением. Есть несколько способов сократить время.

  1. Делайте вещи параллельно, а не последовательно. как-то так (без изменений в вашей текущей архитектуре)
router.post('/upload', upload.single('file'), (req, res) => {
  sharp(req.file.path).metadata()
  .then(m => /* reading metadata */)
  .then(() => /* some db operations */)
  .then(() => /* uploading original file to S3 */)
  .then(() => Promise.all([funcResolution1(), funcResolution2(), funcResolution3()]))
  .then(() => res.json({ success: true }))
  .catch(err => res.status(400).send(err.message))

Если вы готовы изменить архитектуру, вы можете использовать здесь безсерверные технологии. что-то вроде AWS лямбда (https://aws.amazon.com/lambda/). Вы в основном берете файл из конечной точки и после этого вызываете некоторые события, чтобы функция делала для вас другие вещи. ИЛИ есть триггер на s3 для запуска функции, как и когда есть файл. эта лямбда-функция может сделать для вас миниатюры и т.д. c. (https://aws.amazon.com/blogs/compute/resize-images-on-the-fly-with-amazon-s3-aws-lambda-and-amazon-api-gateway/)

Вы можете делегировать задачу другому приложению, которое запускается при появлении файла.

Надеюсь, это даст вам представление.

...