New task checking if remote instance is reachable to avoid playback latence

This commit is contained in:
Petitminion 2022-06-30 18:04:04 +02:00 committed by Georg Krause
commit 0cb3457378
8 changed files with 92 additions and 1 deletions

View file

@ -70,6 +70,8 @@ class DomainFactory(NoUpdateOnCreate, factory.django.DjangoModelFactory):
name = factory.Faker("domain_name")
nodeinfo_fetch_date = factory.LazyFunction(lambda: timezone.now())
allowed = None
reachable = True
last_successful_contact = None
class Meta:
model = "federation.Domain"

View file

@ -0,0 +1,23 @@
# Generated by Django 3.2.16 on 2022-10-27 11:41
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('federation', '0027_auto_20220627_1915'),
]
operations = [
migrations.AddField(
model_name='domain',
name='last_successful_contact',
field=models.DateTimeField(default=None, null=True),
),
migrations.AddField(
model_name='domain',
name='reachable',
field=models.BooleanField(default=True),
),
]

View file

@ -123,7 +123,8 @@ class Domain(models.Model):
)
# are interactions with this domain allowed (only applies when allow-listing is on)
allowed = models.BooleanField(default=None, null=True)
reachable = models.BooleanField(default=True)
last_successful_contact = models.DateTimeField(default=None, null=True)
objects = DomainQuerySet.as_manager()
def __str__(self):

View file

@ -625,3 +625,35 @@ def fetch_collection(url, max_pages, channel, is_page=False):
results["errored"],
)
return results
@celery.app.task(name="federation.check_all_remote_instance_availability")
def check_all_remote_instance_availability():
domains = models.Domain.objects.all().prefetch_related()
for domain in domains:
check_single_remote_instance_availability(domain)
@celery.app.task(name="federation.check_single_remote_instance_availability")
def check_single_remote_instance_availability(domain):
try:
response = requests.get(f"https://{domain.name}/api/v1/instance/nodeinfo/2.0/")
nodeinfo = response.json()
except Exception as e:
logger.info(
f"Domain {domain.name} could not be reached because of the following error : {e}. \
Setting domain as unreacheable."
)
domain.reachable = False
domain.save()
if "version" in nodeinfo.keys():
domain.reachable = True
domain.last_successful_contact = datetime.datetime.now()
domain.save()
else:
logger.info(
f"Domain {domain.name} is not reacheable at the moment. Setting domain as unreacheable."
)
domain.reachable = False
domain.save()

View file

@ -1184,12 +1184,15 @@ class LibraryQuerySet(models.QuerySet):
)
.values_list("target__channel__library", flat=True)
)
domains_reachable = federation_models.Domain.objects.filter(reachable=True)
return self.filter(
me_query
| instance_query
| models.Q(privacy_level="everyone")
| models.Q(pk__in=followed_libraries)
| models.Q(pk__in=followed_channels_libraries)
& models.Q(actor__domain__in=domains_reachable)
)