Asynchronous facade for PostgreSQL and MinIO for corporate semantic search systems.
Project description
SensoryDataClient: Асинхронный клиент для данных и их структуры
SensoryDataClient — это изолированный, портируемый Python-модуль, предоставляющий единый асинхронный интерфейс для работы с объектным хранилищем MinIO и реляционной базой данных PostgreSQL. Он спроектирован как надежный фундамент для сервисов, которым требуется атомарно управлять не только файлами и их метаданными, но и их структурированным содержимым в виде строк.
🎯 Миссия
Предоставить разработчикам production-ready инструмент, который инкапсулирует всю сложность взаимодействия с хранилищами данных, предлагая простой, типобезопасный и асинхронный API для управления как целыми документами, так и их составными частями.
✨ Ключевые возможности
- Асинхронность "из коробки": Построен на
asyncio,SQLAlchemy 2.0 (async),asyncpgи асинхронных обертках над SDK MinIO. - Единый фасад (
DataClient): Один класс для управления файлами, их метаданными и структурированными строками. Больше не нужно жонглировать несколькими клиентами в бизнес-логике. - Управление строками документа (
Document Lines): Возможность сохранять, обновлять и запрашивать разобранное содержимое документа (текст, код, ссылки на изображения) с указанием типа и точной позиции (float), что идеально подходит для реализации diff-обновлений и RAG-пайплайнов. - Атомарные операции: Метод
upload_fileгарантирует, что метаданные не появятся в БД без соответствующего файла в MinIO (с автоматическим откатом). Операции со строками также транзакционны. - Типобезопасность: Активное использование
Pydanticдля моделей данных и 100% покрытие кода тайп-хинтами. - Готовность к развертыванию: Настройка через переменные окружения, структурированное JSON-логирование и удобный CLI-интерфейс на базе
Typer. - Простота для разработчика: Готовое Docker Compose окружение для локального тестирования и CLI для быстрой инициализации.
🏗️ Архитектура
Клиент реализует паттерн Фасад, скрывая детали работы с конкретными репозиториями. В отличие от предыдущей версии, работа с PostgreSQL теперь разделена на два репозитория для лучшего разделения ответственности (SRP).
┌────────────────────────────────┐
│ Ваш Сервис (Business Logic) │
└───────────────┬────────────────┘
│
┌───────────────▼────────────────┐
│ DataClient │ <- Единая точка входа
└───────────────┬────────────────┘
┌─────────┴─────────┬────────────────┐
│ │ │
┌─────▼─────┐ ┌─────▼──────┐ ┌─────▼──────┐
│ MinIO │ │ MetaData │ │ Line │
│ Repository│ │ Repository │ │ Repository │
└───────────┘ └────────────┘ └────────────┘
(MinIO SDK) (SQLAlchemy) (SQLAlchemy)
🚀 Установка
Для использования клиента в других проектах предполагается его установка из приватного репозитория или локально.
Установка для разработки
Шаг 1: Клонируйте репозиторий
git clone https://github.com/sensoryfox/datafileclient.git
cd datafileclient
Шаг 2: Установите зависимости Эта команда установит все необходимые библиотеки для работы клиента и для его разработки (тесты, линтеры).
pip install -e ".[dev]"
Организация хранения таблиц с данными:
┌───────────────────┐ ┌───────────────────┐
│ StoredFileORM │──────▶│ DocumentORM │
│ (stored_files) │ 1..1 │ (documents) │
└───────────────────┘ └─────────┬─────────┘
│ 1..N
▼
┌───────────────────┐
│ RawLineORM │ <- Главная "лента" контента
│ (raw_lines) │
└─────────┬─────────┘
┌──────────────────────────┼──────────────────────────┐
│ 1..0/1 │ 1..0/1 │ 1..0/1
▼ ▼ ▼
┌───────────────────┐ ┌───────────────────┐ ┌───────────────────┐
│ DocumentLineORM │ │ ImageLineORM │ │ AudioLineORM │
│ (lines_document) │ │ (lines_image) │ │ (lines_audio) │
└───────────────────┘ └───────────────────┘ └───────────────────┘
(геометрия, страница) (путь в S3, alt-text) (таймкоды, спикер)
🐳 Локальная разработка с Docker
Для разработки и тестирования клиента вам понадобятся запущенные экземпляры PostgreSQL и MinIO. Мы предоставляем готовую конфигурацию docker-compose.
Шаг 1: Создайте файл с переменными окружения Скопируйте пример. Для локального запуска менять ничего не нужно.
cp .env.example .env
Важно: Файл
.envдолжен содержатьPOSTGRES_HOST=localhostиMINIO_ENDPOINT=localhost:9000для подключения с вашего компьютера к контейнерам.
Шаг 2: Запустите окружение Эта команда поднимет контейнеры с PostgreSQL и MinIO.
docker-compose up -d
После запуска:
- Веб-консоль MinIO будет доступна по адресу
http://localhost:9001. - PostgreSQL будет доступен по адресу
localhost:5432.
Шаг 3: Инициализируйте окружение
Эта команда создаст таблицы в PostgreSQL (documents, document_lines) и бакет в MinIO.
python -m sensory_data_client init
Шаг 4: Проверьте соединения Убедитесь, что ваш локальный Python-код может достучаться до сервисов в Docker.
python -m sensory_data_client check
Вы должны увидеть:
✅ Connection Check
✔ PostgreSQL connection: OK
✔ MinIO connection: OK (bucket: 'test-bucket')
🛠️ Пример использования
import asyncio
from uuid import uuid4
from sensory_data_client import create_data_client, DocumentCreate, DocumentMetadata, Line
# --- 1. Инициализация клиента через фабрику ---
client = create_data_client()
# --- 2. Модель метаданных ---
doc_meta = DocumentCreate(
user_document_id="ext-id-456",
name="Project Proposal.md",
owner="user-02",
access_group="engineering",
extension="md"
)
# --- 3. Контент файла ---
file_content = b"# Project Sensory\n\nThis is the main proposal document."
# --- 4. Структурированные строки из файла ---
document_lines = [
Line(block_id="block-1", position=1.0, type="header", content="# Project Sensory"),
Line(block_id="block-2", position=2.0, type="paragraph", content="This is the main proposal document."),
]
async def main():
"""Основной сценарий использования клиента."""
new_doc_id = None
try:
# --- 5. Загрузка файла и метаданных ---
print("Uploading file...")
new_doc = await client.upload_file(
file_name="proposal.md",
content=file_content,
meta=doc_meta
)
new_doc_id = new_doc.id
print(f"Document created with ID: {new_doc_id}")
# --- 6. Сохранение разобранных строк документа ---
print("\nSaving document lines...")
await client.save_document_lines(new_doc_id, document_lines)
print(f"Saved {len(document_lines)} lines.")
# --- 7. Получение строк документа из БД ---
print("\nFetching document lines...")
retrieved_lines = await client.list_doclines(new_doc_id)
assert len(retrieved_lines) == len(document_lines)
assert retrieved_lines[0].content == "# Project Sensory"
print("Lines match!")
# --- 8. Генерация временной ссылки на скачивание ---
print("\nGenerating presigned URL for the original file...")
download_url = await client.generate_download_url(new_doc_id, expires_in=60)
print(f"URL (expires in 60s): {download_url}")
except Exception as e:
print(f"An error occurred: {e}")
finally:
# --- 9. Удаление документа для очистки ---
if new_doc_id:
print(f"\nDeleting document {new_doc_id}...")
# Удаление метаданных и файла. Строки будут удалены каскадно или их нужно удалять отдельно.
await client.delete_file(new_doc_id)
print("Document deleted successfully.")
if __name__ == "__main__":
asyncio.run(main())
⚙️ Конфигурация
Клиент настраивается через переменные окружения. Значения по умолчанию можно найти в файле .env.example.
| Переменная | Описание | Значение по умолчанию |
|---|---|---|
POSTGRES_HOST |
Хост PostgreSQL | localhost |
POSTGRES_PORT |
Порт PostgreSQL | 5432 |
POSTGRES_DB |
Имя базы данных | documents |
POSTGRES_USER |
Пользователь PostgreSQL | postgres |
POSTGRES_PASSWORD |
Пароль пользователя PostgreSQL | postgres |
MINIO_ENDPOINT |
Адрес MinIO (хост:порт) | localhost:9000 |
MINIO_ACCESS_KEY |
Ключ доступа MinIO | minioadmin |
MINIO_SECRET_KEY |
Секретный ключ MinIO | minioadmin |
MINIO_BUCKET |
Имя бакета для хранения файлов | documents |
MINIO_SECURE |
Использовать TLS для MinIO (True/False) |
False |
LOG_LEVEL |
Уровень логирования (INFO, DEBUG, ...) |
INFO |
⌨️ Command-Line Interface (CLI)
Для удобства разработки в клиент встроен CLI на базе Typer. Вызывается как модуль.
- Инициализировать сервисы: Создает таблицы в БД и бакет в MinIO.
python -m sensory_data_client init
- Проверить соединения: Проверяет доступность PostgreSQL и MinIO с текущими настройками.
python -m sensory_data_client check
🧪 Тестирование
Проект использует testcontainers для запуска интеграционных тестов в изолированном окружении с реальными версиями PostgreSQL и MinIO.
Для запуска всех тестов используйте pytest:
pytest
Тесты автоматически поднимут необходимые Docker-контейнеры, выполнят проверки и остановят их после завершения.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file sensory_data_client-0.2.45.tar.gz.
File metadata
- Download URL: sensory_data_client-0.2.45.tar.gz
- Upload date:
- Size: 59.9 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.1.0 CPython/3.10.1
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
11427392a6852637d269a57ec1042849b8f4883ca11a038d9b348b77ccf721e8
|
|
| MD5 |
99cecc49cb760db8db5ed0966d47c695
|
|
| BLAKE2b-256 |
0b3acb1de9a0a9b45acdd14146dbede873f3cfb78ac7b4e4b7a48e46dff2ad7c
|
File details
Details for the file sensory_data_client-0.2.45-py3-none-any.whl.
File metadata
- Download URL: sensory_data_client-0.2.45-py3-none-any.whl
- Upload date:
- Size: 79.8 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.1.0 CPython/3.10.1
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
6f704e72a4c731e321d4afecf1714ae37ba543daebbb62b53549a534ef38e7ea
|
|
| MD5 |
cd847c2d2a538b2370a818507778f189
|
|
| BLAKE2b-256 |
911291e910bd12c093d4c2f63d76fe1c9e90fcee0aab1cf5a6073778417ee1e5
|