Python файлы: - handler.py → sql_runner.py (entrypoint: sql_runner.handle) - handler.py → notes_crud.py (entrypoint: notes_crud.handle) - handler.py → notes_list.py (entrypoint: notes_list.handle) TF ресурсы переименованы: - sless_function.notes → sless_function.notes_crud - sless_trigger.notes_http → sless_trigger.notes_crud_http - sless_job.create_table → sless_job.notes_table_init - sless_job.create_index → sless_job.notes_index_init - archive_file.notes → archive_file.notes_crud_zip - archive_file.sql_runner → archive_file.sql_runner_zip - archive_file.notes_list → archive_file.notes_list_zip Добавлены подробные комментарии во все .tf файлы
82 lines
3.2 KiB
Python
82 lines
3.2 KiB
Python
# 2026-03-09
|
||
# notes_crud.py — CRUD роутер для таблицы notes.
|
||
#
|
||
# Назначение: единая функция, которая обрабатывает все операции с записями.
|
||
# Роутинг осуществляется по sub-path URL (event._path), который runtime
|
||
# берёт из входящего HTTP-запроса и добавляет в event автоматически.
|
||
#
|
||
# Доступные маршруты (все POST):
|
||
# /fn/default/notes/add?title=...&body=... → создать запись
|
||
# /fn/default/notes/update?id=1&title=...&body=... → обновить запись
|
||
# /fn/default/notes/delete?id=1 → удалить запись
|
||
#
|
||
# Параметры берутся из query string (event._query) или из тела запроса (event).
|
||
# event._path и event._query добавляет Python runtime (server.py) автоматически.
|
||
import os
|
||
import psycopg2
|
||
import psycopg2.extras
|
||
|
||
|
||
def handle(event):
|
||
dsn = os.environ['PG_DSN']
|
||
# sub-path без ведущего слэша: "add", "update", "delete"
|
||
action = event.get('_path', '/').strip('/')
|
||
q = event.get('_query', {})
|
||
|
||
conn = psycopg2.connect(dsn)
|
||
try:
|
||
cur = conn.cursor(cursor_factory=psycopg2.extras.RealDictCursor)
|
||
|
||
if action == 'add':
|
||
title = q.get('title') or event.get('title', '')
|
||
body = q.get('body') or event.get('body', '')
|
||
if not title:
|
||
return {'error': 'title is required'}
|
||
cur.execute(
|
||
"INSERT INTO notes (title, body) VALUES (%s, %s)"
|
||
" RETURNING id, title, body, created_at::text",
|
||
(title, body)
|
||
)
|
||
row = cur.fetchone()
|
||
conn.commit()
|
||
return dict(row)
|
||
|
||
elif action == 'update':
|
||
id_ = q.get('id') or event.get('id')
|
||
if not id_:
|
||
return {'error': 'id is required'}
|
||
title = q.get('title') or event.get('title', '')
|
||
body = q.get('body') or event.get('body', '')
|
||
cur.execute(
|
||
"UPDATE notes SET title=%s, body=%s WHERE id=%s"
|
||
" RETURNING id, title, body, created_at::text",
|
||
(title, body, int(id_))
|
||
)
|
||
row = cur.fetchone()
|
||
conn.commit()
|
||
return dict(row) if row else {'error': 'not found'}
|
||
|
||
elif action == 'delete':
|
||
id_ = q.get('id') or event.get('id')
|
||
if not id_:
|
||
return {'error': 'id is required'}
|
||
cur.execute(
|
||
"DELETE FROM notes WHERE id=%s RETURNING id",
|
||
(int(id_),)
|
||
)
|
||
row = cur.fetchone()
|
||
conn.commit()
|
||
return {'deleted': row['id']} if row else {'error': 'not found'}
|
||
|
||
else:
|
||
return {
|
||
'error': f'unknown action: /{action}',
|
||
'hint': 'use /add?title=...&body=..., /update?id=X&title=...&body=..., /delete?id=X'
|
||
}
|
||
|
||
except Exception as e:
|
||
conn.rollback()
|
||
return {'error': str(e)}
|
||
finally:
|
||
conn.close()
|