Схема находится в graph/schema.graphqls. Ниже — примеры типичных запросов, мутаций и подписок.
query {
posts {
id
title
content
allowComments
}
}query {
post(id: "1") {
id
title
content
comments(limit: 10, offset: 0) {
id
content
parentId
replies(limit: 5, offset: 0) {
id
content
parentId
}
}
}
}Описание: Возвращает пост по его id, включая комментарии и вложенные ответы. Уровень вложенности контролирует клиент, добавляя replies в запрос. Для решения проблемы n + 1 есть механизм dataloader.
Параметры пагинации для комментариев:
limit— количество элементов на запрос,offset— смещение.
Все мутации защищены директивой @auth. Для их выполнения пользователь должен быть аутентифицирован (например, через токен, cookie или header).
Запрос:
mutation {
createPost(title: "Новый пост", content: "Текст поста") {
id
title
content
allowComments
}
}Запрос:
mutation {
addComment(postId: "1", content: "Отличная статья!") {
id
postId
parentId
content
}
}Описание:
Добавляет комментарий к посту. Параметр parentId можно указать, чтобы оставить ответ на другой комментарий.
mutation {
disallowComments(postId: "1")
}subscription {
commentAdded(postId: "1") {
id
postId
parentId
content
}
}Сервис поддерживает два типа хранилища:
in-memory (память) — используется по умолчанию, все данные хранятся в оперативной памяти и теряются после перезапуска приложения;
PostgreSQL — используется при запуске с переменной окружения STORAGE=postgres, данные сохраняются на диск и доступны после перезапуска.
При запуске приложения можно указать тип хранилища через параметр --storage:
In-memory (по умолчанию) go run ./cmd/server --storage=in-memory
PostgreSQL go run ./cmd/server --storage=postgres
MemoryStorage хранит данные в нескольких структурах:
comments — линейный список всех комментариев в системе
commentByID — быстрый поиск комментария по ID (map[int]*models.Comment)
commentsByPostID — группировка комментариев по постам (map[int][]*models.Comment)
repliesByParentID — иерархия ответов на комментарии (map[int][]*models.Comment)
posts — список всех постов
users — список всех пользователей
postsByID — индекс постов по ID
userBylogin — индекс пользователей по логину
nextCommentID — счетчик для генерации уникальных ID комментариев
Для обеспечения потокобезопасности используется sync.RWMutex.
Все объекты (Post, Comment, User) хранятся в оперативной памяти внутри срезов (posts, comments, users).
Для ускорения поиска используются индексы (map), которые позволяют получать данные за O(1).
При создании нового поста или комментария:
-
генерируется новый ID через счётчики nextPostID или nextCommentID;
-
объект добавляется в соответствующие коллекции и индексы.
Чтение и запись защищены с помощью sync.RWMutex, что обеспечивает потокобезопасность.
Реализация PostgresStorage обеспечивает сохранение и выборку данных из реляционной базы данных PostgreSQL.
В отличие от MemoryStorage, данные сохраняются на диск и сохраняются между перезапусками приложения.
Для работы используется библиотека sqlx
- Методы принимают
context.Context, что позволяет отменять операции по тайм-ауту или при завершении запроса. - Для вставки данных используется конструкция
INSERT ... RETURNING id, чтобы сразу получить ID новой записи. - Для выборки комментариев реализованы методы с фильтрацией (
WHERE) и пагинацией (LIMIT,OFFSET). - Для получения комментариев и избежания есть метод ListRepliesBatch чтобы получить комментарии по группе parent id
- Добавлены индексы для таблицы comments по post_id и parent_id, и users по полю login для ускорения выборки.