feat(backend): эндпоинты выгрузки/импорта документов + enum DocumentType#22
Open
trialiya wants to merge 6 commits into
Open
feat(backend): эндпоинты выгрузки/импорта документов + enum DocumentType#22trialiya wants to merge 6 commits into
trialiya wants to merge 6 commits into
Conversation
- DocumentType enum заменяет String-тип в DocumentEntity; JDBC-конвертер
хранит lowercase ('document'/'folder') для обратной совместимости,
@jsonvalue сохраняет контракт API
- GET /api/documents/{id}/download — документ как .md, папка как .zip
(поддерево с переписыванием /?doc=ID ссылок), через renderSubtree
- POST /api/documents/admin/import — синхронизация (импорт) из серверной
папки экспорта: восстановление дерева, порядок из .index.md, обратное
переписывание ссылок на /?doc=ID
- тесты: renderSubtree (документ/папка/ссылки) и импорт (иерархия,
порядок, реверс ссылок); существующие тесты обновлены под enum
Render the download subtree lazily as a Stream<ExportEntry> (depth-first walk using Stream.mapMulti for recursive child expansion) and write entries straight into the response OutputStream (ZipOutputStream for folders, raw Markdown for documents) instead of buffering the whole archive in a byte[]. renderSubtree is kept as a thin eager collector over streamSubtree for existing callers/tests. https://claude.ai/code/session_01XejhfdCBDHhk3pqcszieMC
Replace the single repo.findAll() table scan in the download/stream path with DocumentRepository.findAllByParentIdOrderByPosition(parentId): a position-sorted stream fetched one level at a time and drained inside try-with-resources so its JDBC cursor is released. The full documents table is never held in memory; only the lightweight id→path map (for link rewriting) and one level of entities live at a time. exportAll (disk export) is left unchanged. https://claude.ai/code/session_01XejhfdCBDHhk3pqcszieMC
exportAll now loads roots via findRoots and each level via the shared childrenOf(parentId) helper (findAllByParentIdOrderByPosition, stream closed immediately) instead of a full-table findAll() + in-memory byParent index — consistent with the subtree streaming path. Adds DocumentExportAllTest covering the on-disk layout, link rewriting, and meta toggle; applies spotless formatting. https://claude.ai/code/session_01XejhfdCBDHhk3pqcszieMC
…ding Merge main into the branch (resolving the merge-only CI failure) and update DocumentExportServiceTest — added on main after this branch diverged — to the DocumentType enum and the per-level repository loader (findAllByParentIdOrderByPosition) instead of the removed findAll(). Drops the now-redundant DocumentExportAllTest, since the merged DocumentExportServiceTest covers exportAll comprehensively. https://claude.ai/code/session_01XejhfdCBDHhk3pqcszieMC
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Что сделано
Три доработки на бэке (отдельная ветка от
main).1. Enum типа документа вместо String
DocumentType { DOCUMENT, FOLDER }с@JsonValue/@JsonCreator— на проводе остаётся lowercase ("document"/"folder").DocumentEntity.typeтеперьDocumentType.DocumentTypeJdbcConverter(Reader/Writer) зарегистрирован вPgVectorJdbcConfigиH2JdbcConfig— в БД хранится lowercase, поэтому существующие строки и колонка не ломаются, миграция не нужна.String(минимальный blast radius): конверсия черезgetType().getValue(). Контракт API/фронта не изменился.2. REST выгрузки —
GET /api/documents/{id}/download?meta=false.md(text/markdown, attachment);.zipподдерева (Markdown + опц..yaml), структура как у экспорта.DocumentExportService.renderSubtree(...)— рендер в память, переиспользует существующие helpers;/?doc=IDпереписываются в относительные пути внутри архива, внешние ссылки не трогаются.3. Admin REST синхронизации/импорта —
POST /api/documents/admin/import?parentId=DocumentImportService: обходит серверную папку экспорта, восстанавливает дерево, порядок и заголовки берёт из.index.md, тело папок из.content.md, делает обратное переписывание ссылок в/?doc=ID(двухпроходно). ВозвращаетImportResult{created, folders, documents}.Тесты
DocumentExportSubtreeTest— раскладка папки, переписывание ссылок, одиночный документ, отсутствующий root.DocumentImportServiceTest— иерархия/порядок/заголовки, реверс ссылок, импорт под parentId, ошибка при отсутствии папки.DocumentServiceUnitTest(H2 + реальный репозиторий) иPostgresDocumentITобновлены под enum — подтверждают корректный round-trip конвертера.https://claude.ai/code/session_01QwmrrALvDe85nY9kBakg5c