Force refresh actor once in a while

main
Thomas Sileo 2022-10-07 08:55:05 +02:00
parent c8a9793638
commit f6cfe06f66
2 changed files with 41 additions and 18 deletions

View File

@ -1,6 +1,7 @@
import hashlib import hashlib
import typing import typing
from dataclasses import dataclass from dataclasses import dataclass
from datetime import timedelta
from functools import cached_property from functools import cached_property
from typing import Union from typing import Union
from urllib.parse import urlparse from urllib.parse import urlparse
@ -12,6 +13,8 @@ from sqlalchemy.orm import joinedload
from app import activitypub as ap from app import activitypub as ap
from app import media from app import media
from app.database import AsyncSession from app.database import AsyncSession
from app.utils.datetime import as_utc
from app.utils.datetime import now
if typing.TYPE_CHECKING: if typing.TYPE_CHECKING:
from app.models import Actor as ActorModel from app.models import Actor as ActorModel
@ -189,8 +192,23 @@ async def fetch_actor(
if existing_actor: if existing_actor:
if existing_actor.is_deleted: if existing_actor.is_deleted:
raise ap.ObjectNotFoundError(f"{actor_id} was deleted") raise ap.ObjectNotFoundError(f"{actor_id} was deleted")
if now() - as_utc(existing_actor.updated_at) > timedelta(hours=24):
logger.info(
f"Refreshing {actor_id=} last updated {existing_actor.updated_at}"
)
try:
ap_actor = await ap.fetch(actor_id)
existing_actor.ap_actor = ap_actor
existing_actor.updated_at = now()
return existing_actor
except Exception:
logger.exception(f"Failed to refresh {actor_id}")
# If we fail to refresh the actor, return the cached one
return existing_actor return existing_actor
else: else:
return existing_actor
if save_if_not_found: if save_if_not_found:
ap_actor = await ap.fetch(actor_id) ap_actor = await ap.fetch(actor_id)
# Some softwares uses URL when we expect ID # Some softwares uses URL when we expect ID
@ -204,6 +222,9 @@ async def fetch_actor(
) )
).one_or_none() ).one_or_none()
if existing_actor_by_url: if existing_actor_by_url:
# Update the actor as we had to fetch it anyway
existing_actor_by_url.ap_actor = ap_actor
existing_actor_by_url.updated_at = now()
return existing_actor_by_url return existing_actor_by_url
return await save_actor(db_session, ap_actor) return await save_actor(db_session, ap_actor)

View File

@ -1492,6 +1492,7 @@ async def _handle_update_activity(
# Update the actor # Update the actor
from_actor.ap_actor = updated_actor.ap_actor from_actor.ap_actor = updated_actor.ap_actor
from_actor.updated_at = now()
elif (ap_type := wrapped_object["type"]) in [ elif (ap_type := wrapped_object["type"]) in [
"Question", "Question",
"Note", "Note",
@ -1514,6 +1515,7 @@ async def _handle_update_activity(
# Everything looks correct, update the object in the inbox # Everything looks correct, update the object in the inbox
logger.info(f"Updating {existing_object.ap_id}") logger.info(f"Updating {existing_object.ap_id}")
existing_object.ap_object = wrapped_object existing_object.ap_object = wrapped_object
existing_object.updated_at = now()
else: else:
# TODO(ts): support updating objects # TODO(ts): support updating objects
logger.info(f'Cannot update {wrapped_object["type"]}') logger.info(f'Cannot update {wrapped_object["type"]}')