Commit 9f0646cb authored by petitminion's avatar petitminion
Browse files

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

parent 3505ff6e
Pipeline #21301 passed with stage
in 17 seconds
......@@ -846,6 +846,11 @@ CELERY_BEAT_SCHEDULE = {
"schedule": crontab(minute="0", hour="*/5"),
"options": {"expires": 60 * 60},
},
"federation.check_remote_instance_availability": {
"task": "federation.check_remote_instance_availability",
"schedule": crontab(minute="0", hour="*"),
"options": {"expires": 60 * 2},
},
}
if env.bool("ADD_ALBUM_TAGS_FROM_TRACKS", default=True):
......
# Generated by Django 3.2.13 on 2022-06-22 12:02
import django.core.serializers.json
from django.db import migrations, models
import funkwhale_api.audio.models
class Migration(migrations.Migration):
dependencies = [
('audio', '0003_channel_rss_url'),
]
operations = [
migrations.AlterField(
model_name='channel',
name='metadata',
field=models.JSONField(blank=True, default=funkwhale_api.audio.models.empty_dict, encoder=django.core.serializers.json.DjangoJSONEncoder, max_length=50000),
),
]
# Generated by Django 3.2.13 on 2022-06-22 12:02
import django.core.serializers.json
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('common', '0008_auto_20200701_1317'),
]
operations = [
migrations.AlterField(
model_name='mutation',
name='is_applied',
field=models.BooleanField(default=None, null=True),
),
migrations.AlterField(
model_name='mutation',
name='is_approved',
field=models.BooleanField(default=None, null=True),
),
migrations.AlterField(
model_name='mutation',
name='payload',
field=models.JSONField(encoder=django.core.serializers.json.DjangoJSONEncoder),
),
migrations.AlterField(
model_name='mutation',
name='previous_state',
field=models.JSONField(default=None, encoder=django.core.serializers.json.DjangoJSONEncoder, null=True),
),
migrations.AlterField(
model_name='pluginconfiguration',
name='conf',
field=models.JSONField(blank=True, null=True),
),
]
......@@ -70,6 +70,7 @@ class DomainFactory(NoUpdateOnCreate, factory.django.DjangoModelFactory):
name = factory.Faker("domain_name")
nodeinfo_fetch_date = factory.LazyFunction(lambda: timezone.now())
allowed = None
reachable = True
class Meta:
model = "federation.Domain"
......
# Generated by Django 3.2.13 on 2022-06-22 12:02
import django.core.serializers.json
from django.db import migrations, models
import funkwhale_api.federation.models
class Migration(migrations.Migration):
dependencies = [
('federation', '0026_public_key_format'),
]
operations = [
migrations.AddField(
model_name='domain',
name='reachable',
field=models.BooleanField(default=True),
),
migrations.AlterField(
model_name='activity',
name='payload',
field=models.JSONField(blank=True, default=funkwhale_api.federation.models.empty_dict, encoder=django.core.serializers.json.DjangoJSONEncoder, max_length=50000),
),
migrations.AlterField(
model_name='actor',
name='manually_approves_followers',
field=models.BooleanField(default=None, null=True),
),
migrations.AlterField(
model_name='domain',
name='nodeinfo',
field=models.JSONField(blank=True, default=funkwhale_api.federation.models.empty_dict, max_length=50000),
),
migrations.AlterField(
model_name='fetch',
name='detail',
field=models.JSONField(blank=True, default=funkwhale_api.federation.models.empty_dict, encoder=django.core.serializers.json.DjangoJSONEncoder, max_length=50000),
),
migrations.AlterField(
model_name='follow',
name='approved',
field=models.BooleanField(default=None, null=True),
),
migrations.AlterField(
model_name='libraryfollow',
name='approved',
field=models.BooleanField(default=None, null=True),
),
migrations.AlterField(
model_name='librarytrack',
name='metadata',
field=models.JSONField(blank=True, default=funkwhale_api.federation.models.empty_dict, encoder=django.core.serializers.json.DjangoJSONEncoder, max_length=10000),
),
]
......@@ -123,6 +123,7 @@ 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)
objects = DomainQuerySet.as_manager()
......
......@@ -4,6 +4,7 @@ import logging
import os
import requests
from requests import HTTPError
import urllib
from django.conf import settings
from django.db import transaction
......@@ -653,3 +654,25 @@ def refresh_actor_data():
serializer.is_valid(raise_exception=True)
serializer.save(last_fetch_date=timezone.now())
return
@celery.app.task(name="federation.check_remote_instance_availability")
def check_remote_instance_availability():
domains = models.Domain.objects.all().prefetch_related()
for domain in domains:
try:
status = urllib.request.urlopen(f"https://{domain.name}").getcode()
except Exception as e:
logger.info(
f"Domain {domain.name} could not be reached because of the following error : {e}. Setting domain as unreacheable."
)
models.Domain.objects.filter(name=domain.name).update(reachable=False)
status = 400
if status == 200:
models.Domain.objects.filter(name=domain.name).update(reachable=True)
else:
logger.info(
f"Domain {domain.name} is not reacheable at the moment. Setting domain as unreacheable."
)
models.Domain.objects.filter(name=domain.name).update(reachable=False)
# Generated by Django 3.2.13 on 2022-06-22 12:02
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('moderation', '0006_auto_20200803_1222'),
]
operations = [
migrations.AlterField(
model_name='report',
name='target_state',
field=models.JSONField(null=True),
),
migrations.AlterField(
model_name='userrequest',
name='metadata',
field=models.JSONField(null=True),
),
]
# Generated by Django 3.2.13 on 2022-06-22 12:02
import django.core.serializers.json
from django.db import migrations, models
import funkwhale_api.music.models
class Migration(migrations.Migration):
dependencies = [
('music', '0054_alter_uploadversion_mimetype'),
]
operations = [
migrations.AlterField(
model_name='upload',
name='import_details',
field=models.JSONField(blank=True, default=funkwhale_api.music.models.empty_dict, encoder=django.core.serializers.json.DjangoJSONEncoder, max_length=50000),
),
migrations.AlterField(
model_name='upload',
name='import_metadata',
field=models.JSONField(blank=True, default=funkwhale_api.music.models.empty_dict, encoder=django.core.serializers.json.DjangoJSONEncoder, max_length=50000),
),
migrations.AlterField(
model_name='upload',
name='metadata',
field=models.JSONField(blank=True, default=funkwhale_api.music.models.empty_dict, encoder=django.core.serializers.json.DjangoJSONEncoder, max_length=50000),
),
]
......@@ -1184,13 +1184,15 @@ class LibraryQuerySet(models.QuerySet):
)
.values_list("target__channel__library", flat=True)
)
domains_unreachable = federation_models.Domain.objects.filter(reachable=False)
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)
)
).exclude(actor__domain__name__in=domains_unreachable)
class Library(federation_models.FederationMixin):
......
# Generated by Django 3.2.13 on 2022-06-22 12:02
import django.core.serializers.json
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('radios', '0005_auto_20200803_1222'),
]
operations = [
migrations.AlterField(
model_name='radio',
name='config',
field=models.JSONField(encoder=django.core.serializers.json.DjangoJSONEncoder),
),
]
# Generated by Django 3.2.13 on 2022-06-22 12:02
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('users', '0021_auto_20210703_1810'),
]
operations = [
migrations.AlterField(
model_name='user',
name='settings',
field=models.JSONField(blank=True, default=None, max_length=50000, null=True),
),
]
import datetime
import http
import os
import pathlib
import pytest
......@@ -670,3 +671,17 @@ def test_fetch_collection(mocker, r_mock):
assert result["seen"] == 7
assert result["total"] == 27094
assert result["next_page"] == payloads["page2"]["next"]
def test_check_remote_instance_availability(factories, mocker):
domain = factories["federation.Domain"]()
mocker.patch.object(http.client.HTTPResponse, "getcode", return_value=200)
tasks.check_remote_instance_availability()
domain = models.Domain.objects.get(name=domain.name)
assert domain.reachable == True
mocker.patch.object(http.client.HTTPResponse, "getcode", return_value=300)
tasks.check_remote_instance_availability()
domain = models.Domain.objects.get(name=domain.name)
assert domain.reachable == False
New task checking if remote instance is reachable to avoid playback latence (#1711)
\ No newline at end of file
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment