From ad718deddc358c903a0db791c5d94d456885d6dd Mon Sep 17 00:00:00 2001 From: Fendy Date: Wed, 15 Jul 2026 22:57:48 +0800 Subject: [PATCH] migrate from github --- .gitignore | 1 + README.md | 197 +++++++++++++++++++++++++++++++++++++++++++++++++++ README_zh.md | 197 +++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 395 insertions(+) create mode 100644 .gitignore create mode 100644 README.md create mode 100644 README_zh.md diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..c9414e7 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +superpowers/ \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 0000000..11851f1 --- /dev/null +++ b/README.md @@ -0,0 +1,197 @@ +# Yoresee Doc + +Yoresee Doc is a collaborative document platform built with a Go backend, Vue 3 frontend, and a Yjs-based real-time collaboration stack. + +## Runtime Topology + +Core app services: +- `frontend`: Vue 3 (Vite) +- `backend`: Go Connect RPC/gRPC service +- `collab-core`: Node.js Yjs collaboration core +- `collab`: `collab-go` WebSocket gateway +- `snapshot-worker`: document snapshot sync worker +- `notification-worker`: notification event consumer +- `search-sync-worker`: Elasticsearch sync worker + +Infrastructure services: +- `postgres` +- `redis` +- `rabbitmq` +- `consul` +- `minio` +- `elasticsearch` +- `nginx` (single ingress) + +## Request and Event Flow + +Main request path: +1. Browser -> Nginx +2. Nginx `/` -> Frontend +3. Nginx `/grpc/` -> Backend gRPC-web endpoint +4. Backend -> Postgres/Redis/MinIO/Consul/Elasticsearch/MQ as needed + +Realtime collaboration path: +1. Browser -> Nginx `/ws/doc/{docId}` +2. Nginx -> `collab-go` +3. `collab-go` validates JWT and proxies to `collab-core` +4. `collab-core` maintains Yjs doc state in memory and Redis + +Async event path: +1. `collab-core` marks dirty docs in Redis and publishes dirty-doc events +2. `snapshot-worker` consumes `collab.dirty_docs` (RabbitMQ group mode) and also scans dirty set periodically +3. `snapshot-worker` fetches `/internal/yjs/doc-snapshot/{docId}` from `collab-core`, writes snapshot/content to DB, and emits search-sync event when content changed +4. `search-sync-worker` consumes `search.sync.document` and upserts Elasticsearch (when ES is enabled) +5. `notification-worker` consumes `notification.create` and writes notification records + +## Health and Graceful Shutdown + +Backend probes: +- `/health` +- `/readyz` +- `/livez` + +Collab probes: +- `collab-core`: `/health`, `/readyz`, `/livez` +- `collab-go`: `/health`, `/readyz`, `/livez` + +Shutdown behavior: +- Backend and collab services support draining and graceful shutdown. +- Readiness becomes `not_ready` during draining. + +## Deployment Modes + +`deploy/docker-compose.dev.yml`: +- Source-mounted development containers +- Backend debug port exposed (`2345`) +- Postgres/Redis/RabbitMQ/Elasticsearch ports exposed to host +- `start.sh dev ...` auto-runs `deploy/script/gen_proto.sh` + +`deploy/docker-compose.yml`: +- Production-style images +- Fewer host-exposed ports +- Backend/worker binaries are prebuilt in image stages + +## Dev Prerequisites + +`start.sh dev ...` runs `deploy/script/gen_proto.sh` on the host machine before docker compose starts. + +Required on host: +- `docker` + `docker compose` +- `go` + `protoc` (for Go stubs) +- frontend plugins in `frontend/node_modules` (`protoc-gen-es`, `protoc-gen-connect-es`) +- `grpc_tools_node_protoc_plugin` in `PATH` (for Node gRPC stubs used by `collab`) + +## Configuration Workflow + +Single source of truth: +- `deploy/.env` +- template: `deploy/.env.example` + +Interactive init/update: +```bash +bash deploy/script/configure.sh +``` + +What `configure.sh` does: +- prompts for key ports/secrets/env values +- writes/updates `deploy/.env` +- derives `MINIO_BROWSER_REDIRECT_URL` from `VITE_API_BASE_URL` +- calls `prepare.sh` automatically + +Render generated config files: +```bash +bash deploy/script/prepare.sh +``` + +Generated files: +- `backend/config.toml` +- `frontend/nginx.conf` +- `deploy/nginx/nginx.conf` +- `deploy/nginx/conf.d/default.conf` +- `deploy/redis/redis.conf` +- `deploy/rabbitmq/rabbitmq.conf` + +Template files: +- `backend/config.toml.tmpl` +- `frontend/nginx.conf.tmpl` +- `deploy/nginx/nginx.conf.tmpl` +- `deploy/nginx/conf.d/default.conf.tmpl` +- `deploy/redis/redis.conf.tmpl` +- `deploy/rabbitmq/rabbitmq.conf.tmpl` + +## Quick Start + +Recommended (interactive): +```bash +bash deploy/script/configure.sh +bash deploy/script/start.sh dev up +``` + +Non-interactive: +```bash +cp deploy/.env.example deploy/.env +bash deploy/script/prepare.sh +bash deploy/script/start.sh dev up +``` + +Release mode: +```bash +bash deploy/script/start.sh release up +``` + +Backend image startup behavior: +- backend container runs `migrate`, `db_init`, `es_init`, then starts `cmd/main`. + +Other actions: +```bash +bash deploy/script/start.sh dev rebuild +bash deploy/script/start.sh dev restart +bash deploy/script/start.sh dev clear +``` + +## Public Entry Points + +Default dev ports: +- App UI: `http://localhost:8080` +- gRPC-web: `http://localhost:8080/grpc/` +- Collaboration WS: `ws://localhost:8080/ws/doc/{docId}?token={jwt}` +- MinIO console (via Nginx): `http://localhost:8080/minio/` +- Object public path (via Nginx): `http://localhost:8080/storage/...` +- RabbitMQ management (via Nginx): `http://localhost:8080/rabbitmq/` + +Direct infra ports in dev: +- Postgres: `localhost:5432` +- Redis: `localhost:6379` +- RabbitMQ AMQP: `localhost:5672` +- Consul: `localhost:8500` +- Elasticsearch: `localhost:9200` + +## Message Queue Notes + +- Worker consumers are currently configured to use RabbitMQ backend. +- MQ interface supports Redis and RabbitMQ implementations. +- Redis Pub/Sub does not provide true consumer-group semantics. +- For dirty-doc pipeline, keep `DIRTY_DOC_MQ` as `rabbitmq` or `both` if snapshot-worker should consume events from RabbitMQ. + +## Build and Protobuf + +Manual protobuf generation: +```bash +bash deploy/script/gen_proto.sh +``` + +Generated targets: +- `backend/pkg/gen` +- `collab-go/pkg/gen` +- `frontend/src/gen` +- `collab/src/gen` + +## Repository Structure + +- `backend`: API service, workers, repositories, storage integration +- `frontend`: Vue application +- `collab`: Node.js collaboration core +- `collab-go`: Go WebSocket gateway for collaboration traffic +- `proto`: protobuf contracts +- `deploy`: compose files, scripts, infra templates +- `docs`: project docs diff --git a/README_zh.md b/README_zh.md new file mode 100644 index 0000000..15aea3d --- /dev/null +++ b/README_zh.md @@ -0,0 +1,197 @@ +# 远楒文档 + +远楒文档是一个支持实时协作的文档平台,技术栈为 Go 后端、Vue 3 前端和基于 Yjs 的协作服务。 + +## 运行拓扑 + +核心业务服务: +- `frontend`:Vue 3(Vite) +- `backend`:Go Connect RPC/gRPC 服务 +- `collab-core`:Node.js Yjs 协作核心 +- `collab`:`collab-go` WebSocket 网关 +- `snapshot-worker`:文档快照同步 worker +- `notification-worker`:通知事件消费 worker +- `search-sync-worker`:搜索索引同步 worker + +基础设施服务: +- `postgres` +- `redis` +- `rabbitmq` +- `consul` +- `minio` +- `elasticsearch` +- `nginx`(统一入口) + +## 请求与事件链路 + +主请求链路: +1. 浏览器 -> Nginx +2. Nginx `/` -> Frontend +3. Nginx `/grpc/` -> Backend gRPC-web +4. Backend 按需访问 Postgres/Redis/MinIO/Consul/Elasticsearch/MQ + +实时协作链路: +1. 浏览器 -> Nginx `/ws/doc/{docId}` +2. Nginx -> `collab-go` +3. `collab-go` 校验 JWT 后代理到 `collab-core` +4. `collab-core` 在内存和 Redis 中维护 Yjs 文档状态 + +异步事件链路: +1. `collab-core` 在 Redis 标记脏文档并发布脏文档事件 +2. `snapshot-worker` 消费 RabbitMQ 的 `collab.dirty_docs`(组消费模式),并周期扫描脏集合兜底 +3. `snapshot-worker` 调用 `collab-core` 的 `/internal/yjs/doc-snapshot/{docId}`,落库快照与正文;正文变化时发布搜索同步事件 +4. `search-sync-worker` 消费 `search.sync.document` 并写入 Elasticsearch(ES 启用时) +5. `notification-worker` 消费 `notification.create` 并写入通知记录 + +## 健康检查与优雅停机 + +Backend 探针: +- `/health` +- `/readyz` +- `/livez` + +协作服务探针: +- `collab-core`:`/health`、`/readyz`、`/livez` +- `collab-go`:`/health`、`/readyz`、`/livez` + +停机行为: +- Backend 与协作服务支持 draining + 优雅停机。 +- draining 阶段 readiness 会返回 `not_ready`。 + +## 部署模式 + +`deploy/docker-compose.dev.yml`: +- 源码挂载开发模式 +- 暴露 backend 调试端口(`2345`) +- Postgres/Redis/RabbitMQ/Elasticsearch 端口对宿主机开放 +- `start.sh dev ...` 会自动执行 `deploy/script/gen_proto.sh` + +`deploy/docker-compose.yml`: +- 偏生产形态镜像 +- 对外端口更少 +- backend 与 worker 在镜像构建阶段完成编译 + +## 开发前置依赖 + +`start.sh dev ...` 会在 docker compose 启动前,先在宿主机执行 `deploy/script/gen_proto.sh`。 + +宿主机需要: +- `docker` + `docker compose` +- `go` + `protoc`(生成 Go 桩代码) +- `frontend/node_modules` 中的插件(`protoc-gen-es`、`protoc-gen-connect-es`) +- `PATH` 中可用的 `grpc_tools_node_protoc_plugin`(生成 `collab` 侧 Node gRPC 代码) + +## 配置工作流 + +统一配置源: +- `deploy/.env` +- 模板:`deploy/.env.example` + +交互式初始化/更新: +```bash +bash deploy/script/configure.sh +``` + +`configure.sh` 的作用: +- 交互式收集关键端口、密钥、环境变量 +- 写入/更新 `deploy/.env` +- 由 `VITE_API_BASE_URL` 自动推导 `MINIO_BROWSER_REDIRECT_URL` +- 自动调用 `prepare.sh` + +渲染配置文件: +```bash +bash deploy/script/prepare.sh +``` + +生成文件: +- `backend/config.toml` +- `frontend/nginx.conf` +- `deploy/nginx/nginx.conf` +- `deploy/nginx/conf.d/default.conf` +- `deploy/redis/redis.conf` +- `deploy/rabbitmq/rabbitmq.conf` + +模板文件: +- `backend/config.toml.tmpl` +- `frontend/nginx.conf.tmpl` +- `deploy/nginx/nginx.conf.tmpl` +- `deploy/nginx/conf.d/default.conf.tmpl` +- `deploy/redis/redis.conf.tmpl` +- `deploy/rabbitmq/rabbitmq.conf.tmpl` + +## 快速启动 + +推荐(交互式): +```bash +bash deploy/script/configure.sh +bash deploy/script/start.sh dev up +``` + +非交互: +```bash +cp deploy/.env.example deploy/.env +bash deploy/script/prepare.sh +bash deploy/script/start.sh dev up +``` + +生产模式: +```bash +bash deploy/script/start.sh release up +``` + +backend 镜像启动行为: +- backend 容器会先执行 `migrate`、`db_init`、`es_init`,再启动 `cmd/main`。 + +其他常用动作: +```bash +bash deploy/script/start.sh dev rebuild +bash deploy/script/start.sh dev restart +bash deploy/script/start.sh dev clear +``` + +## 对外入口 + +默认开发环境: +- 主站:`http://localhost:8080` +- gRPC-web:`http://localhost:8080/grpc/` +- 协作 WS:`ws://localhost:8080/ws/doc/{docId}?token={jwt}` +- MinIO 控制台(经 Nginx):`http://localhost:8080/minio/` +- 对象访问路径(经 Nginx):`http://localhost:8080/storage/...` +- RabbitMQ 管理页(经 Nginx):`http://localhost:8080/rabbitmq/` + +开发环境基础设施直连端口: +- Postgres:`localhost:5432` +- Redis:`localhost:6379` +- RabbitMQ AMQP:`localhost:5672` +- Consul:`localhost:8500` +- Elasticsearch:`localhost:9200` + +## MQ 说明 + +- 当前 worker 消费链路按 RabbitMQ 后端运行。 +- MQ 接口层支持 Redis 与 RabbitMQ 两种实现。 +- Redis Pub/Sub 不提供真正的组消费语义。 +- 脏文档链路建议将 `DIRTY_DOC_MQ` 设为 `rabbitmq` 或 `both`,以保证 `snapshot-worker` 能从 RabbitMQ 收到事件。 + +## Protobuf 生成 + +手动生成: +```bash +bash deploy/script/gen_proto.sh +``` + +生成目标: +- `backend/pkg/gen` +- `collab-go/pkg/gen` +- `frontend/src/gen` +- `collab/src/gen` + +## 仓库结构 + +- `backend`:API 服务、worker、仓储层、存储集成 +- `frontend`:Vue 前端 +- `collab`:Node.js 协作核心 +- `collab-go`:Go WebSocket 协作网关 +- `proto`:Protobuf 协议 +- `deploy`:Compose、脚本、基础设施模板 +- `docs`:项目文档