From 9a263e8f33bc7150e5b4b8ebf05c90e4cca65f45 Mon Sep 17 00:00:00 2001 From: Mikhail Iudin Date: Mon, 14 Aug 2023 14:21:20 +0200 Subject: [PATCH] GO-1733 Improve readme --- README.md | 187 ++----------------------------------------- core/DEVELOPMENT.md | 27 ------- docs/Architecture.md | 9 +++ docs/Build.md | 45 +++++++++++ docs/Debug.md | 89 ++++++++++++++++++++ docs/Protogen.md | 14 ++++ docs/Testing.md | 46 +++++++++++ docs/store.md | 55 ------------- docs/userstories.md | 125 ----------------------------- 9 files changed, 210 insertions(+), 387 deletions(-) delete mode 100644 core/DEVELOPMENT.md create mode 100644 docs/Architecture.md create mode 100644 docs/Build.md create mode 100644 docs/Debug.md create mode 100644 docs/Protogen.md create mode 100644 docs/Testing.md delete mode 100644 docs/store.md delete mode 100644 docs/userstories.md diff --git a/README.md b/README.md index edebb6baf..f90b381bc 100644 --- a/README.md +++ b/README.md @@ -1,185 +1,12 @@ # Anytype Heart Middleware library for Anytype, distributed as part of the Anytype clients. -## Build from Source -1. Install Golang 1.21.x [from here](http://golang.org/dl/) or using preferred package manager -2. Follow instructions below for the target systems - - - -### Install local deps - -#### Mac -As of 16.01.23 last protobuf version (21.12) broke the JS plugin support, so you can use the v3 branch: -``` -brew install protobuf@3 -``` - -To generate Swift protobuf: -``` -brew install swift-protobuf -``` - -#### Debian/Ubuntu -We need to have protoc binary (3.x version) and libprotoc headers in orderto build the grpc-web plugin -``` -apt install protobuf-compiler libprotoc-dev -``` - -### Build and install for the [desktop client](https://github.com/anyproto/anytype-ts) -`make install-dev-js` — build the local server and copy it and protobuf binding into `../anytype-ts` - -Parameters: -- `ANY_SYNC_NETWORK=/path/to/network.yml` — build using self-hosted [network configuration](https://tech.anytype.io/anytype-heart/configuration) - -### Build for iOS -Instructions to set up environment for iOS: [here](https://github.com/anyproto/anytype-swift/blob/main/docs/Setup_For_Middleware.md) -1. `make build-ios` to build the framework into `dist/ios` folder - - Parameters: - - `ANY_SYNC_NETWORK=/path/to/network.yml` — build using self-hosted [network configuration](https://tech.anytype.io/anytype-heart/configuration) -2. `make protos-swift` to generate swift protobuf bindings into `dist/ios/pb` - -### Build for Android -Instructions to setup environment for Android: [here](https://github.com/anyproto/anytype-kotlin/blob/main/docs/Setup_For_Middleware.md) -1. `make build-android` to build the library into `dist/android` folder - - Parameters: - - `ANY_SYNC_NETWORK=/path/to/network.yml` — build using self-hosted [network configuration](https://tech.anytype.io/anytype-heart/configuration) -2. `make protos-java` to generate java protobuf bindings into `dist/android/pb` - -## Rebuild protobuf generated files -First, you need to install [protobuf](https://github.com/anyproto/anytype-heart#install-local-deps-mac) pkg using your preferred package manager. -This repo uses custom protoc located at [anyproto/protobuf](https://github.com/anyproto/protobuf/tree/master/protoc-gen-gogo). It adds `gomobile` plugin and some env-controlled options to control the generated code style. -This protobuf generator will replace your `protoc` binary, BTW it doesn't have any breaking changes for other protobuf and grpc code - -You can override the binary with a simple command: -``` -make setup-protoc -``` - -Then you can easily regenerate proto files: -``` -make protos -``` - -## Run tests -Install dependencies for running tests and generate mocks: -``` -make test-deps -``` - -GO test: -``` -make test -``` -You'll need to install latest (at least clang 15) -``` -brew install llvm -echo 'export PATH="//llvm/bin:$PATH"' >> ~/.zshrc -``` - -### Integration tests -First you need to start a docker container via docker-compose: -``` -export ANYTYPE_TEST_GRPC_PORT=31088 -docker-compose up -d -``` - -Then you can run the basic integration tests: -``` -make test-integration -``` - - -## Run local gRPC server to debug -⚠️ Make sure to update/install protobuf compiler from [this repo](https://github.com/anyproto/protobuf) using `make setup-protoc` - -Commands: -- `make run-server` - builds proto files for grpc server, builds the binary and runs it -- `make build-server` - builds proto files for grpc server and builds the binary into `dist/server` - -If you want to change the default port(9999): - -`ANYTYPE_GRPC_ADDR=127.0.0.1:8888 make run-debug` - ----- -## Useful tools for debug - -### Debug server -Use env var ANYDEBUG=address to enable debugging HTTP server. For example: `ANYDEBUG=:6061` will start debug server on port 6061 - -You can find all endpoints in `/debug` page. For example: http://localhost:6061/debug - -### gRPC logging -In order to log mw gRPC requests/responses use `ANYTYPE_GRPC_LOG` env var: -- `ANYTYPE_LOG_LEVEL="grpc=DEBUG" ANYTYPE_GRPC_LOG=1` - log only method names -- `ANYTYPE_LOG_LEVEL="grpc=DEBUG" ANYTYPE_GRPC_LOG=2` - log method names + payloads for commands -- `ANYTYPE_LOG_LEVEL="grpc=DEBUG" ANYTYPE_GRPC_LOG=2` - log method names + payloads for commands&events - -### gRPC tracing -1. Run jaeger UI on the local machine: -```docker run --rm -d -p6832:6832/udp -p6831:6831/udp -p16686:16686 -p5778:5778 -p5775:5775/udp jaegertracing/all-in-one:latest``` -2. Run mw with `ANYTYPE_GRPC_TRACE` env var: -- `ANYTYPE_GRPC_TRACE=1` - log only method names/times -- `ANYTYPE_GRPC_TRACE=2` - log method names + payloads for commands -- `ANYTYPE_GRPC_TRACE=2` - log method names + payloads for commands&events -3. Open Jaeger UI at http://localhost:16686 - -### Debug tree -1. You can use `cmd/debugtree.go` to perform different operations with tree exported in zip archive (`rpc DebugTree`) -2. The usage looks like this `go run debugtree.go -j -t -f [path to zip archive]` where `-t` tells the cmd to generate tree graph view and `-j` - to generate json representation of the tree (i.e. data in each individual block) -3. You can use flag `-r` to build the tree from its root, that way you will see all the changes in the tree, and not only those from the common snapshot -3. For more info please check the command usage in `debugtree.go` - -### gRPC clients - -#### GUI - -https://github.com/uw-labs/bloomrpc - -HowTo: Set the import path to the middleware root, then select commands.proto file - -#### CLI - -https://github.com/fullstorydev/grpcurl - -You should specify import-path to the root of anytype-heart repository and gRPC port of running application - -Command examples: - -- List available methods -``` -grpcurl -import-path ../anytype-heart/ -proto pb/protos/service/service.proto localhost:31007 describe -``` - -- Describe method signature -``` -grpcurl -import-path ../anytype-heart/ -proto pb/protos/service/service.proto localhost:31007 describe anytype.ClientCommands.ObjectCreate -``` - -- Describe structure of specified protobuf message -``` -grpcurl -import-path ../anytype-heart/ -proto pb/protos/service/service.proto localhost:31007 describe .anytype.Rpc.Object.Create.Request -``` - -- Call method with specified plain-text payload -``` -grpcurl -import-path ../anytype-heart/ -proto pb/protos/service/service.proto -plaintext -d '{"details": {"name": "hello there", "type": "ot-page"}}' localhost:31007 anytype.ClientCommands.ObjectCreate -``` - -- Call method using unix pipe -``` -echo '{"details": {"name": "hello there", "type": "ot-page"}}' | grpcurl -import-path ../anytype-heart/ -proto pb/protos/service/service.proto -plaintext -d @ localhost:31007 anytype.ClientCommands.ObjectCreate -``` - -## Running with prometheus and grafana -- `cd metrics/docker` – cd into folder with docker-compose file -- `docker-compose up` - run the prometheus/grafana -- use `ANYTYPE_PROM=0.0.0.0:9094` when running middleware to enable metrics collection. Client commands metrics available only in gRPC mode -- open http://127.0.0.1:3000 to view collected metrics in Grafana. You can find several dashboards there: - - **MW** internal middleware metrics such as changes, added and created threads histograms - - **MW commands server** metrics for clients commands. Works only in grpc-server mode +## Docs +- [Build instructions](docs/Build.md) +- [Protobuf generation](docs/Protogen.md) +- [Testing instructions](docs/Testing.md) +- [Debug instructions](docs/Debug.md) +- [Project architecture](docs/Architecture.md) ## Contribution Thank you for your desire to develop Anytype together! @@ -195,4 +22,4 @@ Thank you for your desire to develop Anytype together! --- Made by Any — a Swiss association 🇨🇭 -Licensed under [Any Source Available License 1.0](./LICENSE.md). +Licensed under [Any Source Available License 1.0](LICENSE.md). diff --git a/core/DEVELOPMENT.md b/core/DEVELOPMENT.md deleted file mode 100644 index 02ea2f496..000000000 --- a/core/DEVELOPMENT.md +++ /dev/null @@ -1,27 +0,0 @@ -# Development - -## Services/components -### Bootstrapping -If you need your component to be visible to other components, you need to register it in Service Locator's registry. -To do it go to `Bootstrap` function in `core/anytype/bootstrap.go` and `Register` it - -### Dependency injection -We use our own implementation of Service Locator pattern: `github.com/anyproto/any-sync/app`. - -## Writing tests - -### Structure of tests -Prefer structuring your tests in Act-Arrange-Assert style. Use comments for visual separation of those test parts, like: -```go -// Given -... -// When -... -// Then -``` - -### Fixtures for services under test -Define `fixture` structure to easily bootstrap service and its dependencies. You can find examples in our code. - -### Mocking -Prefer using Mockery for new mocks. It's configured in `.mockery.yaml` diff --git a/docs/Architecture.md b/docs/Architecture.md new file mode 100644 index 000000000..24717c738 --- /dev/null +++ b/docs/Architecture.md @@ -0,0 +1,9 @@ +# Architecture + +## Services/components +### Bootstrapping +If you need your component to be visible to other components, you need to register it in Service Locator's registry. +To do it go to `Bootstrap` function in `core/anytype/bootstrap.go` and `Register` it + +### Dependency injection +We use our own implementation of Service Locator pattern: `github.com/anyproto/any-sync/app`. \ No newline at end of file diff --git a/docs/Build.md b/docs/Build.md new file mode 100644 index 000000000..eeafe1548 --- /dev/null +++ b/docs/Build.md @@ -0,0 +1,45 @@ +# Build instructions +## Build from Source +1. Install Golang 1.21.x [from here](http://golang.org/dl/) or using preferred package manager +2. Follow instructions below for the target systems + +### Install local deps + +#### Mac +As of 16.01.23 last protobuf version (21.12) broke the JS plugin support, so you can use the v3 branch: +``` +brew install protobuf@3 +``` + +To generate Swift protobuf: +``` +brew install swift-protobuf +``` + +#### Debian/Ubuntu +We need to have protoc binary (3.x version) and libprotoc headers in orderto build the grpc-web plugin +``` +apt install protobuf-compiler libprotoc-dev +``` + +### Build and install for the [desktop client](https://github.com/anyproto/anytype-ts) +`make install-dev-js` — build the local server and copy it and protobuf binding into `../anytype-ts` + +Parameters: +- `ANY_SYNC_NETWORK=/path/to/network.yml` — build using self-hosted [network configuration](https://tech.anytype.io/anytype-heart/configuration) + +### Build for iOS +Instructions to set up environment for iOS: [here](https://github.com/anyproto/anytype-swift/blob/main/docs/Setup_For_Middleware.md) +1. `make build-ios` to build the framework into `dist/ios` folder + + Parameters: + - `ANY_SYNC_NETWORK=/path/to/network.yml` — build using self-hosted [network configuration](https://tech.anytype.io/anytype-heart/configuration) +2. `make protos-swift` to generate swift protobuf bindings into `dist/ios/pb` + +### Build for Android +Instructions to setup environment for Android: [here](https://github.com/anyproto/anytype-kotlin/blob/main/docs/Setup_For_Middleware.md) +1. `make build-android` to build the library into `dist/android` folder + + Parameters: + - `ANY_SYNC_NETWORK=/path/to/network.yml` — build using self-hosted [network configuration](https://tech.anytype.io/anytype-heart/configuration) +2. `make protos-java` to generate java protobuf bindings into `dist/android/pb` \ No newline at end of file diff --git a/docs/Debug.md b/docs/Debug.md new file mode 100644 index 000000000..783f9ff5e --- /dev/null +++ b/docs/Debug.md @@ -0,0 +1,89 @@ +# Debug +## Run local gRPC server to debug +⚠️ Make sure to update/install protobuf compiler from [this repo](https://github.com/anyproto/protobuf) using `make setup-protoc` + +Commands: +- `make run-server` - builds proto files for grpc server, builds the binary and runs it +- `make build-server` - builds proto files for grpc server and builds the binary into `dist/server` + +If you want to change the default port(9999): + +`ANYTYPE_GRPC_ADDR=127.0.0.1:8888 make run-debug` + +---- +## Useful tools for debug + +### Debug server +Use env var ANYDEBUG=address to enable debugging HTTP server. For example: `ANYDEBUG=:6061` will start debug server on port 6061 + +You can find all endpoints in `/debug` page. For example: http://localhost:6061/debug + +### gRPC logging +In order to log mw gRPC requests/responses use `ANYTYPE_GRPC_LOG` env var: +- `ANYTYPE_LOG_LEVEL="grpc=DEBUG" ANYTYPE_GRPC_LOG=1` - log only method names +- `ANYTYPE_LOG_LEVEL="grpc=DEBUG" ANYTYPE_GRPC_LOG=2` - log method names + payloads for commands +- `ANYTYPE_LOG_LEVEL="grpc=DEBUG" ANYTYPE_GRPC_LOG=2` - log method names + payloads for commands&events + +### gRPC tracing +1. Run jaeger UI on the local machine: + ```docker run --rm -d -p6832:6832/udp -p6831:6831/udp -p16686:16686 -p5778:5778 -p5775:5775/udp jaegertracing/all-in-one:latest``` +2. Run mw with `ANYTYPE_GRPC_TRACE` env var: +- `ANYTYPE_GRPC_TRACE=1` - log only method names/times +- `ANYTYPE_GRPC_TRACE=2` - log method names + payloads for commands +- `ANYTYPE_GRPC_TRACE=2` - log method names + payloads for commands&events +3. Open Jaeger UI at http://localhost:16686 + +### Debug tree +1. You can use `cmd/debugtree.go` to perform different operations with tree exported in zip archive (`rpc DebugTree`) +2. The usage looks like this `go run debugtree.go -j -t -f [path to zip archive]` where `-t` tells the cmd to generate tree graph view and `-j` - to generate json representation of the tree (i.e. data in each individual block) +3. You can use flag `-r` to build the tree from its root, that way you will see all the changes in the tree, and not only those from the common snapshot +3. For more info please check the command usage in `debugtree.go` + +### gRPC clients + +#### GUI + +https://github.com/uw-labs/bloomrpc + +HowTo: Set the import path to the middleware root, then select commands.proto file + +#### CLI + +https://github.com/fullstorydev/grpcurl + +You should specify import-path to the root of anytype-heart repository and gRPC port of running application + +Command examples: + +- List available methods +``` +grpcurl -import-path ../anytype-heart/ -proto pb/protos/service/service.proto localhost:31007 describe +``` + +- Describe method signature +``` +grpcurl -import-path ../anytype-heart/ -proto pb/protos/service/service.proto localhost:31007 describe anytype.ClientCommands.ObjectCreate +``` + +- Describe structure of specified protobuf message +``` +grpcurl -import-path ../anytype-heart/ -proto pb/protos/service/service.proto localhost:31007 describe .anytype.Rpc.Object.Create.Request +``` + +- Call method with specified plain-text payload +``` +grpcurl -import-path ../anytype-heart/ -proto pb/protos/service/service.proto -plaintext -d '{"details": {"name": "hello there", "type": "ot-page"}}' localhost:31007 anytype.ClientCommands.ObjectCreate +``` + +- Call method using unix pipe +``` +echo '{"details": {"name": "hello there", "type": "ot-page"}}' | grpcurl -import-path ../anytype-heart/ -proto pb/protos/service/service.proto -plaintext -d @ localhost:31007 anytype.ClientCommands.ObjectCreate +``` + +## Running with prometheus and grafana +- `cd metrics/docker` – cd into folder with docker-compose file +- `docker-compose up` - run the prometheus/grafana +- use `ANYTYPE_PROM=0.0.0.0:9094` when running middleware to enable metrics collection. Client commands metrics available only in gRPC mode +- open http://127.0.0.1:3000 to view collected metrics in Grafana. You can find several dashboards there: + - **MW** internal middleware metrics such as changes, added and created threads histograms + - **MW commands server** metrics for clients commands. Works only in grpc-server mode \ No newline at end of file diff --git a/docs/Protogen.md b/docs/Protogen.md new file mode 100644 index 000000000..ede14fa6a --- /dev/null +++ b/docs/Protogen.md @@ -0,0 +1,14 @@ +## Rebuild protobuf generated files +First, you need to install [protobuf](https://github.com/anyproto/anytype-heart#install-local-deps-mac) pkg using your preferred package manager. +This repo uses custom protoc located at [anyproto/protobuf](https://github.com/anyproto/protobuf/tree/master/protoc-gen-gogo). It adds `gomobile` plugin and some env-controlled options to control the generated code style. +This protobuf generator will replace your `protoc` binary, BTW it doesn't have any breaking changes for other protobuf and grpc code + +You can override the binary with a simple command: +``` +make setup-protoc +``` + +Then you can easily regenerate proto files: +``` +make protos +``` \ No newline at end of file diff --git a/docs/Testing.md b/docs/Testing.md new file mode 100644 index 000000000..42bc8128d --- /dev/null +++ b/docs/Testing.md @@ -0,0 +1,46 @@ +# Testing +## Run tests +Install dependencies for running tests and generate mocks: +``` +make test-deps +``` + +GO test: +``` +make test +``` +You'll need to install latest (at least clang 15) +``` +brew install llvm +echo 'export PATH="//llvm/bin:$PATH"' >> ~/.zshrc +``` + +### Integration tests +First you need to start a docker container via docker-compose: +``` +export ANYTYPE_TEST_GRPC_PORT=31088 +docker-compose up -d +``` + +Then you can run the basic integration tests: +``` +make test-integration +``` + +## Writing tests + +### Structure of tests +Prefer structuring your tests in Act-Arrange-Assert style. Use comments for visual separation of those test parts, like: +```go +// Given +... +// When +... +// Then +``` + +### Fixtures for services under test +Define `fixture` structure to easily bootstrap service and its dependencies. You can find examples in our code. + +### Mocking +Prefer using Mockery for new mocks. It's configured in `.mockery.yaml` \ No newline at end of file diff --git a/docs/store.md b/docs/store.md deleted file mode 100644 index 5e78f9275..000000000 --- a/docs/store.md +++ /dev/null @@ -1,55 +0,0 @@ -### Store - -Должна быть некоторая структура, которая будет хранить состояние приложения, а именно: - -1. Какие документы/блоки с какими версиями сохранены. -2. Какие экраны были открыты в последний раз, какие окна. -3. Все настройки клиента, которые не сохраняются в IPFS, должны быть в этой структуре состояния. -4. В каких поля ввода что содержится. - -Когда Middleware штатно/аварийно завершает своё выполнение, при следующем запуске состояние должно восстанавливаться из этого файла. - -Раз в несколько секунд middle записывает своё состояние в этот файл. - -#### Наверное, плохая идея: store описан в .proto, клиент имеет к нему доступ - -Плохая, потому что иначе на клиенте придется продублировать много функционала с middle, клиент должен быть абстрагирован от этой логики. - -#### Получится-ли сходу реализовать соответствие files <--> documents/blocks - -А что, если вот так: -1. Есть центральная директория /Anytype, в которой лежат папки документов – на каждый документ по папке. -2. В папке документа лежат файлы – по файлу на каждый блок. Если у документа есть внутренние документы, то там же, соответственно, лежат соответствующие им папки. Плюс лежит .json файл, который содержит структурную информацию документа. Тоже типа такой блок. -3. В папке лежит .git папка, в которой содержится история версий. - -Так вот, пишем watcher, который следит за изменениями как внутри файловой системы в директории /Anytype, так и за изменениями, сделанными в приложени Anytype, и автоматически коммитит изменения, меняет файлы. - -То есть, например, скидываем картинки в папку /Anytype/kitties, и автоматом все юзеры, кто работает с этим документом, получают новые блоки с картинками. - -Текстовые файлы, например, хранятся в виде markdown файлов. -Информация о том, как отображать картинку, может хранится в meta-блоке изображения. - -В идеале сделать так, чтобы информация по минимуму дублировалась. Однако мы не ограничены в использовании дополнительных файлов, которые будут хранить какие-то промежуточные представления, если они не будут содержать тяжелый контент. - -#### Как это заимплементить, MVP -Документ состоит только из текстовых блоков. -Блоки и документ – каждый имеет свою историю версий. -Есть чейн изменений блока, и есть его скомпилированный стейт. Скомпилированный стейт – .md файл. Чейн изменений – файлы в специальной директории. - -Или так – блоки и документы хранятся на одном уровне иерархии, а в папке документа хранятся ссылки на эти блоки/файлы. - -Есть директория /anytype. -CLI-клиент, в котором есть команды: - -```js - block_create() -> docId - block_set(id, 'text') - block_remove(id) - - doc_create() -> docId - doc_addBlock(docId, id, prior) - doc_setPrior(docId, id, prior) - doc_removeBlock(docId, id) -``` - -Есть watcher. Это JS-скрипт, который чекает изменения файлов в папке. diff --git a/docs/userstories.md b/docs/userstories.md deleted file mode 100644 index 89a93869c..000000000 --- a/docs/userstories.md +++ /dev/null @@ -1,125 +0,0 @@ -### User stories - -#### 0. Как ответы задавать -```js -// 1. Избыточная информация, плюс Result получится слишком кастомным -Package (id:'0x765', Reply {to:'0x123', error:Error{ type:WRONG_MNEMONIC, message:'Mnemonic is wrong' }, Result:{ type:FAILURE }}) -// 2. Сообщение тоже получается ибыточным. из Error.type мы можем его получать на клиенте, плюс локализация -Package (id:'0x765', Status{ type:WRONG_MNEMONIC, message:'Mnemonic is wrong' }) -// 3. -Package (id:'0x765', Error{ type:WRONG_MNEMONIC }) -Package (id:'0x765', Success{}) -// 4. -Package (id:'0x765', Status{ type:WRONG_MNEMONIC }) -Package (id:'0x765', Status{ type:SUCCESS }) -``` - -Выбрали четвертый вариант - -#### 1. Log in - -```js -// 1. Клиент передает мнемонику в middle, которую ввел пользователь -Front: Package (id:'0x123', WalletLogin { mnemonic:'abc def ... xyz', pin:'12345'} ) -Middle: Package (id:'0x980', Status { replyTo:'0x123', type:SUCCESS }) -// 2. Middle начинает слать аккаунты -Middle: Package (id:'0x789', AccountFound { Account {name:'Pablo', id:'0xabcabc', icon:'0x123123'}}}) -Middle: Package (id:'0x678', AccountFound{ Account {name:'Carlito', id:'0xabcabc', icon:'0x123123'}}) -// 2.B. Middle сообщает об ошибке -Middle: Package (id:'0x765', Status { replyTo'0x123': type: WRONG_MNEMONIC }) -// 3. Клиент отправляет аккаунт, под которым хочет работать -Front: Package (id:'0x789', AccountSelect {id:'0xabcabc'}}) -Middle: Package (id:'0x777', Status { replyTo'0x789': type: SUCCESS }) -``` - -#### 2. Sign up -```js -// 1. Просим создать аккаунт -Front: Package (id:'0x123', WalletCreate {} ) -Middle: Package (id:'0x980', Status { replyTo'0x123': type: SUCCESS }) - -Front: Package (id:'0x345', AccountCreate { name:'Carlos', icon:'0x1231243257', pin:'1232724'} ) -Middle: Package (id:'0x456', Status { replyTo'0x345': type: SUCCESS }) -``` - -#### 3A. Получение списка документов (если store контролирует клиент) -Нужно получить список id документов, их имена, аватарки, хеши последних актуальных версий -Когда нужен этот сценарий? Когда юзер хочет запустить главный экран. - -1. Юзер запустил приложение. Middle уже авторизован, пока ничего не отрисовано -2. Фронт сообщает о том, какие у него документы есть - -```js - Front: Message StartUp (docs: [ - {root:0x345, last_ver:0x123}, - {root:0x456, last_ver:0x234}, - ...]) -``` - -3. Миддл сообщает, какие документы поменяли имена/аватарки, присылает их, актуальная ли версия хранимого документа, и если нет, то какая актуальная (или массив хешей CRDT-изменений, которые нужно скачать для восстановления до актуальной версии) - -```js - Middle: Message StartUp reply (docs: [ - {root:0x345, status:last_version}, - {root:0x456, status:outdated, name:same, icon:b64(newIcon.png), lastVersion:0x789}, - ...]) -``` - -4. Клиент применяет полученные изменения и отображает список документов - -#### 3B. Получение списка документов (если store контролирует middle) -Не вижу проблемы, если middle будет контролировать store. Плюсы – логика с клиента переходит на middle. - -1. Юзер запустил приложение. Middle уже авторизован, пока ничего не отрисовано -2. Клиент сообщает, что он запустился - -```js - Front: Message StartUp () -``` - -3. Middle отдает данные, которые нужно отрисовать на главной странице – список документов - -```js - Middle: Message DocumentsOrganizier (docs: [ - {name:'Doc 1', version:0x123, icon:icon1.png}, - {name:'Doc 2', version:0x234, icon:icon2.png}, - ...]) -``` - -Логика по получению актуальных версий, сверки и прочего полностью абстрагирована от клиента. - -4. Клиент просто отрисовывает полученные данные. - -##### Cообщения сценария -1. Сообщение, которым клиент сообщает, что ему нужен отрисовать список документов. Возникает в сценариях, когда мы на главном меню, плюс, возможно, в других сценариях (например, какое-то всплывающее контекстное меню, в котором отображаются документы). -2. Сообщение, в котором middle передает список всех документов. - -```js - // С помощью запроса с entity == docHeaders можно запросить список документов - // Выделять отдельное в сообщение DocumentsRequest не вижу смысла, оно слишком тривиальное получится - message Request { - string id = 0; - string entity = 1; - string target = 2; - } - - // когда приходит DocHeaders, автоматом на фронте отрисовывается соответствующий target с docHeaders. - message DocHeaders { - string id = 0; - repeated DocHeader docHeaders = 1; - } - - message DocHeader { - string id = 0; - string name = 1; - string root = 2; - string version = 3; - string iconName = 4; - } -``` - -#### 4. Получение документа -1. Юзер находится в главном меню и видит список документов. Юзер нажимает на один из них -2. Клиент отправляет сообщение `Request { entity:document, target:0x123123 }` -3. Middle отправляет сообщение `Document { root:0x123123, ..., blocks:[...] }` -4. Клиент отрисовывает документ. \ No newline at end of file