Verified Commit 032197da authored by Eliot Berriot's avatar Eliot Berriot
Browse files

Added stats endpoint for domain

parent be388870
......@@ -88,7 +88,7 @@ class Domain(models.Model):
name = models.CharField(primary_key=True, max_length=255)
creation_date = models.DateTimeField(default=timezone.now)
nodeinfo_fetch_date = models.DateTimeField(default=None, null=True, blank=True)
nodeinfo = JSONField(default=empty_dict, max_length=50000)
nodeinfo = JSONField(default=empty_dict, max_length=50000, blank=True)
objects = DomainQuerySet.as_manager()
......@@ -104,6 +104,38 @@ class Domain(models.Model):
super().save(**kwargs)
def get_stats(self):
from funkwhale_api.music import models as music_models
data = Domain.objects.filter(pk=self.pk).aggregate(
actors=models.Count("actors", distinct=True),
outbox_activities=models.Count("actors__outbox_activities", distinct=True),
libraries=models.Count("actors__libraries", distinct=True),
uploads=models.Count("actors__libraries__uploads", distinct=True),
received_library_follows=models.Count(
"actors__libraries__received_follows", distinct=True
),
emitted_library_follows=models.Count(
"actors__library_follows", distinct=True
),
)
data["artists"] = music_models.Artist.objects.filter(
from_activity__actor__domain_id=self.pk
).count()
data["albums"] = music_models.Album.objects.filter(
from_activity__actor__domain_id=self.pk
).count()
data["tracks"] = music_models.Track.objects.filter(
from_activity__actor__domain_id=self.pk
).count()
uploads = music_models.Upload.objects.filter(library__actor__domain_id=self.pk)
data["media_total_size"] = uploads.aggregate(v=models.Sum("size"))["v"] or 0
data["media_downloaded_size"] = (
uploads.with_file().aggregate(v=models.Sum("size"))["v"] or 0
)
return data
class Actor(models.Model):
ap_type = "Actor"
......
......@@ -125,3 +125,8 @@ class ManageDomainViewSet(
federation_tasks.update_domain_nodeinfo(domain_name=domain.name)
domain.refresh_from_db()
return response.Response(domain.nodeinfo, status=200)
@detail_route(methods=["get"])
def stats(self, request, *args, **kwargs):
domain = self.get_object()
return response.Response(domain.get_stats(), status=200)
......@@ -617,6 +617,8 @@ class UploadQuerySet(models.QuerySet):
def for_federation(self):
return self.filter(import_status="finished", mimetype__startswith="audio/")
def with_file(self):
return self.exclude(audio_file=None).exclude(audio_file='')
TRACK_FILE_IMPORT_STATUS_CHOICES = (
("pending", "Pending"),
......
......@@ -77,3 +77,23 @@ def test_external_domains(factories, settings):
settings.FEDERATION_HOSTNAME = d1.pk
assert list(models.Domain.objects.external()) == [d2]
def test_domain_stats(factories):
expected = {
"actors": 0,
"libraries": 0,
"tracks": 0,
"albums": 0,
"uploads": 0,
"artists": 0,
"outbox_activities": 0,
"received_library_follows": 0,
"emitted_library_follows": 0,
"media_total_size": 0,
"media_downloaded_size": 0,
}
domain = factories["federation.Domain"]()
assert domain.get_stats() == expected
......@@ -103,3 +103,14 @@ def test_domain_nodeinfo(factories, superuser_api_client, mocker):
assert response.data == {"status": "ok", "payload": {"hello": "world"}}
update_domain_nodeinfo.assert_called_once_with(domain_name=domain.name)
def test_domain_stats(factories, superuser_api_client, mocker):
domain = factories["federation.Domain"]()
get_stats = mocker.patch.object(
domain.__class__, "get_stats", return_value={"hello": "world"}
)
url = reverse("api:v1:manage:federation:domains-stats", kwargs={"pk": domain.name})
response = superuser_api_client.get(url)
assert response.status_code == 200
assert response.data == {"hello": "world"}
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