Index authorized mailbox cache changes in Search
This commit is contained in:
@@ -7,11 +7,17 @@ from threading import Lock
|
||||
from sqlalchemy import func
|
||||
from sqlalchemy.orm import Session
|
||||
|
||||
from govoplan_core.core.change_sequence import record_change
|
||||
from govoplan_core.security.time import ensure_aware_utc, utc_now
|
||||
from govoplan_mail.backend.db.models import MailMailboxFolderIndex, MailMailboxMessageIndex
|
||||
from govoplan_mail.backend.db.models import (
|
||||
MailMailboxFolderIndex,
|
||||
MailMailboxMessageIndex,
|
||||
new_uuid,
|
||||
)
|
||||
from govoplan_mail.backend.sending.imap import ImapFolderListResult, ImapMailboxInfo, ImapMailboxMessageListResult, ImapMailboxMessageSummary
|
||||
|
||||
MAILBOX_INDEX_TTL_SECONDS = 30
|
||||
MAILBOX_MESSAGES_COLLECTION = "mail.mailbox_messages"
|
||||
|
||||
_refresh_lock = Lock()
|
||||
_refreshing_keys: set[tuple[str, str, str]] = set()
|
||||
@@ -44,6 +50,13 @@ def clear_mailbox_index(session: Session, *, profile_id: str) -> tuple[int, int]
|
||||
transport change. Message rows are removed before their folder metadata.
|
||||
"""
|
||||
|
||||
messages = (
|
||||
session.query(MailMailboxMessageIndex)
|
||||
.filter(MailMailboxMessageIndex.profile_id == profile_id)
|
||||
.all()
|
||||
)
|
||||
for message in messages:
|
||||
_record_message_change(session, message, operation="deleted")
|
||||
deleted_messages = (
|
||||
session.query(MailMailboxMessageIndex)
|
||||
.filter(MailMailboxMessageIndex.profile_id == profile_id)
|
||||
@@ -89,6 +102,17 @@ def cache_mailbox_folders(
|
||||
expected_names = {folder.name for folder in result.folders}
|
||||
removed_names = set(existing) - expected_names
|
||||
if removed_names:
|
||||
removed_messages = (
|
||||
session.query(MailMailboxMessageIndex)
|
||||
.filter(
|
||||
MailMailboxMessageIndex.tenant_id == tenant_id,
|
||||
MailMailboxMessageIndex.profile_id == profile_id,
|
||||
MailMailboxMessageIndex.folder.in_(removed_names),
|
||||
)
|
||||
.all()
|
||||
)
|
||||
for message in removed_messages:
|
||||
_record_message_change(session, message, operation="deleted")
|
||||
(
|
||||
session.query(MailMailboxMessageIndex)
|
||||
.filter(
|
||||
@@ -139,6 +163,17 @@ def cache_mailbox_messages(
|
||||
|
||||
uids = [message.uid for message in result.messages]
|
||||
if result.total_count <= 0:
|
||||
removed_messages = (
|
||||
session.query(MailMailboxMessageIndex)
|
||||
.filter(
|
||||
MailMailboxMessageIndex.tenant_id == tenant_id,
|
||||
MailMailboxMessageIndex.profile_id == profile_id,
|
||||
MailMailboxMessageIndex.folder == result.folder,
|
||||
)
|
||||
.all()
|
||||
)
|
||||
for message in removed_messages:
|
||||
_record_message_change(session, message, operation="deleted")
|
||||
(
|
||||
session.query(MailMailboxMessageIndex)
|
||||
.filter(
|
||||
@@ -161,6 +196,7 @@ def cache_mailbox_messages(
|
||||
if uids:
|
||||
stale_query = stale_query.filter(MailMailboxMessageIndex.uid.notin_(uids))
|
||||
for row in stale_query.all():
|
||||
_record_message_change(session, row, operation="deleted")
|
||||
session.delete(row)
|
||||
existing = {}
|
||||
if uids:
|
||||
@@ -177,13 +213,16 @@ def cache_mailbox_messages(
|
||||
}
|
||||
for index, message in enumerate(result.messages):
|
||||
row = existing.get(message.uid)
|
||||
created = row is None
|
||||
if row is None:
|
||||
row = MailMailboxMessageIndex(
|
||||
id=new_uuid(),
|
||||
tenant_id=tenant_id,
|
||||
profile_id=profile_id,
|
||||
folder=result.folder,
|
||||
uid=message.uid,
|
||||
)
|
||||
previous = None if created else _message_state(row)
|
||||
row.uid_int = _uid_int(message.uid)
|
||||
row.sort_position = result.offset + index
|
||||
row.subject = message.subject
|
||||
@@ -198,6 +237,12 @@ def cache_mailbox_messages(
|
||||
row.attachment_count = message.attachment_count
|
||||
row.indexed_at = indexed_at
|
||||
session.add(row)
|
||||
if created or previous != _message_state(row):
|
||||
_record_message_change(
|
||||
session,
|
||||
row,
|
||||
operation="created" if created else "updated",
|
||||
)
|
||||
|
||||
|
||||
def cached_mailbox_folders(
|
||||
@@ -308,6 +353,48 @@ def _message_from_index(row: MailMailboxMessageIndex) -> ImapMailboxMessageSumma
|
||||
)
|
||||
|
||||
|
||||
def _message_state(row: MailMailboxMessageIndex) -> tuple[object, ...]:
|
||||
return (
|
||||
row.folder,
|
||||
row.uid,
|
||||
row.sort_position,
|
||||
row.subject,
|
||||
row.from_header,
|
||||
row.to_header,
|
||||
row.cc_header,
|
||||
row.date,
|
||||
row.message_id,
|
||||
tuple(row.flags or ()),
|
||||
row.size_bytes,
|
||||
row.body_preview,
|
||||
row.attachment_count,
|
||||
)
|
||||
|
||||
|
||||
def _record_message_change(
|
||||
session: Session,
|
||||
row: MailMailboxMessageIndex,
|
||||
*,
|
||||
operation: str,
|
||||
) -> None:
|
||||
record_change(
|
||||
session,
|
||||
module_id="mail",
|
||||
collection=MAILBOX_MESSAGES_COLLECTION,
|
||||
resource_type="mailbox_message",
|
||||
resource_id=row.id,
|
||||
operation=operation,
|
||||
tenant_id=row.tenant_id,
|
||||
actor_type="system",
|
||||
payload={
|
||||
"profile_id": row.profile_id,
|
||||
"folder": row.folder,
|
||||
"uid": row.uid,
|
||||
"message_id": row.message_id,
|
||||
},
|
||||
)
|
||||
|
||||
|
||||
def _uid_int(uid: str) -> int:
|
||||
try:
|
||||
return int(str(uid))
|
||||
|
||||
Reference in New Issue
Block a user