Использование потоков при получении объектов из S3

Нам следует изменить способ обработки запросов getObject в наших приложениях Node.js AWS. Техника читаемых потоков пригодится, когда мы будем обрабатывать ответ S3.

1. Классическая проблема

Допустим, мы сталкиваемся с классической проблемой: у нас есть функция Lambda, которая программно получает объекты из S3 с помощью AWS SDK в Node.js.

Приложение использует метод getObject для получения объекта из ведра.

2. Изменения

Но когда мы обновим SDK до версии 3 (или напишем новое приложение с этой версией), мы столкнемся с некоторыми изменениями в сигнатуре методов.

Версия 3 является модульной, поэтому нам придется устанавливать в приложение только то, что нам нужно. Это уменьшит размер пакета, что улучшит время развертывания, так что все звучит хорошо.

Мы должны установить только модуль @aws-sdk/client-s3 вместо всего пакета aws-sdk. Модуль содержит метод getObject, который помогает нам получать объекты из ведра.

Конструктор S3 по-прежнему доступен в модуле, так что до сих пор в нем нет ничего нового.

2.1. Отсутствие метода promise()

Первое изменение заключается в том, что метод getObject будет возвращать Promise.

В версии 2 метод getObject возвращает объект, и нам приходилось вызывать метод promise(), который разрешается в ответ S3. Поскольку мы всегда хотим использовать синтаксис async/await вместо обратных вызовов, метод promise() стал частью нашей жизни разработчиков.

Хорошей новостью является то, что AWS упростил сигнатуру в версии 3, и метод getObject уже возвращает Promise. Поэтому нам не нужно вызывать метод promise(), если мы хотим await для получения разрешенного значения.

2.2 Читаемые потоки вместо буфера

Обещание метода S3 getObject разрешается в объект, который расширяет тип GetObjectOutput. Этот объект имеет те же свойства, что и в SDK v2, но содержит разрушающее изменение.

В версии 3 свойство Body разрешенного объекта ответа S3 представляет собой читаемый поток вместо Buffer. Это изменение подразумевает, что мы должны изменить то, как приложение обрабатывает объект.

3. Некоторый код TypeScript

Читаемые потоки реализуют метод Symbol.asyncIterator, поэтому потоки также являются асинхронными итераторами.

Поэтому мы можем использовать конструкцию for...of для итерации по читаемому потоку и получения фрагментов, которые предоставляет поток.

В следующем примере мы вернем объект, который мы загрузили из S3. Пример кода, обрабатывающего запросы getObject, может выглядеть следующим образом:

async function getObject(params) {
  const s3ResponseStream = (await s3.getObject(params)).Body
  const chunks = []

  for await (const chunk of s3ResponseStream) {
    chunks.push(chunk)
  }

  const responseBuffer = Buffer.concat(chunks)
  return JSON.parse(responseBuffer.toString())
}
Вход в полноэкранный режим Выход из полноэкранного режима

Каждый chunk представляет собой Buffer. После того как мы получили последний чанк объекта S3, мы можем конкатенировать и преобразовать их в строку, а затем, наконец, в объект JavaScript.

Лямбда-обработчик может выглядеть следующим образом:

import { S3 } from '@aws-sdk/client-s3'

const s3 = new S3({ region: 'us-east-1' })

export async function handler(event) {
  try {
    const s3Object = await getObject({
      Bucket: 'ARN OF THE BUCKET',
      Key: 'NAME OF THE OBJECT TO FETCH',
    })

    return s3Object
  } catch (error) {
    console.error('Error while downloading object from S3', error.message)
    throw error
  }
}
Войти в полноэкранный режим Выйти из полноэкранного режима

Мы можем обернуть логику обработки потока в функцию getObject и использовать ее в блоке try/catch, как мы обычно делаем в обработчике Lambda.

Обратите внимание, что в приведенном выше примере мы все еще храним объект S3 в памяти. Реальное преимущество потоков заключается в том, что мы обрабатываем чанк по мере его поступления. Такие примеры использования, как преобразование данных, сохранение их в базе данных или возврат ответа в виде потока, не входят в эту статью, и я, возможно, расскажу о них в другой раз.

4. Резюме

Подпись метода getObject изменилась в SDK версии 3. Свойство Body ответа теперь представляет собой читаемый поток вместо Buffer.

Мы можем использовать основную логику потока Node.js для обработки возвращаемого значения в наших лямбда-функциях.

5. Ссылки

AWS SDK для JavaScript v3

Оцените статью
devanswers.ru
Добавить комментарий