notifications+topics-resolvers-fix
Some checks failed
Deploy on push / deploy (push) Failing after 2m35s
Some checks failed
Deploy on push / deploy (push) Failing after 2m35s
This commit is contained in:
@@ -16,6 +16,9 @@
|
||||
- **Передача сессий в тесты**: `assign_role_to_user`, `get_user_roles_in_community` теперь принимают `session` параметр
|
||||
- **Исправлена логика RBAC**: `if ca.role_list:` → `if not ca.role_list:` в удалении записей
|
||||
- **Устойчивость моков**: Тесты `test_drafts.py` и `test_update_security.py` теперь устойчивы к различиям CI/локальной среды
|
||||
- Исправления интерфейса уведомлений
|
||||
- Исправление выдачи всех авторов
|
||||
- Исправление резолверов для тем
|
||||
|
||||
## [0.9.7] - 2025-08-18
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import time
|
||||
from datetime import datetime
|
||||
from datetime import UTC, datetime
|
||||
from typing import Any
|
||||
|
||||
import orjson
|
||||
@@ -34,36 +34,21 @@ def query_notifications(author_id: int, after: int = 0) -> tuple[int, int, list[
|
||||
)
|
||||
if after:
|
||||
# Convert Unix timestamp to datetime for PostgreSQL compatibility
|
||||
after_datetime = datetime.fromtimestamp(after)
|
||||
after_datetime = datetime.fromtimestamp(after, tz=UTC)
|
||||
q = q.where(Notification.created_at > after_datetime)
|
||||
q = q.group_by(NotificationSeen.notification, Notification.created_at)
|
||||
|
||||
with local_session() as session:
|
||||
# Convert Unix timestamp to datetime for PostgreSQL compatibility
|
||||
after_datetime = datetime.fromtimestamp(after) if after else None
|
||||
|
||||
total = (
|
||||
session.query(Notification)
|
||||
.where(
|
||||
and_(
|
||||
Notification.action == NotificationAction.CREATE.value,
|
||||
Notification.created_at > after_datetime,
|
||||
)
|
||||
)
|
||||
.count()
|
||||
)
|
||||
# Build query conditions
|
||||
conditions = [Notification.action == NotificationAction.CREATE.value]
|
||||
if after:
|
||||
after_datetime = datetime.fromtimestamp(after, tz=UTC)
|
||||
conditions.append(Notification.created_at > after_datetime)
|
||||
|
||||
unread = (
|
||||
session.query(Notification)
|
||||
.where(
|
||||
and_(
|
||||
Notification.action == NotificationAction.CREATE.value,
|
||||
Notification.created_at > after_datetime,
|
||||
not_(Notification.seen),
|
||||
)
|
||||
)
|
||||
.count()
|
||||
)
|
||||
total = session.query(Notification).where(and_(*conditions)).count()
|
||||
|
||||
unread_conditions = [*conditions, not_(Notification.seen)]
|
||||
unread = session.query(Notification).where(and_(*unread_conditions)).count()
|
||||
|
||||
notifications_result = session.execute(q)
|
||||
notifications = []
|
||||
@@ -267,8 +252,11 @@ async def notifications_seen_after(_: None, info: GraphQLResolveInfo, after: int
|
||||
if author_id:
|
||||
with local_session() as session:
|
||||
# Convert Unix timestamp to datetime for PostgreSQL compatibility
|
||||
after_datetime = datetime.fromtimestamp(after) if after else None
|
||||
nnn = session.query(Notification).where(and_(Notification.created_at > after_datetime)).all()
|
||||
after_datetime = datetime.fromtimestamp(after, tz=UTC) if after else None
|
||||
if after_datetime:
|
||||
nnn = session.query(Notification).where(and_(Notification.created_at > after_datetime)).all()
|
||||
else:
|
||||
nnn = session.query(Notification).all()
|
||||
for notification in nnn:
|
||||
ns = NotificationSeen(notification=notification.id, author=author_id)
|
||||
session.add(ns)
|
||||
@@ -288,27 +276,45 @@ async def notifications_seen_thread(_: None, info: GraphQLResolveInfo, thread: s
|
||||
[shout_id, reply_to_id] = thread.split(":")
|
||||
with local_session() as session:
|
||||
# Convert Unix timestamp to datetime for PostgreSQL compatibility
|
||||
after_datetime = datetime.fromtimestamp(after) if after else None
|
||||
|
||||
after_datetime = datetime.fromtimestamp(after, tz=UTC) if after else None
|
||||
|
||||
# TODO: handle new follower and new shout notifications
|
||||
new_reaction_notifications = (
|
||||
session.query(Notification)
|
||||
.where(
|
||||
Notification.action == "create",
|
||||
Notification.entity == "reaction",
|
||||
Notification.created_at > after_datetime,
|
||||
if after_datetime:
|
||||
new_reaction_notifications = (
|
||||
session.query(Notification)
|
||||
.where(
|
||||
Notification.action == "create",
|
||||
Notification.entity == "reaction",
|
||||
Notification.created_at > after_datetime,
|
||||
)
|
||||
.all()
|
||||
)
|
||||
.all()
|
||||
)
|
||||
removed_reaction_notifications = (
|
||||
session.query(Notification)
|
||||
.where(
|
||||
Notification.action == "delete",
|
||||
Notification.entity == "reaction",
|
||||
Notification.created_at > after_datetime,
|
||||
removed_reaction_notifications = (
|
||||
session.query(Notification)
|
||||
.where(
|
||||
Notification.action == "delete",
|
||||
Notification.entity == "reaction",
|
||||
Notification.created_at > after_datetime,
|
||||
)
|
||||
.all()
|
||||
)
|
||||
else:
|
||||
new_reaction_notifications = (
|
||||
session.query(Notification)
|
||||
.where(
|
||||
Notification.action == "create",
|
||||
Notification.entity == "reaction",
|
||||
)
|
||||
.all()
|
||||
)
|
||||
removed_reaction_notifications = (
|
||||
session.query(Notification)
|
||||
.where(
|
||||
Notification.action == "delete",
|
||||
Notification.entity == "reaction",
|
||||
)
|
||||
.all()
|
||||
)
|
||||
.all()
|
||||
)
|
||||
exclude = set()
|
||||
for nr in removed_reaction_notifications:
|
||||
reaction = orjson.loads(str(nr.payload))
|
||||
|
||||
@@ -228,7 +228,7 @@ async def get_topics_with_stats(
|
||||
WHERE st.topic IN ({placeholders})
|
||||
GROUP BY st.topic
|
||||
"""
|
||||
params = {f"id{i}": topic_id for i, topic_id in enumerate(topic_ids)}
|
||||
params: dict[str, int | str] = {f"id{i}": topic_id for i, topic_id in enumerate(topic_ids)}
|
||||
shouts_stats = {row[0]: row[1] for row in session.execute(text(shouts_stats_query), params)}
|
||||
|
||||
# Запрос на получение статистики по подписчикам для выбранных тем
|
||||
|
||||
@@ -11,7 +11,7 @@ from ariadne import (
|
||||
|
||||
from orm import collection, community, draft, invite, notification, reaction, shout, topic
|
||||
from orm.author import Author, AuthorBookmark, AuthorFollower, AuthorRating
|
||||
from storage.db import create_table_if_not_exists, local_session
|
||||
from storage.db import create_table_if_not_exists
|
||||
|
||||
# Создаем основные типы
|
||||
query = QueryType()
|
||||
@@ -69,7 +69,7 @@ def create_all_tables() -> None:
|
||||
]
|
||||
|
||||
from storage.db import engine
|
||||
|
||||
|
||||
# Используем одно соединение для всех таблиц, чтобы избежать проблем с транзакциями
|
||||
with engine.connect() as connection:
|
||||
for model in models_in_order:
|
||||
|
||||
Reference in New Issue
Block a user