From 1e094c71cb1e6ba23187b5e02bf37008adddd9c0 Mon Sep 17 00:00:00 2001 From: gas-coder <59146585+gas-coder@users.noreply.github.com> Date: Sun, 26 Oct 2025 01:01:42 +0500 Subject: [PATCH 1/3] Create rest_api.yml MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Добавлен файл rest_api.yaml --- api/rest_api.yml | 455 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 455 insertions(+) create mode 100644 api/rest_api.yml diff --git a/api/rest_api.yml b/api/rest_api.yml new file mode 100644 index 0000000..d28d535 --- /dev/null +++ b/api/rest_api.yml @@ -0,0 +1,455 @@ +openapi: 3.0.0 + +tags: + - name: Posts + - name: Subscriptions + - name: Engagement + - name: Feed + - name: Destinations + +info: + title: Travel Platform API + description: API для работы с приложением для путешественников + version: 1.0.0 + +paths: + /api/v1/posts: + post: + summary: Создать новый пост о путешествии + description: Если пользователь не лайкал пост - лайк добавляется. Если пользователь лайкал пост - лакй удаляется + tags: + - Posts + requestBody: + required: true + content: + application/json: + schema: + type: object + properties: + description: + type: string + maxLength: 1000 + example: "Текст поста" + photoUrls: + type: array + items: + type: string + items: + type: string + format: uri + minItems: 1 + maxItems: 10 + example: ["https://cdn.example.com/photo1.jpg", "https://cdn.example.com/photo2.jpg"] + location: + type: object + properties: + id: + type: string + example: "123" + name: + type: string + example: "Какое-то описание" + latitude: + type: number + format: float + example: 44.4444 + longitude: + type: number + format: float + example: 33.3333 + required: + - name + required: + - description + - photoUrls + - location + responses: + 200: + description: Ok + content: + application/json: + schema: + $ref: '#/components/schemas/Post' + 400: + description: Некорректные данные + 401: + description: Пользователь не авторизован + + /api/v1/users/{id}/subscribes: + post: + summary: Подписаться или отписаться от путешественника + description: Если нет подписки на пользователя - подписка. Если есть подписка на пользователя - отписка + tags: + - Subscriptions + parameters: + - name: id + in: path + required: true + schema: + type: string + description: Идентификатор путешественника + responses: + 200: + description: Ok + content: + application/json: + schema: + type: object + properties: + subscribed: + type: boolean + example: true + subscribersCount: + type: integer + example: 10 + required: + - subscribed + 401: + description: Пользователь не авторизован + 404: + description: Пользователь не найден + + /api/v1/posts/{id}/like: + post: + summary: Поставить или убрать лайк с поста + description: Если пользователь не лайкал пост - лайк добавляется. Если пользователь лайкал пост - лайк удаляется + tags: + - Engagement + parameters: + - name: id + in: path + required: true + schema: + type: string + description: Идентификатор поста + responses: + 200: + description: Ok + content: + application/json: + schema: + type: object + properties: + liked: + type: boolean + example: true + likesCount: + type: integer + example: 1 + required: + - liked + - likesCount + examples: + response: + value: + liked: true + likesCount: 1 + 401: + description: Пользователь не авторизован + 404: + description: Пост не найден + + /api/v1/posts/{id}/comments: + post: + summary: Добавить комменарий к посту + description: Добавляет комментарий к посту пользователя + tags: + - Engagement + parameters: + - name: id + in: path + required: true + schema: + type: string + description: Идентификатор поста + requestBody: + required: true + content: + application/json: + schema: + type: object + properties: + content: + type: string + minLength: 1 + maxLength: 1000 + example: "Какой-то комментарий" + required: + - content + responses: + 201: + description: Ok + content: + application/json: + schema: + $ref: '#/components/schemas/Comment' + 400: + description: Некорректные данные + 401: + description: Пользователь не авторизован + 404: + description: Пост не найден + + /api/v1/feed/global: + get: + summary: Получить глобальную ленту путешественников + description: Возвращает глобальную ленту путешесвенников в обратном хронологическом порядке + tags: + - Feed + parameters: + - name: limit + in: query + description: Количество записей на странице (макс. 30) + schema: + type : integer + default: 10 + minimum: 1 + maximum: 30 + - name: offset + in: query + description: Смещение для пагинации + schema: + type : integer + default: 0 + minimum: 0 + responses: + 200: + description: Список постов + 401: + description: Пользователь не авторизован + + /api/v1/destinations/popular: + get: + summary: Получить список популярных мест для путешествий + description: Возвращает списко популярныхы мест для путешествий + tags: + - Destinations + parameters: + - name: limit + in: query + description: Количество возвращаемых мест (макс. 100) + schema: + type : integer + default: 20 + minimum: 1 + maximum: 100 + responses: + 200: + description: Список популярных мест + content: + application/json: + schema: + type: object + properties: + items: + type: array + items: + $ref: '#/components/schemas/Destination' + total: + type: integer + example: 150 + required: + - items + - total + 400: + description: Некорректные параметры запроса + + /api/v1/destinations/{id}/posts: + get: + summary: Получить посты, привязанные к конкретному месту + description: Возвращает список постов, привязанных к конкретному месту + tags: + - Destinations + parameters: + - name: id + in: path + required: true + schema: + type: string + description: Идентификатор места + - name: limit + in: query + description: Количество постов на странице + schema: + type : integer + default: 20 + minimum: 1 + maximum: 50 + - name: offset + in: query + schema: + type: integer + default: 0 + minimum: 0 + description: Смещение для пагинации + responses: + 200: + description: Список постов для указанного места + content: + application/json: + schema: + type: object + properties: + items: + type: array + items: + $ref: '#/components/schemas/Post' + total: + type: integer + example: 87 + limit: + type: integer + example: 20 + offset: + type: integer + example: 0 + required: + - items + - total + - limit + - offser + 404: + description: Место не найдено + + /api/v1/feed/subscriptions: + get: + summary: Получить ленту по подписчикам + description: Возвращает ленту путешесвенников, на которых подписан текущий пользователь, в обратном хронологическом порядке + tags: + - Feed + parameters: + - name: limit + in: query + description: Количество записей на странице (макс. 30) + schema: + type : integer + default: 10 + minimum: 1 + maximum: 30 + - name: offset + in: query + description: Смещение для пагинации + schema: + type : integer + default: 0 + minimum: 0 + responses: + 200: + description: Список постов + 401: + description: Пользователь не авторизован + +components: + schemas: + Comment: + type: object + properties: + id: + type: string + example: "123" + authorId: + type: string + example: "456" + content: + type: string + example: "Какой-то комментарий" + createdAt: + type: string + format: date-time + example: "2024-06-10T15:45:00Z" + postId: + type: string + example: "789" + required: + - id + - authorId + - authorName + - content + - createdAt + - postId + + Destination: + type: object + properties: + id: + type: string + example: "123" + name: + type: string + example: "Наименование постов" + country: + type: string + example: "Италия" + latitude: + type: number + format: float + example: 44.4444 + longitude: + type: number + format: float + example: 33.3333 + postCount: + type: integer + example: 1200 + previewPhotoUrl: + type: string + format: uri + example: "https://cdn.travelapp.com.italy-review.jpg" + required: + - id + - name + - country + - latitude + - longitude + - postCount + + Post: + type: object + properties: + id: + type: string + example: "123" + authorId: + type: string + example: "456" + authorName: + type: string + example: "Иванов Иван" + description: + type: string + example: "Какое-то описание" + photoUrls: + type: array + items: + type: string + format: uri + example: ["https://cdn.example.com/photo1.jpg"] + location: + type: object + properties: + id: + type: string + example: "123" + name: + type: string + example: "Наименование локации" + latitude: + type: number + format: float + example: 44.4444 + longitude: + type: number + format: float + example: 33.3333 + publishedAt: + type: string + format: date-time + example: "2024-06-12T11:00:00Z" + required: + - id + - authorId + - authorName + - description + - photoUrls + - location + - publishedAt From bf5e19e1258daeb8410981b4959d4a7735cad731 Mon Sep 17 00:00:00 2001 From: gas-coder <59146585+gas-coder@users.noreply.github.com> Date: Sat, 1 Nov 2025 01:58:02 +0500 Subject: [PATCH 2/3] Update rest_api.yml MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Обработаны все комментарии --- api/rest_api.yml | 472 ++++++++++++++++++++++++++++++++++++----------- 1 file changed, 369 insertions(+), 103 deletions(-) diff --git a/api/rest_api.yml b/api/rest_api.yml index d28d535..11b320c 100644 --- a/api/rest_api.yml +++ b/api/rest_api.yml @@ -5,7 +5,9 @@ tags: - name: Subscriptions - name: Engagement - name: Feed - - name: Destinations + - name: Comments + - name: Reactions + - name: Media info: title: Travel Platform API @@ -74,11 +76,13 @@ paths: description: Некорректные данные 401: description: Пользователь не авторизован + 500: + description: Внутренняя ошибка сервера /api/v1/users/{id}/subscribes: post: - summary: Подписаться или отписаться от путешественника - description: Если нет подписки на пользователя - подписка. Если есть подписка на пользователя - отписка + summary: Подписаться на путешественника + description: Создает подписку текущего пользователя на указанного путешественника tags: - Subscriptions parameters: @@ -104,15 +108,56 @@ paths: example: 10 required: - subscribed + - subscribersCount 401: description: Пользователь не авторизован 404: description: Пользователь не найден + 500: + description: Внутренняя ошибка сервера + + delete: + summary: Отписаться от путешественника + description: Удаляет подписку текущего пользователя на указанного путешественника + tags: + - Subscriptions + parameters: + - name: id + in: path + required: true + schema: + type: string + description: Идентификатор путешественника + responses: + 200: + description: Ок + content: + application/json: + schema: + type: object + properties: + subscribed: + type: boolean + example: false + subscribersCount: + type: integer + example: 9 + required: + - subscribed + - subscribersCount + 400: + description: Некорректные данные + 401: + description: Пользователь не авторизован + 404: + description: Путешественник с указанным ID не найден + 500: + description: Внутрення ошибка сервера - /api/v1/posts/{id}/like: + /api/v1/posts/{id}/reaction: post: - summary: Поставить или убрать лайк с поста - description: Если пользователь не лайкал пост - лайк добавляется. Если пользователь лайкал пост - лайк удаляется + summary: Поставить лайк на пост + description: Создает лайк текущего пользователя у указанного поста tags: - Engagement parameters: @@ -130,24 +175,69 @@ paths: schema: type: object properties: - liked: + reaction: type: boolean example: true - likesCount: + reactionsCount: type: integer example: 1 required: - - liked - - likesCount + - reaction + - reactionsCount examples: response: value: - liked: true - likesCount: 1 + reaction: true + reactionsCount: 1 401: description: Пользователь не авторизован 404: description: Пост не найден + 500: + description: Внутренняя ошибка сервера + + delete: + summary: Убрать реакцию с поста + description: Удаляет лайк текущего пользователя с указанного поста + tags: + - Engagement + parameters: + - name: id + in: path + required: true + schema: + type: string + description: Идентификатор поста + responses: + 200: + description: OK + content: + application/json: + schema: + type: object + properties: + reaction: + type: boolean + example: false + reactionsCount: + type: integer + example: 0 + required: + - reaction + - reactionsCount + examples: + response: + value: + reaction: false + reactionsCount: 0 + 400: + description: Невозможно удалить реакцию + 401: + description: Пользователь не авторизован + 404: + description: Пост не найден + 500: + description: Внутренняя ошибка сервера /api/v1/posts/{id}/comments: post: @@ -189,11 +279,87 @@ paths: description: Пользователь не авторизован 404: description: Пост не найден + 500: + description: Внутренняя ошибка сервера - /api/v1/feed/global: + /api/v1/posts: get: - summary: Получить глобальную ленту путешественников - description: Возвращает глобальную ленту путешесвенников в обратном хронологическом порядке + summary: Получить список постов с возможностью фильтрации + description: + Возвращает список постов + - Если указан `destinationId`, возвращаются посты, привязанные к этому месту + - Если `destinationId` не указан — возвращается глобальная лента (все посты) + - Если указан `feed=popular-destinations` — возвращает посты из популярных мест + Поддерживает пагинацию. + tags: + - Posts + parameters: + - name: destinationId + in: query + required: false + schema: + type: string + description: Идентификатор места. Если не указан — возвращаются все посты + - name: feed + in: query + required: false + schema: + type: string + enum: + - popular-destinations + description: Специальные типы лент. Например, "popular-destinations" — посты из популярных мест. + - name: limit + in: query + description: Количество постов на странице + schema: + type: integer + default: 20 + minimum: 1 + maximum: 50 + - name: offset + in: query + schema: + type: integer + default: 0 + minimum: 0 + description: Смещение для пагинации + responses: + 200: + description: Список постов + content: + application/json: + schema: + type: object + properties: + items: + type: array + items: + $ref: '#/components/schemas/Post' + total: + type: integer + example: 150 + limit: + type: integer + example: 20 + offset: + type: integer + example: 0 + required: + - items + - total + - limit + - offset + 400: + description: Некорректные параметры запроса + 404: + description: Указанное место не найдено + 500: + description: Внутренняя ошибка сервера + + /api/v1/feed/subscriptions: + get: + summary: Получить ленту по подписчикам + description: Возвращает ленту путешесвенников, на которых подписан текущий пользователь, в обратном хронологическом порядке tags: - Feed parameters: @@ -217,25 +383,40 @@ paths: description: Список постов 401: description: Пользователь не авторизован + 500: + description: Внутренняя ошибка сервера - /api/v1/destinations/popular: + /api/v1/posts/{postId}/comments: get: - summary: Получить список популярных мест для путешествий - description: Возвращает списко популярныхы мест для путешествий + summary: Получить комментарии к посту + description: Возвращает комментарии, созданные к посту tags: - - Destinations + - Comments parameters: + - name: postId + in: path + required: true + schema: + type: string + description: Идентификатор поста - name: limit in: query - description: Количество возвращаемых мест (макс. 100) schema: - type : integer + type: integer default: 20 minimum: 1 maximum: 100 + description: Количество комментариев на странице + - name: offset + in: query + schema: + type: integer + default: 0 + minimum: 0 + description: Смещение для пагинации responses: 200: - description: Список популярных мест + description: Список комментариев content: application/json: schema: @@ -244,37 +425,47 @@ paths: items: type: array items: - $ref: '#/components/schemas/Destination' + $ref: '#/components/schemas/Comment' total: type: integer - example: 150 - required: + example: 42 + limit: + type: integer + example: 20 + offset: + type: integer + example: 0 + required: - items - total - 400: - description: Некорректные параметры запроса - - /api/v1/destinations/{id}/posts: + - limit + - offset + 404: + description: Пост не найден + 500: + description: Внутренняя ошибка сервера + + /api/v1/posts/{postId}/reactions: get: - summary: Получить посты, привязанные к конкретному месту - description: Возвращает список постов, привязанных к конкретному месту + summary: Получить реакции (лайки) на пост + description: Возвращает лайки к посту tags: - - Destinations + - Reactions parameters: - - name: id + - name: postId in: path required: true schema: type: string - description: Идентификатор места + description: Идентификатор поста - name: limit in: query - description: Количество постов на странице schema: - type : integer - default: 20 + type: integer + default: 50 minimum: 1 - maximum: 50 + maximum: 200 + description: Максимальное количество реакций - name: offset in: query schema: @@ -284,7 +475,7 @@ paths: description: Смещение для пагинации responses: 200: - description: Список постов для указанного места + description: Список реакций content: application/json: schema: @@ -293,51 +484,52 @@ paths: items: type: array items: - $ref: '#/components/schemas/Post' + $ref: '#/components/schemas/Reaction' total: type: integer - example: 87 + example: 128 limit: type: integer - example: 20 + example: 50 offset: type: integer example: 0 - required: + required: - items - total - limit - - offser + - offset 404: - description: Место не найдено - - /api/v1/feed/subscriptions: + description: Пост не найден + 500: + description: Внутренняя ошибка сервера + + /api/v1/posts/{postId}/media: get: - summary: Получить ленту по подписчикам - description: Возвращает ленту путешесвенников, на которых подписан текущий пользователь, в обратном хронологическом порядке + summary: Получить медиафайлы поста + description: Возвращает медиафайлы для поста tags: - - Feed + - Media parameters: - - name: limit - in: query - description: Количество записей на странице (макс. 30) - schema: - type : integer - default: 10 - minimum: 1 - maximum: 30 - - name: offset - in: query - description: Смещение для пагинации + - name: postId + in: path + required: true schema: - type : integer - default: 0 - minimum: 0 + type: string + description: Идентификатор поста responses: 200: - description: Список постов - 401: - description: Пользователь не авторизован + description: Список медиафайлов + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/Media' + 404: + description: Пост не найден или у поста нет медиа + 500: + description: Внутренняя ошибка сервера components: schemas: @@ -367,41 +559,6 @@ components: - content - createdAt - postId - - Destination: - type: object - properties: - id: - type: string - example: "123" - name: - type: string - example: "Наименование постов" - country: - type: string - example: "Италия" - latitude: - type: number - format: float - example: 44.4444 - longitude: - type: number - format: float - example: 33.3333 - postCount: - type: integer - example: 1200 - previewPhotoUrl: - type: string - format: uri - example: "https://cdn.travelapp.com.italy-review.jpg" - required: - - id - - name - - country - - latitude - - longitude - - postCount Post: type: object @@ -423,7 +580,8 @@ components: items: type: string format: uri - example: ["https://cdn.example.com/photo1.jpg"] + example: + - "https://cdn.example.com/photo1.jpg" location: type: object properties: @@ -453,3 +611,111 @@ components: - photoUrls - location - publishedAt + + Comment: + type: object + properties: + id: + type: string + author: + $ref: '#/components/schemas/User' + content: + type: string + createdAt: + type: string + format: date-time + required: + - id + - author + - content + - createdAt + + Reaction: + type: object + properties: + userId: + type: string + type: + type: string + example: "like" + createdAt: + type: string + format: date-time + required: + - userId + - type + + Media: + type: object + properties: + id: + type: string + url: + type: string + format: uri + type: + type: string + enum: + - image + - video + width: + type: integer + height: + type: integer + User: + type: object + description: Информация о пользователе (путешественнике) + properties: + id: + type: string + format: uuid + example: "usr_5f8e3a1b2c9d" + description: Уникальный идентификатор пользователя + username: + type: string + example: "alex_traveler" + description: Уникальное имя пользователя + displayName: + type: string + example: "Алексей Петров" + description: Отображаемое имя + avatarUrl: + type: string + format: uri + nullable: true + example: "https://example.com/avatars/alex.jpg" + description: Ссылка на аватар + isVerified: + type: boolean + example: true + description: Подтверждён ли аккаунт (галочка верификации) + bio: + type: string + nullable: true + example: "Люблю горы, море и старые города" + description: Краткая биография + followersCount: + type: integer + minimum: 0 + example: 142 + description: Количество подписчиков + followingCount: + type: integer + minimum: 0 + example: 87 + description: Количество подписок + postsCount: + type: integer + minimum: 0 + example: 23 + description: Количество опубликованных постов + createdAt: + type: string + format: date-time + example: "2023-05-12T10:30:00Z" + description: Дата регистрации + required: + - id + - username + - displayName + From a4fcbbdcf32fb5a20ef5cda10c49e11cc17e2317 Mon Sep 17 00:00:00 2001 From: gas-coder Date: Tue, 4 Nov 2025 23:02:55 +0500 Subject: [PATCH 3/3] =?UTF-8?q?=D0=9C=D0=BE=D0=B4=D0=B5=D0=BB=D1=8C=20?= =?UTF-8?q?=D1=85=D1=80=D0=B0=D0=BD=D0=B5=D0=BD=D0=B8=D1=8F=20=D0=B4=D0=B0?= =?UTF-8?q?=D0=BD=D0=BD=D1=8B=D1=85=20=D0=B8=20=D0=BE=D1=86=D0=B5=D0=BD?= =?UTF-8?q?=D0=BA=D0=B0=20=D0=BA=D0=BE=D0=BB=D0=B8=D1=87=D0=B5=D1=81=D1=82?= =?UTF-8?q?=D0=B2=D0=B0=20=D0=B4=D0=B8=D1=81=D0=BA=D0=BE=D0=B2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 42 +++++++++++++++++++++++++ database/database.io_Content_Service | 29 +++++++++++++++++ database/database.io_Discovery_Service | 8 +++++ database/database.io_Engagement_Service | 24 ++++++++++++++ database/database.io_User_Service | 22 +++++++++++++ database/redis_Feed_Service | 10 ++++++ 6 files changed, 135 insertions(+) create mode 100644 database/database.io_Content_Service create mode 100644 database/database.io_Discovery_Service create mode 100644 database/database.io_Engagement_Service create mode 100644 database/database.io_User_Service create mode 100644 database/redis_Feed_Service diff --git a/README.md b/README.md index 6215350..21ad0e0 100644 --- a/README.md +++ b/README.md @@ -111,3 +111,45 @@ RPS = 10 000 000 * 0.4 / 86 400 = ~47 Расчет одновременных соединений Connections = 10 000 000 * 0.1 = 1 000 000 + +Посты. + +Трафик. Публикация постов (мета) - 0,14 МБ/с +Трафик. Публикация постов (медиа) - 470 МБ/с +Трафик. Просмотр ленты (мета) - 18 МБ/с +Трафик. Просмотр ленты (медиа) - 2 222 МБ/с +Трафик. Поиск и просмотр постов/мест (мета) - 9 МБ/с +Трафик. Поиск и просмотр постов/мест (медиа) - 3 819 МБ/с +Трафик. Подписки - 0,05 МБ/с + +Capacity = 470,14 МБ/с * 86 400 * 365 = 15 000 ТБ +SSD: +Disk_for_capacity = 15 000 ТБ/ 90 ТБ = 167 +Disks_for_throughput = 6 540 / 500 МБ/с = 13 +Disks_for_iops = 3 172 / 1 000 = 3 +Disks max (167, 13, 3) = 167 + +Реакции. + +Трафик. Создание комментария - 0,04 МБ/с +Трафик. Чтение комментария - 0,36 МБ/с + +Capacity = 0,04 МБ/с * 86 400 * 365 = 1,3 ТБ +SSD: +Disk_for_capacity = 1,3 ТБ/ 1 ТБ = 1,3 +Disks_for_throughput = 0,4 / 500 МБ/с = 0,0008 +Disks_for_iops = 556 / 1 000 = 0,556 +Disks max (1,3, 0,0008, 0,556) = 1 + +Комментарии. + +Трафик. Создание лайка - 0,16 МБ/с +Трафик. Чтение лайка - 1,44 МБ/с + +Capacity = 0,16 МБ/с * 86 400 * 365 = 5 ТБ +SSD: +Disk_for_capacity = 5 ТБ/ 2 ТБ = 2,5 +Disks_for_throughput = 1,6 / 500 МБ/с = 0,0032 +Disks_for_iops = 139 / 1 000 = 0,139 +Disks max (2,5, 0,0032, 0,136) = 3 + diff --git a/database/database.io_Content_Service b/database/database.io_Content_Service new file mode 100644 index 0000000..5f5cadb --- /dev/null +++ b/database/database.io_Content_Service @@ -0,0 +1,29 @@ +// Content Service - посты, медиа, места посещения + +Table destinations { + id uuid [primary key] + name varchar [not null] + country varchar [not null] + city varchar + lat double precision + lng double precision + popularity_score integer [default: 0] + created_at timestamp [default: `now()`] +} + +Table posts { + id uuid [primary key] + user_id uuid [not null] // ID из User Service + destination_id uuid [not null, ref: > destinations.id] + content text + created_at timestamp [default: `now()`] +} + +Table media { + id uuid [primary key] + post_id uuid [not null, ref: > posts.id] + url varchar [not null] // URL в S3 + media_type varchar [note: "'image'"] + order_index integer [default: 0] + created_at timestamp [default: `now()`] +} \ No newline at end of file diff --git a/database/database.io_Discovery_Service b/database/database.io_Discovery_Service new file mode 100644 index 0000000..3533cf1 --- /dev/null +++ b/database/database.io_Discovery_Service @@ -0,0 +1,8 @@ +// Discovery Service - популярные места + +Table popular_destinations { + destination_id uuid [primary key] // ID из Content Service + post_count integer [default: 0] + reaction_count integer [default: 0] + last_updated timestamp [default: `now()`] +} \ No newline at end of file diff --git a/database/database.io_Engagement_Service b/database/database.io_Engagement_Service new file mode 100644 index 0000000..0d4c3bb --- /dev/null +++ b/database/database.io_Engagement_Service @@ -0,0 +1,24 @@ +// Engagement Service - лайки и комментарии + +Table reactions { + user_id uuid [not null] // ID из User Service + post_id uuid [not null] // ID из Content Service + created_at timestamp [default: `now()`] + + indexes { + (user_id, post_id) [unique] + (post_id) + } +} + +Table comments { + id uuid [primary key] + post_id uuid [not null] // ID из Content Service + user_id uuid [not null] // ID из User Service + content text [not null] + created_at timestamp [default: `now()`] + + indexes { + (post_id, created_at) + } +} \ No newline at end of file diff --git a/database/database.io_User_Service b/database/database.io_User_Service new file mode 100644 index 0000000..f02bb07 --- /dev/null +++ b/database/database.io_User_Service @@ -0,0 +1,22 @@ +// User Service - управление пользователями и подписками + +Table users { + id uuid [primary key] + username varchar [unique, not null] + display_name varchar [not null] + avatar_url varchar + bio text + created_at timestamp [default: `now()`] +} + +Table subscriptions { + follower_id uuid [not null] + followee_id uuid [not null] + created_at timestamp [default: `now()`] + + indexes { + (follower_id, followee_id) [unique] + (follower_id) + (followee_id) + } +} \ No newline at end of file diff --git a/database/redis_Feed_Service b/database/redis_Feed_Service new file mode 100644 index 0000000..b09f6ac --- /dev/null +++ b/database/redis_Feed_Service @@ -0,0 +1,10 @@ +// Feed Service (Redis) - лента +// Описание ключей + +Table feed_structure { + key_pattern varchar [note: "'user_feed:{user_id}'"] + data_type varchar [note: "Sorted Set"] + score double [note: "timestamp (в миллисекундах)"] + value varchar [note: "post_id (UUID из Content Service)"] + ttl varchar [note: "Бессрочно или по политике"] +} \ No newline at end of file