Запуск AWS Lambda при поступлении новых файлов в AWS S3 - PullRequest
0 голосов
/ 22 апреля 2019

У меня есть лямбда-функция, написанная на Python, в которой есть код для запуска команд копирования Redshift для 3 таблиц из 3 файлов, расположенных в AWS S3.

Пример:

У меня есть таблица A, B и C.

The python code contains:

'copy to redshift A from "s3://bucket/abc/A.csv"'
'copy to redshift B from "s3://bucket/abc/B.csv"'
'copy to redshift C from "s3://bucket/abc/C.csv"'

Этот код запускается всякий раз, когда новый файл из трех поступает в "s3: // bucket / abc /" в S3.Таким образом, он загружает все три таблицы, даже если поступил только один CSV-файл.

Наилучшее решение: разбейте код на три разные функции Lambda и напрямую сопоставьте их с каждым обновлением / загрузкой исходных файлов.

Но мое требование состоит в том, чтобы продолжить работу с одним лямбда-кодом, который будет выборочно запускать его часть (используя if) только для тех CSV-файлов, которые были обновлены.

Пример:

if (new csv file for A has arrived):
    'copy to redshift A from "s3://bucket/abc/A.csv"'
if (new csv file for B has arrived):
    'copy to redshift B from "s3://bucket/abc/B.csv"'
if (new csv file for C has arrived):
    'copy to redshift C from "s3://bucket/abc/C.csv"'

В настоящее время для достижения этого я храню метаданные этих файлов (LastModified) в файле python, ключом которого являются имена файлов.Печать dict будет выглядеть примерно так:

{'bucket/abc/A.csv': '2019-04-17 11:14:11+00:00', 'bucket/abc/B.csv': '2019-04-18 12:55:47+00:00', 'bucket/abc/C.csv': '2019-04-17 11:09:55+00:00'}

И затем, когда новый файл появляется среди любого из трех, Lambda запускается, и я читаю dict и сравниваю время каждого файла.с соответствующими значениями в dict, если новый LastModified увеличен, я запускаю команду копирования этой таблицы.

Все это, потому что нет никакой работы, которую я мог бы найти с событием S3 / CloudWatch для этого видаварианта использования.

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

1 Ответ

2 голосов
/ 22 апреля 2019

Когда событие Amazon S3 запускает функцию AWS Lambda, оно предоставляет имя корзины и ключ объекта как часть event:

def lambda_handler(event, context):

  # Get the bucket and object key from the Event
  bucket = event['Records'][0]['s3']['bucket']['name']
  key = urllib.parse.unquote_plus(event['Records'][0]['s3']['object']['key'])

В то время как объект детализируется какя подозреваю, что каждое событие предоставляется только с одним объектом (отсюда и использование [0]).Однако я не уверен на 100%, что так будет всегда.Лучше предположить это, пока не доказано обратное.

Таким образом, если ваш код ожидает определенных объектов, ваш код будет:

if key == 'abc/A.csv':
    'copy to Table-A from "s3://bucket/abc/A.csv"'
if key == 'abc/B.csv':
    'copy to Table-B from "s3://bucket/abc/B.csv"'
if key == 'abc/C.csv':
    'copy to Table-C from "s3://bucket/abc/C.csv"'

Нет необходимости хранить LastModified, так какСобытие запускается всякий раз, когда загружается новый файл.Кроме того, будьте осторожны с хранением данных в глобальном dict и ожидайте, что они будут в будущем при выполнении - это не всегда будет так.Контейнер Lambda может быть удален, если он не запускается в течение определенного периода времени, и при параллельном выполнении могут быть созданы дополнительные контейнеры Lambda.

Если вы всегда знаете, что ожидаете 3 файла, и они всегдазагружен в определенном порядке , тогда вы можете вместо этого использовать загрузку 3-го файла для запуска процесса, который затем скопирует все 3 файла в Redshift.

...