summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--stator/runner.py25
-rw-r--r--stator/views.py24
-rw-r--r--takahe/urls.py3
3 files changed, 43 insertions, 9 deletions
diff --git a/stator/runner.py b/stator/runner.py
index cb97f6e..48549bc 100644
--- a/stator/runner.py
+++ b/stator/runner.py
@@ -26,6 +26,7 @@ class StatorRunner:
liveness_file: Optional[str] = None,
schedule_interval: int = 30,
lock_expiry: int = 300,
+ run_for: int = 0,
):
self.models = models
self.runner_id = uuid.uuid4().hex
@@ -34,9 +35,11 @@ class StatorRunner:
self.liveness_file = liveness_file
self.schedule_interval = schedule_interval
self.lock_expiry = lock_expiry
+ self.run_for = run_for
async def run(self):
self.handled = 0
+ self.started = time.monotonic()
self.last_clean = time.monotonic() - self.schedule_interval
self.tasks = []
# For the first time period, launch tasks
@@ -71,17 +74,21 @@ class StatorRunner:
)
self.handled += 1
space_remaining -= 1
- # Prevent busylooping
- await asyncio.sleep(0.1)
- except KeyboardInterrupt:
- # Wait for tasks to finish
- print("Waiting for tasks to complete")
- while True:
- self.remove_completed_tasks()
- if not self.tasks:
+ # Are we in limited run mode?
+ if self.run_for and (time.monotonic() - self.started) > self.run_for:
break
# Prevent busylooping
- await asyncio.sleep(1)
+ await asyncio.sleep(0.5)
+ except KeyboardInterrupt:
+ pass
+ # Wait for tasks to finish
+ print("Waiting for tasks to complete")
+ while True:
+ self.remove_completed_tasks()
+ if not self.tasks:
+ break
+ # Prevent busylooping
+ await asyncio.sleep(0.1)
print("Complete")
return self.handled
diff --git a/stator/views.py b/stator/views.py
new file mode 100644
index 0000000..df51e3d
--- /dev/null
+++ b/stator/views.py
@@ -0,0 +1,24 @@
+from django.conf import settings
+from django.http import HttpResponse, HttpResponseForbidden
+from django.views import View
+
+from stator.models import StatorModel
+from stator.runner import StatorRunner
+
+
+class RequestRunner(View):
+ """
+ Runs a Stator runner within a HTTP request.
+ For when you're on something serverless.
+ """
+
+ async def get(self, request):
+ # Check the token, if supplied
+ if not settings.STATOR_TOKEN:
+ return HttpResponseForbidden("No token set")
+ if request.GET.get("token") != settings.STATOR_TOKEN:
+ return HttpResponseForbidden("Invalid token")
+ # Run on all models
+ runner = StatorRunner(StatorModel.subclasses, run_for=2)
+ handled = await runner.run()
+ return HttpResponse(f"Handled {handled}")
diff --git a/takahe/urls.py b/takahe/urls.py
index b94f205..98e1050 100644
--- a/takahe/urls.py
+++ b/takahe/urls.py
@@ -5,6 +5,7 @@ from django.views.static import serve
from activities.views import posts, search, timelines
from core import views as core
+from stator import views as stator
from users.views import activitypub, admin, auth, follows, identity, settings
urlpatterns = [
@@ -121,6 +122,8 @@ urlpatterns = [
path(".well-known/nodeinfo", activitypub.NodeInfo.as_view()),
path("nodeinfo/2.0/", activitypub.NodeInfo2.as_view()),
path("actor/", activitypub.SystemActorView.as_view()),
+ # Stator
+ path(".stator/", stator.RequestRunner.as_view()),
# Django admin
path("djadmin/", djadmin.site.urls),
# Media files