5.6 KiB
type, status, related
| type | status | related | |||
|---|---|---|---|---|---|
| reference | current |
|
Community Server DB — прямой SQL-доступ (read-only)
Что это
Бэкенд pgStore (file_pg.go) читает файлы и папки напрямую из БД
Community Server, без HTTP-слоя. Реализует FileStore (List/Stat/
Download) и Searcher по имени. Запись запрещена: все write-методы
возвращают ErrReadOnly.
Что за БД (research, live)
Проверено на VM onlyoffice-v2 (SSH 127.0.0.1:32):
- Community Server работает на MySQL 8.0, не на PostgreSQL.
- Хост:
127.0.0.1:3306внутри VM, базаonlyoffice. - Конфиг:
/etc/onlyoffice/communityserver/appsettings.production.json,providerName: MySql.Data.MySqlClient. - Таблицы:
files_file,files_folder,files_folder_tree,files_security, тенанты —tenants_tenants(неtenants).
- Хост:
- PostgreSQL 16 в той же VM — наш контур (
edw_docs, ролиedw/edw_ro, office-assistant), к OnlyOffice отношения не имеет.files_fileв PG нет. - Портал хранит файлы в S3/MinIO (DiscStorage только для мелочи).
Бакет
office, объект — по ключу (см. ниже).
Вывод: бэкенд назван по issue «PostgreSQL», но живой источник — MySQL.
database/sql + драйвер по DSN: mysql для MySQL, pgx для PostgreSQL.
Name() возвращает фактический движок (mysql или postgres).
Схема
files_file — одна строка на версию (PK tenant_id, id, version):
| поле | смысл |
|---|---|
id |
id файла (тот же, что в REST/ES) |
version |
номер версии этой строки |
version_group |
номер версии |
current_version |
1 = текущая версия, 0 = старая |
folder_id |
id родительской папки |
title |
имя файла с расширением |
content_length |
размер в байтах |
create_on, modified_on |
даты (UTC, без зоны) |
tenant_id |
тенант (портал) |
files_folder: id, parent_id, title, create_on, modified_on,
tenant_id. files_folder_tree: folder_id, parent_id, level — готовое
дерево, пока не используется.
Текущую строку файла берём по current_version = 1.
Доступ (SSH-туннель)
MySQL слушает только 127.0.0.1:3306 внутри VM. Снаружи — SSH-туннель
(SSH в VM открыт как 127.0.0.1:32):
ssh -f -N -o ControlMaster=no -o ControlPath=none \
-p 32 -i ~/.ssh/id_ed25519 \
-L 13306:127.0.0.1:3306 root@127.0.0.1
# MySQL DSN затем:
# root:<pw>@tcp(127.0.0.1:13306)/onlyoffice?parseTime=true
-o ControlMaster=no -o ControlPath=none обязательны: иначе forward уходит в
persistent master из ~/.ssh/config.
Переменные
| env | default | смысл |
|---|---|---|
ONLYOFFICE_DSN |
— | DSN драйвера (MySQL ...@tcp(...)/... или postgres://...) |
ONLYOFFICE_PG_DRIVER |
авто | postgres или mysql; иначе по форме DSN |
ONLYOFFICE_PG_TENANT |
ONLYOFFICE_TENANT |
фильтр tenant_id (пусто = все) |
ONLYOFFICE_PG_HOST/PORT/USER/PASSWORD/DBNAME/SSLMODE |
— | собрать PG DSN, если ONLYOFFICE_DSN пуст |
Имена — в .env.example. Секретов нет.
Download (MinIO)
Download не ходит в REST. Ключ объекта собирается из строки files_file:
00/00/<tenant>/files/folder_<shard>/file_<id>/v<version>/content.<ext>
shard = (id/1000 + 1) * 1000
shard — не folder_id, а следующая тысяча над id (файл 3727 →
folder_4000). Проверено live по бакету office.
Стриминг переиспользует downloadMinioObject из storage_fallback.go
(та же подпись SigV4 и MINIO_*), без дублирования.
Тесты
go test ./... # unit: rebind, csObjectKey, маппинг
go test -race ./...
# integration (нужен DSN; skip без него)
ONLYOFFICE_DSN='root:<pw>@tcp(127.0.0.1:13306)/onlyoffice?parseTime=true' \
ONLYOFFICE_PG_TENANT=1 \
ONLYOFFICE_PG_TEST_FILE_ID=22484 \
ONLYOFFICE_PG_TEST_FOLDER_ID=649 \
MINIO_ACCESS_KEY=... MINIO_SECRET_KEY=... \
go test -tags=integration -run TestIntegrationPGStore -v ./...
Integration сверяет Stat/List/Download с REST (c.Files()) и проверяет,
что write-методы дают ErrReadOnly.
Грабли
- MySQL хранит
datetimeбез зоны;parseTime=true(ставится автоматически) читает их как UTC. REST отдаёт+02:00— сравнивать моменты, не строки. GetFile(REST) не отдаётcontentLength— размер сверять сStatSQL.- Один файл = много строк
files_file(по версиям). Безcurrent_version = 1получите дубликаты. folder_idне входит в ключ MinIO; ключ считаетshardотid.- Searcher SQL ищет только по имени (
LIKE). Контент — Elasticsearch (elasticsearch.md).