mirror of
https://github.com/django-q2/django-q2.git
synced 2026-09-28 10:18:12 +08:00
Compare commits
41
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
5ff834b794 | ||
|
|
2fe20033e3 | ||
|
|
1537872bf2 | ||
|
|
c9020ce94e | ||
|
|
5597d7ccd8 | ||
|
|
480b77dfe4 | ||
|
|
a699578c34 | ||
|
|
5975a2d081 | ||
|
|
936fdd10b1 | ||
|
|
fab97463c2 | ||
|
|
1abdc5b653 | ||
|
|
01df35c923 | ||
|
|
573b8da528 | ||
|
|
8a563d289d | ||
|
|
1b0f71a39b | ||
|
|
b51575a4b0 | ||
|
|
fd927087f1 | ||
|
|
386e04171b | ||
|
|
0054535624 | ||
|
|
09e65da5b3 | ||
|
|
65d2548e98 | ||
|
|
cbe51f995c | ||
|
|
0090a6f411 | ||
|
|
a154fd658a | ||
|
|
81f2531e3e | ||
|
|
c464751ae9 | ||
|
|
144536cbe4 | ||
|
|
7e72b68c7f | ||
|
|
404932117e | ||
|
|
ddc1aa2de1 | ||
|
|
351bf66d71 | ||
|
|
ccd760a69f | ||
|
|
fb23b6b825 | ||
|
|
35c911080b | ||
|
|
81058fc1cf | ||
|
|
505eb8d537 | ||
|
|
dcfe5b6650 | ||
|
|
c3b49cca25 | ||
|
|
c1e00b09cb | ||
|
|
8e403d0136 | ||
|
|
337a5782d9 |
+17
-18
@@ -26,25 +26,24 @@ jobs:
|
|||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
strategy:
|
strategy:
|
||||||
matrix:
|
matrix:
|
||||||
python-version: [ "3.8", "3.9", "3.10", "3.11", "3.12" ]
|
python-version:
|
||||||
django: [ "4.2", "5.0", "5.1"]
|
- "3.10"
|
||||||
|
- "3.11"
|
||||||
|
- "3.12"
|
||||||
|
- "3.13"
|
||||||
|
- "3.14"
|
||||||
|
django:
|
||||||
|
- "5.2"
|
||||||
|
- "6.0"
|
||||||
exclude:
|
exclude:
|
||||||
# django 5.1 does not support 3.8 and 3.9
|
# django 6 does not support 3.10
|
||||||
- python-version: "3.8"
|
- python-version: "3.10"
|
||||||
django: "5.1"
|
django: "6.0"
|
||||||
- python-version: "3.9"
|
# django 6 does not support 3.11
|
||||||
django: "5.1"
|
- python-version: "3.11"
|
||||||
# django 5.0 does not support 3.8 and 3.9
|
django: "6.0"
|
||||||
- python-version: "3.8"
|
|
||||||
django: "5.0"
|
|
||||||
- python-version: "3.9"
|
|
||||||
django: "5.0"
|
|
||||||
|
|
||||||
services:
|
services:
|
||||||
disque:
|
|
||||||
image: efrecon/disque:1.0-rc1
|
|
||||||
ports:
|
|
||||||
- '7711:7711/tcp'
|
|
||||||
mongodb:
|
mongodb:
|
||||||
image: mongo
|
image: mongo
|
||||||
ports:
|
ports:
|
||||||
@@ -73,8 +72,8 @@ jobs:
|
|||||||
- name: Install dependencies with Django ${{ matrix.django }}
|
- name: Install dependencies with Django ${{ matrix.django }}
|
||||||
run: |
|
run: |
|
||||||
python -m pip install --upgrade pip
|
python -m pip install --upgrade pip
|
||||||
pip install poetry
|
pip install poetry==1.8.5
|
||||||
poetry add "django==${{ matrix.django }}" --python=${{ matrix.python-version }}
|
poetry add "django~=${{ matrix.django }}a1" --python=${{ matrix.python-version }}
|
||||||
poetry install -E testing
|
poetry install -E testing
|
||||||
- name: Run Tests
|
- name: Run Tests
|
||||||
run: |
|
run: |
|
||||||
|
|||||||
@@ -1,5 +1,56 @@
|
|||||||
# Changelog
|
# Changelog
|
||||||
|
|
||||||
|
## [v1.10.0](https://github.com/django-q2/django-q2/tree/v1.10.0) (2026-05-01)
|
||||||
|
|
||||||
|
- fix: Fix incorrect signal import (#308) https://github.com/django-q2/django-q2/pull/308
|
||||||
|
- Add post_execute_in_worker signal (#309) https://github.com/django-q2/django-q2/pull/309
|
||||||
|
- Fix BadSignature after the default Django cache expires (#311) https://github.com/django-q2/django-q2/pull/311
|
||||||
|
- feat:add Simplified Chinese Translation (#314) https://github.com/django-q2/django-q2/pull/314
|
||||||
|
- Update Django Q2 compatibility information (#316) https://github.com/django-q2/django-q2/pull/316
|
||||||
|
- Don't close DB connection if async_task was called with sync=True (#301) https://github.com/django-q2/django-q2/pull/301
|
||||||
|
- Convert queue size and count to string in monitor (#319) https://github.com/django-q2/django-q2/pull/319
|
||||||
|
- Fix unbounded growth of Broker.set_stat cluster master list (#322) https://github.com/django-q2/django-q2/pull/322
|
||||||
|
- Update Python base image to 3.9-slim-bookworm (#325) https://github.com/django-q2/django-q2/pull/325
|
||||||
|
- feat: add ru locale and improve translations (#320) https://github.com/django-q2/django-q2/pull/320
|
||||||
|
|
||||||
|
|
||||||
|
## [v1.9.0](https://github.com/django-q2/django-q2/tree/v1.9.0) (2025-12-04)
|
||||||
|
|
||||||
|
- Django 6.0 support https://github.com/django-q2/django-q2/pull/307
|
||||||
|
- Fix to make tests work with redis-py > 5 https://github.com/django-q2/django-q2/pull/282
|
||||||
|
|
||||||
|
## [v1.8.0](https://github.com/django-q2/django-q2/tree/v1.8.0) (2025-04-25)
|
||||||
|
|
||||||
|
- Delete deprecated imports and unwrapping https://github.com/django-q2/django-q2/pull/261
|
||||||
|
- Remove disque from CI https://github.com/django-q2/django-q2/pull/270
|
||||||
|
- Avoid creating task run on Scheduler creation https://github.com/django-q2/django-q2/pull/268
|
||||||
|
- Update tested versions, add python 3.13 support and django 5.2 support. Drop python 3.8 support https://github.com/django-q2/django-q2/pull/271
|
||||||
|
- Move timeout function from ORM broker into class to allow easy customization https://github.com/django-q2/django-q2/pull/274
|
||||||
|
|
||||||
|
## [v1.7.6](https://github.com/django-q2/django-q2/tree/v1.7.6) (2025-01-12)
|
||||||
|
|
||||||
|
- Make poetry version fixed in CI https://github.com/django-q2/django-q2/pull/260
|
||||||
|
|
||||||
|
## [v1.7.5](https://github.com/django-q2/django-q2/tree/v1.7.5) (2025-01-12)
|
||||||
|
|
||||||
|
- perf: avoid checking success tasks when save limit is disabled https://github.com/django-q2/django-q2/pull/255
|
||||||
|
- Fix install path for CHANGELOG.md https://github.com/django-q2/django-q2/pull/258
|
||||||
|
|
||||||
|
## [v1.7.4](https://github.com/django-q2/django-q2/tree/v1.7.4) (2024-11-03)
|
||||||
|
|
||||||
|
- Decrease the MAX_RSS set in test_cluster::test_max_rss https://github.com/django-q2/django-q2/pull/240
|
||||||
|
- Fix BROKER_CLASS monkeypatch in test_brokers https://github.com/django-q2/django-q2/pull/239
|
||||||
|
- Fix 'receive_message_wait_time_seconds' SQS broker management https://github.com/django-q2/django-q2/pull/243
|
||||||
|
|
||||||
|
## [v1.7.3](https://github.com/django-q2/django-q2/tree/v1.7.3) (2024-10-15)
|
||||||
|
|
||||||
|
- Catch missing SEGALRM with AttributeError instead of ValueError https://github.com/django-q2/django-q2/pull/223
|
||||||
|
- Refactor timeout handling to handle AttributeError and ValueError for Windows users https://github.com/django-q2/django-q2/pull/234
|
||||||
|
- Fix type check for args in scheduler.py E721 https://github.com/django-q2/django-q2/pull/233
|
||||||
|
- Only trigger prometheus if configured https://github.com/django-q2/django-q2/pull/231
|
||||||
|
- Fix missing ack_id when finishing task https://github.com/django-q2/django-q2/pull/224
|
||||||
|
|
||||||
|
|
||||||
## [v1.7.2](https://github.com/django-q2/django-q2/tree/v1.7.2) (2024-09-09)
|
## [v1.7.2](https://github.com/django-q2/django-q2/tree/v1.7.2) (2024-09-09)
|
||||||
|
|
||||||
- Fix twine check
|
- Fix twine check
|
||||||
|
|||||||
+5
-1
@@ -1,5 +1,5 @@
|
|||||||
# Sets the python version
|
# Sets the python version
|
||||||
FROM python:3.9.5-slim
|
FROM python:3.12-slim-bookworm
|
||||||
|
|
||||||
# Allows the logs generated by python apps to be rendered in the terminal
|
# Allows the logs generated by python apps to be rendered in the terminal
|
||||||
ENV PYTHONUNBUFFERED 1
|
ENV PYTHONUNBUFFERED 1
|
||||||
@@ -7,6 +7,10 @@ ENV PYTHONUNBUFFERED 1
|
|||||||
# Sets the default shell to bash
|
# Sets the default shell to bash
|
||||||
ENV SHELL /bin/bash
|
ENV SHELL /bin/bash
|
||||||
|
|
||||||
|
RUN set -ex \
|
||||||
|
&& apt update \
|
||||||
|
&& apt-get install gcc python3-dev --yes
|
||||||
|
|
||||||
# Upgrades pip
|
# Upgrades pip
|
||||||
RUN pip install -U pip setuptools
|
RUN pip install -U pip setuptools
|
||||||
|
|
||||||
|
|||||||
@@ -2,16 +2,16 @@ dev:
|
|||||||
docker compose -f web-docker-compose.yaml up
|
docker compose -f web-docker-compose.yaml up
|
||||||
|
|
||||||
test:
|
test:
|
||||||
docker-compose -f test-services-docker-compose.yaml run --rm django-q2 poetry run pytest
|
docker compose -f test-services-docker-compose.yaml run --rm django-q2 poetry run pytest
|
||||||
|
|
||||||
shell:
|
shell:
|
||||||
docker-compose -f test-services-docker-compose.yaml run --rm django-q2 poetry run python manage.py shell
|
docker compose -f test-services-docker-compose.yaml run --rm django-q2 poetry run python manage.py shell
|
||||||
|
|
||||||
makemigrations:
|
makemigrations:
|
||||||
docker-compose -f test-services-docker-compose.yaml run --rm django-q2 poetry run python manage.py makemigrations
|
docker compose -f test-services-docker-compose.yaml run --rm django-q2 poetry run python manage.py makemigrations
|
||||||
|
|
||||||
migrate:
|
migrate:
|
||||||
docker-compose -f test-services-docker-compose.yaml run --rm django-q2 poetry run python manage.py migrate
|
docker compose -f test-services-docker-compose.yaml run --rm django-q2 poetry run python manage.py migrate
|
||||||
|
|
||||||
createsuperuser:
|
createsuperuser:
|
||||||
docker compose -f web-docker-compose.yaml run --rm web python manage.py createsuperuser
|
docker compose -f web-docker-compose.yaml run --rm web python manage.py createsuperuser
|
||||||
|
|||||||
+5
-2
@@ -35,10 +35,13 @@ See the `changelog <https://github.com/GDay/django-q2/blob/master/CHANGELOG.md>`
|
|||||||
Requirements
|
Requirements
|
||||||
~~~~~~~~~~~~
|
~~~~~~~~~~~~
|
||||||
|
|
||||||
- `Django <https://www.djangoproject.com>`__ > = 4.2
|
- `Django <https://www.djangoproject.com>`__ 5.2 and 6.0
|
||||||
- `Django-picklefield <https://github.com/gintas/django-picklefield>`__
|
- `Django-picklefield <https://github.com/gintas/django-picklefield>`__
|
||||||
|
|
||||||
Tested with: Python 3.8, 3.9, 3.10, 3.11 and 3.12. Works with Django 4.2.X and 5.0.X
|
Tested with:
|
||||||
|
|
||||||
|
* Python 3.10 to 3.14.
|
||||||
|
* Django 5.2 and 6.0.
|
||||||
|
|
||||||
Brokers
|
Brokers
|
||||||
~~~~~~~
|
~~~~~~~
|
||||||
|
|||||||
Executable
+19
@@ -0,0 +1,19 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
# Note that this file needs to have the executable bit set for it to work with later localstack implementations.
|
||||||
|
|
||||||
|
export DEFAULT_REGION=us-west-2
|
||||||
|
|
||||||
|
create_sqs() {
|
||||||
|
QUEUE_NAME="$1"
|
||||||
|
TIMEOUT=${2:-60}
|
||||||
|
DL_QUEUE_URL=$(awslocal sqs create-queue --queue-name "dl-$QUEUE_NAME" --query QueueUrl --output text)
|
||||||
|
echo ">>> Created $DL_QUEUE_URL queue!"
|
||||||
|
DL_QUEUE_ARN=$(awslocal sqs get-queue-attributes --queue-url "$DL_QUEUE_URL" --attribute-names QueueArn --query Attributes.QueueArn --output text)
|
||||||
|
awslocal sqs create-queue --queue-name "$QUEUE_NAME" --attributes '{
|
||||||
|
"RedrivePolicy": "{\"deadLetterTargetArn\": \"'"$DL_QUEUE_ARN"'\",\"maxReceiveCount\":\"3\"}",
|
||||||
|
"VisibilityTimeout": "'"$TIMEOUT"'"
|
||||||
|
}'
|
||||||
|
}
|
||||||
|
|
||||||
|
# Create SQS queues
|
||||||
|
create_sqs testing
|
||||||
@@ -1,8 +1,3 @@
|
|||||||
import django
|
VERSION = (1, 10, 0)
|
||||||
|
|
||||||
VERSION = (1, 7, 2)
|
|
||||||
|
|
||||||
if django.VERSION < (3, 2):
|
|
||||||
default_app_config = "django_q.apps.DjangoQConfig"
|
|
||||||
|
|
||||||
__all__ = ["conf", "cluster", "models", "tasks"]
|
__all__ = ["conf", "cluster", "models", "tasks"]
|
||||||
|
|||||||
+10
-1
@@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
from django.contrib import admin
|
from django.contrib import admin
|
||||||
from django.db.models.expressions import OuterRef, Subquery
|
from django.db.models.expressions import OuterRef, Subquery
|
||||||
|
from django.template.defaultfilters import truncatechars
|
||||||
from django.urls import reverse
|
from django.urls import reverse
|
||||||
from django.utils.html import format_html
|
from django.utils.html import format_html
|
||||||
from django.utils.translation import gettext_lazy as _
|
from django.utils.translation import gettext_lazy as _
|
||||||
@@ -60,6 +61,10 @@ class TaskAdmin(admin.ModelAdmin):
|
|||||||
"""Set all fields readonly."""
|
"""Set all fields readonly."""
|
||||||
return list(self.readonly_fields) + [field.name for field in obj._meta.fields]
|
return list(self.readonly_fields) + [field.name for field in obj._meta.fields]
|
||||||
|
|
||||||
|
@admin.display(description=_("Time Taken"))
|
||||||
|
def time_taken(self, obj):
|
||||||
|
return obj.time_taken()
|
||||||
|
|
||||||
|
|
||||||
class FailAdmin(admin.ModelAdmin):
|
class FailAdmin(admin.ModelAdmin):
|
||||||
"""model admin for failed tasks."""
|
"""model admin for failed tasks."""
|
||||||
@@ -87,6 +92,10 @@ class FailAdmin(admin.ModelAdmin):
|
|||||||
"""Set all fields readonly."""
|
"""Set all fields readonly."""
|
||||||
return list(self.readonly_fields) + [field.name for field in obj._meta.fields]
|
return list(self.readonly_fields) + [field.name for field in obj._meta.fields]
|
||||||
|
|
||||||
|
@admin.display(description=_("Short result"))
|
||||||
|
def short_result(self, obj):
|
||||||
|
return truncatechars(obj.result, 100)
|
||||||
|
|
||||||
|
|
||||||
class ScheduleAdmin(admin.ModelAdmin):
|
class ScheduleAdmin(admin.ModelAdmin):
|
||||||
"""model admin for schedules"""
|
"""model admin for schedules"""
|
||||||
@@ -138,7 +147,7 @@ class ScheduleAdmin(admin.ModelAdmin):
|
|||||||
url = reverse("admin:django_q_success_change", args=(obj.task_id,))
|
url = reverse("admin:django_q_success_change", args=(obj.task_id,))
|
||||||
else:
|
else:
|
||||||
url = reverse("admin:django_q_failure_change", args=(obj.task_id,))
|
url = reverse("admin:django_q_failure_change", args=(obj.task_id,))
|
||||||
return format_html(f'<a href="{url}">[{obj.task_name}]</a>')
|
return format_html('<a href="{}">[{}]</a>', url, obj.task_name)
|
||||||
return None
|
return None
|
||||||
|
|
||||||
get_last_run.allow_tags = True
|
get_last_run.allow_tags = True
|
||||||
|
|||||||
@@ -106,8 +106,13 @@ class Broker:
|
|||||||
return
|
return
|
||||||
key_list = self.cache.get(Conf.Q_STAT, [])
|
key_list = self.cache.get(Conf.Q_STAT, [])
|
||||||
if key not in key_list:
|
if key not in key_list:
|
||||||
|
# Prune stale entries whose per-stat value has expired, so the
|
||||||
|
# master list cannot grow without bound across cluster restarts.
|
||||||
|
key_list = [k for k in key_list if self.cache.get(k) is not None]
|
||||||
key_list.append(key)
|
key_list.append(key)
|
||||||
self.cache.set(Conf.Q_STAT, key_list)
|
# timeout=None: master list lifetime is managed by membership
|
||||||
|
# changes, not by TTL refresh on every heartbeat.
|
||||||
|
self.cache.set(Conf.Q_STAT, key_list, None)
|
||||||
return self.cache.set(key, value, timeout)
|
return self.cache.set(key, value, timeout)
|
||||||
|
|
||||||
def get_stat(self, key: str):
|
def get_stat(self, key: str):
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
import copy
|
||||||
|
|
||||||
from boto3 import Session
|
from boto3 import Session
|
||||||
from botocore.client import ClientError
|
from botocore.client import ClientError
|
||||||
|
|
||||||
@@ -78,15 +80,15 @@ class Sqs(Broker):
|
|||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def get_connection(list_key: str = None) -> Session:
|
def get_connection(list_key: str = None) -> Session:
|
||||||
config = Conf.SQS
|
config_cloned = copy.deepcopy(Conf.SQS)
|
||||||
if "aws_region" in config:
|
if "aws_region" in config_cloned:
|
||||||
config["region_name"] = config["aws_region"]
|
config_cloned["region_name"] = config_cloned["aws_region"]
|
||||||
del config["aws_region"]
|
del config_cloned["aws_region"]
|
||||||
|
|
||||||
if "receive_message_wait_time_seconds" in config:
|
if "receive_message_wait_time_seconds" in config_cloned:
|
||||||
del config["receive_message_wait_time_seconds"]
|
del config_cloned["receive_message_wait_time_seconds"]
|
||||||
|
|
||||||
return Session(**config)
|
return Session(**config_cloned)
|
||||||
|
|
||||||
def get_queue(self):
|
def get_queue(self):
|
||||||
self.sqs = self.connection.resource("sqs")
|
self.sqs = self.connection.resource("sqs")
|
||||||
|
|||||||
@@ -10,10 +10,6 @@ from django_q.conf import Conf, logger
|
|||||||
from django_q.models import OrmQ
|
from django_q.models import OrmQ
|
||||||
|
|
||||||
|
|
||||||
def _timeout():
|
|
||||||
return timezone.now() + timedelta(seconds=Conf.RETRY)
|
|
||||||
|
|
||||||
|
|
||||||
class ORM(Broker):
|
class ORM(Broker):
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def get_connection(list_key: str = None):
|
def get_connection(list_key: str = None):
|
||||||
@@ -28,6 +24,9 @@ class ORM(Broker):
|
|||||||
logger.debug("Broker in an atomic transaction")
|
logger.debug("Broker in an atomic transaction")
|
||||||
return OrmQ.objects.using(Conf.ORM)
|
return OrmQ.objects.using(Conf.ORM)
|
||||||
|
|
||||||
|
def timeout(self, task):
|
||||||
|
return timezone.now() + timedelta(seconds=Conf.RETRY)
|
||||||
|
|
||||||
def queue_size(self) -> int:
|
def queue_size(self) -> int:
|
||||||
return (
|
return (
|
||||||
self.get_connection()
|
self.get_connection()
|
||||||
@@ -75,7 +74,7 @@ class ORM(Broker):
|
|||||||
if (
|
if (
|
||||||
self.get_connection()
|
self.get_connection()
|
||||||
.filter(id=task.id, lock=task.lock)
|
.filter(id=task.id, lock=task.lock)
|
||||||
.update(lock=_timeout())
|
.update(lock=self.timeout(task))
|
||||||
):
|
):
|
||||||
task_list.append((task.pk, task.payload))
|
task_list.append((task.pk, task.payload))
|
||||||
# else don't process, as another cluster has been faster than us on
|
# else don't process, as another cluster has been faster than us on
|
||||||
|
|||||||
+35
-4
@@ -1,4 +1,5 @@
|
|||||||
# Standard
|
# Standard
|
||||||
|
import os
|
||||||
import signal
|
import signal
|
||||||
import socket
|
import socket
|
||||||
import uuid
|
import uuid
|
||||||
@@ -72,7 +73,30 @@ class Cluster:
|
|||||||
)
|
)
|
||||||
self.sentinel.start()
|
self.sentinel.start()
|
||||||
logger.info(_("Q Cluster %(name)s starting.") % {"name": self.name})
|
logger.info(_("Q Cluster %(name)s starting.") % {"name": self.name})
|
||||||
while not self.start_event.is_set():
|
# Wait for the sentinel to set start_event by polling the event's state. We
|
||||||
|
# cannot call wait() as that will deadlock if a signal is received while blocked
|
||||||
|
# in wait(), as the sentinel will block in start_event.set() while this process
|
||||||
|
# is blocked in sentinel.join(). It is also necessary to check for start_event
|
||||||
|
# being set to None by the signal handler.
|
||||||
|
while self.start_event and not self.start_event.is_set():
|
||||||
|
# While waiting for the sentinel to start, also check for sentinel premature
|
||||||
|
# death
|
||||||
|
if not self.sentinel.is_alive():
|
||||||
|
if self.sentinel.exitcode == 0:
|
||||||
|
# the cluster was stopped via SIGTERM/SIGINT and sentinel early
|
||||||
|
# termination was intentional -- exit quietly
|
||||||
|
break
|
||||||
|
logger.error(
|
||||||
|
_(
|
||||||
|
"Q Cluster %(name)s failed to start. Sentinel exited "
|
||||||
|
"with exit code %(exitcode)s."
|
||||||
|
)
|
||||||
|
% {"name": self.name, "exitcode": self.sentinel.exitcode}
|
||||||
|
)
|
||||||
|
raise RuntimeError(
|
||||||
|
f"Q Cluster {self.name} failed to start: sentinel exited "
|
||||||
|
f"with code {self.sentinel.exitcode}"
|
||||||
|
)
|
||||||
sleep(0.1)
|
sleep(0.1)
|
||||||
return self.pid
|
return self.pid
|
||||||
|
|
||||||
@@ -230,8 +254,14 @@ class Sentinel:
|
|||||||
% {"name": process.name}
|
% {"name": process.name}
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
if prometheus_multiprocess:
|
# check if prometheus is proper configurated
|
||||||
|
prometheus_path = os.getenv(
|
||||||
|
"PROMETHEUS_MULTIPROC_DIR", os.getenv("prometheus_multiproc_dir")
|
||||||
|
)
|
||||||
|
|
||||||
|
if prometheus_multiprocess and prometheus_path:
|
||||||
prometheus_multiprocess.mark_process_dead(process.pid)
|
prometheus_multiprocess.mark_process_dead(process.pid)
|
||||||
|
|
||||||
self.pool.remove(process)
|
self.pool.remove(process)
|
||||||
self.spawn_worker()
|
self.spawn_worker()
|
||||||
if process.timer.value == 0:
|
if process.timer.value == 0:
|
||||||
@@ -306,7 +336,7 @@ class Sentinel:
|
|||||||
counter = 0
|
counter = 0
|
||||||
cycle = Conf.GUARD_CYCLE # guard loop sleep in seconds
|
cycle = Conf.GUARD_CYCLE # guard loop sleep in seconds
|
||||||
# Guard loop. Runs at least once
|
# Guard loop. Runs at least once
|
||||||
while not self.stop_event.is_set() or not counter:
|
while True:
|
||||||
# Check Workers
|
# Check Workers
|
||||||
for p in self.pool:
|
for p in self.pool:
|
||||||
with p.timer.get_lock():
|
with p.timer.get_lock():
|
||||||
@@ -330,7 +360,8 @@ class Sentinel:
|
|||||||
scheduler(broker=self.broker)
|
scheduler(broker=self.broker)
|
||||||
# Save current status
|
# Save current status
|
||||||
Stat(self).save()
|
Stat(self).save()
|
||||||
sleep(cycle)
|
if self.stop_event.wait(cycle):
|
||||||
|
break
|
||||||
self.stop()
|
self.stop()
|
||||||
|
|
||||||
def stop(self):
|
def stop(self):
|
||||||
|
|||||||
+1
-1
@@ -1,9 +1,9 @@
|
|||||||
import logging
|
import logging
|
||||||
import os
|
import os
|
||||||
|
import signal
|
||||||
import sys
|
import sys
|
||||||
from copy import deepcopy
|
from copy import deepcopy
|
||||||
from multiprocessing import cpu_count
|
from multiprocessing import cpu_count
|
||||||
from signal import signal
|
|
||||||
from warnings import warn
|
from warnings import warn
|
||||||
|
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ msgid ""
|
|||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: \n"
|
"Project-Id-Version: \n"
|
||||||
"Report-Msgid-Bugs-To: \n"
|
"Report-Msgid-Bugs-To: \n"
|
||||||
"POT-Creation-Date: 2023-01-26 01:38+0000\n"
|
"POT-Creation-Date: 2026-04-17 21:10+0000\n"
|
||||||
"PO-Revision-Date: 2018-08-05 18:28+0200\n"
|
"PO-Revision-Date: 2018-08-05 18:28+0200\n"
|
||||||
"Last-Translator: Jonas Winkler\n"
|
"Last-Translator: Jonas Winkler\n"
|
||||||
"Language-Team: \n"
|
"Language-Team: \n"
|
||||||
@@ -17,37 +17,45 @@ msgstr ""
|
|||||||
"X-Generator: Poedit 2.1.1\n"
|
"X-Generator: Poedit 2.1.1\n"
|
||||||
"Plural-Forms: nplurals=2; plural=(n > 1);\n"
|
"Plural-Forms: nplurals=2; plural=(n > 1);\n"
|
||||||
|
|
||||||
#: admin.py:43
|
#: admin.py:30
|
||||||
msgid "Resubmit selected tasks to queue"
|
msgid "Resubmit selected tasks to queue"
|
||||||
msgstr "Ausgewählte Aufgaben erneut ausführen"
|
msgstr "Ausgewählte Aufgaben erneut ausführen"
|
||||||
|
|
||||||
#: admin.py:107 models.py:293
|
#: admin.py:64
|
||||||
|
msgid "Time Taken"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: admin.py:95
|
||||||
|
msgid "Short result"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: admin.py:142 models.py:412
|
||||||
#, fuzzy
|
#, fuzzy
|
||||||
#| msgid "Success"
|
#| msgid "Success"
|
||||||
msgid "success"
|
msgid "success"
|
||||||
msgstr "erfolg"
|
msgstr "erfolg"
|
||||||
|
|
||||||
#: admin.py:119 models.py:295
|
#: admin.py:154 models.py:414
|
||||||
msgid "last_run"
|
msgid "last_run"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: cluster.py:79
|
#: cluster.py:75
|
||||||
#, python-format
|
#, python-format
|
||||||
msgid "Q Cluster %(name)s starting."
|
msgid "Q Cluster %(name)s starting."
|
||||||
msgstr "Q-Cluster %(name)s wird gestartet."
|
msgstr "Q-Cluster %(name)s wird gestartet."
|
||||||
|
|
||||||
#: cluster.py:87
|
#: cluster.py:83
|
||||||
#, fuzzy, python-format
|
#, fuzzy, python-format
|
||||||
#| msgid "Q Cluster-{} stopping."
|
#| msgid "Q Cluster-{} stopping."
|
||||||
msgid "Q Cluster %(name)s stopping."
|
msgid "Q Cluster %(name)s stopping."
|
||||||
msgstr "Q-Cluster {name} wird gestoppt."
|
msgstr "Q-Cluster {name} wird gestoppt."
|
||||||
|
|
||||||
#: cluster.py:90
|
#: cluster.py:86
|
||||||
#, python-format
|
#, python-format
|
||||||
msgid "Q Cluster %(name)s has stopped."
|
msgid "Q Cluster %(name)s has stopped."
|
||||||
msgstr "Q-Cluster %(name)s wurde gestoppt."
|
msgstr "Q-Cluster %(name)s wurde gestoppt."
|
||||||
|
|
||||||
#: cluster.py:97
|
#: cluster.py:93
|
||||||
#, python-format
|
#, python-format
|
||||||
msgid "%(name)s got signal %(signal)s"
|
msgid "%(name)s got signal %(signal)s"
|
||||||
msgstr "%(name)s erhielt das Signal %(signal)s"
|
msgstr "%(name)s erhielt das Signal %(signal)s"
|
||||||
@@ -62,7 +70,7 @@ msgstr "Monitor %(name)s wurde nach unerwartetem Absturz neu gestartet"
|
|||||||
msgid "reincarnated pusher %(name)s after sudden death"
|
msgid "reincarnated pusher %(name)s after sudden death"
|
||||||
msgstr "Pusher %(name)s wurde nach unerwartetem Absturz neu gestartet"
|
msgstr "Pusher %(name)s wurde nach unerwartetem Absturz neu gestartet"
|
||||||
|
|
||||||
#: cluster.py:250
|
#: cluster.py:262
|
||||||
#, fuzzy, python-format
|
#, fuzzy, python-format
|
||||||
#| msgid "reincarnated worker %(name)s after timeout"
|
#| msgid "reincarnated worker %(name)s after timeout"
|
||||||
msgid ""
|
msgid ""
|
||||||
@@ -70,123 +78,57 @@ msgid ""
|
|||||||
"%(task_name)s"
|
"%(task_name)s"
|
||||||
msgstr "Worker %(name)s wurde nach Zeitüberschreitung neu gestartet"
|
msgstr "Worker %(name)s wurde nach Zeitüberschreitung neu gestartet"
|
||||||
|
|
||||||
#: cluster.py:255
|
#: cluster.py:265
|
||||||
#, python-format
|
#, python-format
|
||||||
msgid "reincarnated worker %(name)s after timeout"
|
msgid "reincarnated worker %(name)s after timeout"
|
||||||
msgstr "Worker %(name)s wurde nach Zeitüberschreitung neu gestartet"
|
msgstr "Worker %(name)s wurde nach Zeitüberschreitung neu gestartet"
|
||||||
|
|
||||||
#: cluster.py:260
|
#: cluster.py:270
|
||||||
#, python-format
|
#, python-format
|
||||||
msgid "recycled worker %(name)s"
|
msgid "recycled worker %(name)s"
|
||||||
msgstr "Worker %(name)s wurde wiederverwendet"
|
msgstr "Worker %(name)s wurde wiederverwendet"
|
||||||
|
|
||||||
#: cluster.py:263
|
#: cluster.py:273
|
||||||
#, python-format
|
#, python-format
|
||||||
msgid "reincarnated worker %(name)s after death"
|
msgid "reincarnated worker %(name)s after death"
|
||||||
msgstr "Worker %(name)s wurde nach unerwartetem Absturz neu gestartet"
|
msgstr "Worker %(name)s wurde nach unerwartetem Absturz neu gestartet"
|
||||||
|
|
||||||
#: cluster.py:287
|
#: cluster.py:297
|
||||||
#, python-format
|
#, python-format
|
||||||
msgid "%(name)s guarding cluster %(cluster_name)s"
|
msgid "%(name)s guarding cluster %(cluster_name)s"
|
||||||
msgstr "%(name)s beschützt das Cluster %(cluster_name)s"
|
msgstr "%(name)s beschützt das Cluster %(cluster_name)s"
|
||||||
|
|
||||||
#: cluster.py:296
|
#: cluster.py:307
|
||||||
#, python-format
|
#, python-format
|
||||||
msgid "Q Cluster %(cluster_name)s running."
|
msgid "Q Cluster %(cluster_name)s running."
|
||||||
msgstr "Q-Cluster %(cluster_name)s läuft."
|
msgstr "Q-Cluster %(cluster_name)s läuft."
|
||||||
|
|
||||||
#: cluster.py:332
|
#: cluster.py:346
|
||||||
#, python-format
|
#, python-format
|
||||||
msgid "%(name)s stopping cluster processes"
|
msgid "%(name)s stopping cluster processes"
|
||||||
msgstr "%(name)s hält Cluster-Prozesse an"
|
msgstr "%(name)s hält Cluster-Prozesse an"
|
||||||
|
|
||||||
#: cluster.py:357
|
#: cluster.py:371
|
||||||
#, python-format
|
#, python-format
|
||||||
msgid "%(name)s waiting for the monitor."
|
msgid "%(name)s waiting for the monitor."
|
||||||
msgstr "%(name)s wartet auf den Monitor."
|
msgstr "%(name)s wartet auf den Monitor."
|
||||||
|
|
||||||
#: cluster.py:383
|
#: cluster.py:394
|
||||||
#, fuzzy, python-format
|
|
||||||
#| msgid "%(process_name)s pushing tasks at %(id)s"
|
|
||||||
msgid "%(name)s pushing tasks at %(id)s"
|
|
||||||
msgstr "%(process_name)s veröffentlicht Aufagaben auf %(id)s"
|
|
||||||
|
|
||||||
#: cluster.py:407
|
|
||||||
#, python-format
|
|
||||||
msgid "queueing from %(list_key)s"
|
|
||||||
msgstr "Einreihen von %(list_key)s"
|
|
||||||
|
|
||||||
#: cluster.py:411
|
|
||||||
#, python-format
|
|
||||||
msgid "%(name)s stopped pushing tasks"
|
|
||||||
msgstr "%(name)s veröffentlicht keine Aufgaben mehr"
|
|
||||||
|
|
||||||
#: cluster.py:426
|
|
||||||
#, python-format
|
|
||||||
msgid "%(name)s monitoring at %(id)s"
|
|
||||||
msgstr "%(name)s beobachtet auf %(id)s"
|
|
||||||
|
|
||||||
#: cluster.py:445
|
|
||||||
#, python-format
|
|
||||||
msgid "Processed '%(info_name)s' (%(task_name)s)"
|
|
||||||
msgstr "[%(task_name)s] - '%(info_name)s' wurde verarbeitet"
|
|
||||||
|
|
||||||
#: cluster.py:451
|
|
||||||
#, python-format
|
|
||||||
msgid "Failed '%(info_name)s' (%(task_name)s) - %(task_result)s"
|
|
||||||
msgstr "'%(info_name)s' (%(task_name)s) ist fehlgeschlagen - %(task_result)s"
|
|
||||||
|
|
||||||
#: cluster.py:458
|
|
||||||
#, python-format
|
|
||||||
msgid "%(name)s stopped monitoring results"
|
|
||||||
msgstr "%(name)s überwacht keine Ergebnisse mehr"
|
|
||||||
|
|
||||||
#: cluster.py:474
|
|
||||||
#, python-format
|
|
||||||
msgid "%(proc_name)s ready for work at %(id)s"
|
|
||||||
msgstr "%(proc_name)s ist bereit für Arbeit auf %(id)s"
|
|
||||||
|
|
||||||
#: cluster.py:494
|
|
||||||
#, fuzzy, python-format
|
|
||||||
#| msgid "%(proc_name)s processing '%(func_name)s' (%(task_name)s)"
|
|
||||||
msgid "%(proc_name)s processing %(task_name)s '%(func_name)s'"
|
|
||||||
msgstr "%(proc_name)s verarbeitet '%(func_name)s' (%(task_name)s)"
|
|
||||||
|
|
||||||
#: cluster.py:546
|
|
||||||
#, python-format
|
|
||||||
msgid "%(proc_name)s stopped doing work"
|
|
||||||
msgstr "%(proc_name)s hat die Arbeit beendet"
|
|
||||||
|
|
||||||
#: cluster.py:751
|
|
||||||
#, python-format
|
|
||||||
msgid "%(process_name)s failed to create a task from schedule [%(schedule)s]"
|
|
||||||
msgstr ""
|
|
||||||
"%(process_name)s konnte keine Aufgabe von Zeitplan [%(schedule)s] erstellen"
|
|
||||||
|
|
||||||
#: cluster.py:762
|
|
||||||
#, fuzzy, python-format
|
|
||||||
#| msgid "%(process_name)s created a task from schedule [%(schedule)s]"
|
|
||||||
msgid ""
|
|
||||||
"%(process_name)s created task %(task_name)s from schedule [%(schedule)s]"
|
|
||||||
msgstr ""
|
|
||||||
"%(process_name)s hat eine Aufgabe des Zeitplans [%(schedule)s] erstellt"
|
|
||||||
|
|
||||||
#: cluster.py:808
|
|
||||||
msgid "Skipping cpu affinity because psutil was not found."
|
msgid "Skipping cpu affinity because psutil was not found."
|
||||||
msgstr "Cpu-Affinität wird übersprungen, da psutil nicht gefunden wurde."
|
msgstr "Cpu-Affinität wird übersprungen, da psutil nicht gefunden wurde."
|
||||||
|
|
||||||
#: cluster.py:813
|
#: cluster.py:399
|
||||||
msgid "Faking cpu affinity because it is not supported on this platform"
|
msgid "Faking cpu affinity because it is not supported on this platform"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Vortäuschen von CPU-Affinität, da diese auf dieser Plattform nicht "
|
"Vortäuschen von CPU-Affinität, da diese auf dieser Plattform nicht "
|
||||||
"unterstützt wird"
|
"unterstützt wird"
|
||||||
|
|
||||||
#: cluster.py:835
|
#: cluster.py:421
|
||||||
#, python-format
|
#, python-format
|
||||||
msgid "%(pid)s will use cpu %(affinity)s"
|
msgid "%(pid)s will use cpu %(affinity)s"
|
||||||
msgstr "%(pid)s wird CPU %(affinity)s benutzen"
|
msgstr "%(pid)s wird CPU %(affinity)s benutzen"
|
||||||
|
|
||||||
#: conf.py:90
|
#: conf.py:122
|
||||||
#, python-format
|
#, python-format
|
||||||
msgid ""
|
msgid ""
|
||||||
"SAVE_LIMIT_PER (%(option)s) is not a valid option. Options are: 'group', "
|
"SAVE_LIMIT_PER (%(option)s) is not a valid option. Options are: 'group', "
|
||||||
@@ -196,28 +138,28 @@ msgstr ""
|
|||||||
"'group', 'name', 'func' und None. Standard ist None."
|
"'group', 'name', 'func' und None. Standard ist None."
|
||||||
|
|
||||||
#. Translators: Cluster status descriptions
|
#. Translators: Cluster status descriptions
|
||||||
#: conf.py:207
|
#: conf.py:239
|
||||||
msgid "Starting"
|
msgid "Starting"
|
||||||
msgstr "Wird gestartet"
|
msgstr "Wird gestartet"
|
||||||
|
|
||||||
#: conf.py:208
|
#: conf.py:240
|
||||||
msgid "Working"
|
msgid "Working"
|
||||||
msgstr "Arbeitet"
|
msgstr "Arbeitet"
|
||||||
|
|
||||||
#: conf.py:209
|
#: conf.py:241
|
||||||
msgid "Idle"
|
msgid "Idle"
|
||||||
msgstr "Leerlauf"
|
msgstr "Leerlauf"
|
||||||
|
|
||||||
#: conf.py:210
|
#: conf.py:242
|
||||||
msgid "Stopped"
|
msgid "Stopped"
|
||||||
msgstr "Gestoppt"
|
msgstr "Gestoppt"
|
||||||
|
|
||||||
#: conf.py:211
|
#: conf.py:243
|
||||||
msgid "Stopping"
|
msgid "Stopping"
|
||||||
msgstr "Wird gestoppt"
|
msgstr "Wird gestoppt"
|
||||||
|
|
||||||
#. Translators: help text for qcluster management command
|
#. Translators: help text for qcluster management command
|
||||||
#: management/commands/qcluster.py:9
|
#: management/commands/qcluster.py:11
|
||||||
msgid "Starts a Django Q Cluster."
|
msgid "Starts a Django Q Cluster."
|
||||||
msgstr "Startet ein Django-Q-Cluster."
|
msgstr "Startet ein Django-Q-Cluster."
|
||||||
|
|
||||||
@@ -236,253 +178,479 @@ msgstr "Überwacht die Speichernutzung von Q Cluster"
|
|||||||
msgid "Monitors Q Cluster activity"
|
msgid "Monitors Q Cluster activity"
|
||||||
msgstr "Q-Cluster aktiv überwachen"
|
msgstr "Q-Cluster aktiv überwachen"
|
||||||
|
|
||||||
#: models.py:125
|
#: models.py:30 models.py:469
|
||||||
msgid "Successful task"
|
msgid "Task id"
|
||||||
msgstr "Erfolgreiche Aufgabe"
|
msgstr ""
|
||||||
|
|
||||||
#: models.py:126
|
#: models.py:31
|
||||||
msgid "Successful tasks"
|
msgid "32-character task identifier."
|
||||||
msgstr "Erfolgreiche Aufgaben"
|
msgstr ""
|
||||||
|
|
||||||
#: models.py:141
|
#: models.py:36 models.py:235 models.py:470
|
||||||
msgid "Failed task"
|
msgid "Name"
|
||||||
msgstr "Fehlgeschlagene Aufgabe"
|
msgstr ""
|
||||||
|
|
||||||
#: models.py:142
|
#: models.py:37
|
||||||
msgid "Failed tasks"
|
msgid "Optional human-readable name for lookup and display."
|
||||||
msgstr "Fehlgeschlagene Aufgaben"
|
msgstr ""
|
||||||
|
|
||||||
#: models.py:150 models.py:234
|
#: models.py:41 models.py:240 models.py:468
|
||||||
msgid "Please install croniter to enable cron expressions"
|
msgid "Function"
|
||||||
msgstr "Bitte installieren Sie croniter, um Cron-Ausdrücke zu aktivieren"
|
msgstr ""
|
||||||
|
|
||||||
#: models.py:170
|
#: models.py:42
|
||||||
msgid "e.g. 1, 2, 'John'"
|
msgid "Dotted import path to the callable, e.g. myapp.tasks.job."
|
||||||
msgstr "zum Beispiel 1, 2, 'John'"
|
msgstr ""
|
||||||
|
|
||||||
#: models.py:172
|
#: models.py:47 models.py:247
|
||||||
msgid "e.g. x=1, y=2, name='John'"
|
msgid "Hook"
|
||||||
msgstr "zum Beispiel x=1, y=2, name='John'"
|
msgstr ""
|
||||||
|
|
||||||
#: models.py:186
|
#: models.py:48
|
||||||
msgid "Once"
|
msgid "Optional dotted path to a callback that receives the task result."
|
||||||
msgstr "Einmal"
|
msgstr ""
|
||||||
|
|
||||||
#: models.py:187
|
#: models.py:53 models.py:253 models.py:472
|
||||||
msgid "Minutes"
|
msgid "Arguments"
|
||||||
msgstr "Minuten"
|
msgstr ""
|
||||||
|
|
||||||
#: models.py:188
|
#: models.py:54
|
||||||
msgid "Hourly"
|
msgid "Pickled positional arguments (tuple)."
|
||||||
msgstr "Stündlich"
|
msgstr ""
|
||||||
|
|
||||||
#: models.py:189
|
#: models.py:59 models.py:259 models.py:473
|
||||||
msgid "Daily"
|
msgid "Keyword arguments"
|
||||||
msgstr "Täglich"
|
msgstr ""
|
||||||
|
|
||||||
#: models.py:190
|
#: models.py:60
|
||||||
msgid "Weekly"
|
msgid "Pickled keyword arguments (dict)."
|
||||||
msgstr "Wöchentlich"
|
msgstr ""
|
||||||
|
|
||||||
#: models.py:191
|
#: models.py:65
|
||||||
msgid "Biweekly"
|
msgid "Result"
|
||||||
msgstr "Zweiwöchentlich"
|
msgstr ""
|
||||||
|
|
||||||
#: models.py:192
|
#: models.py:66
|
||||||
msgid "Monthly"
|
msgid "Pickled return value or error payload."
|
||||||
msgstr "Monatlich"
|
msgstr ""
|
||||||
|
|
||||||
#: models.py:193
|
#: models.py:72 models.py:471
|
||||||
msgid "Bimonthly"
|
msgid "Group"
|
||||||
msgstr "Zweimonatlich"
|
msgstr ""
|
||||||
|
|
||||||
#: models.py:194
|
#: models.py:73
|
||||||
msgid "Quarterly"
|
msgid "Optional group id to aggregate related tasks."
|
||||||
msgstr "Vierteljährlich"
|
msgstr ""
|
||||||
|
|
||||||
#: models.py:195
|
#: models.py:80 models.py:328
|
||||||
msgid "Yearly"
|
#, fuzzy
|
||||||
msgstr "Jährlich"
|
#| msgid "Clusters"
|
||||||
|
msgid "Cluster"
|
||||||
|
msgstr "Cluster"
|
||||||
|
|
||||||
#: models.py:196
|
#: models.py:81
|
||||||
msgid "Cron"
|
msgid "Name of the cluster that executed this task."
|
||||||
msgstr "Cron"
|
msgstr ""
|
||||||
|
|
||||||
#: models.py:199
|
#: models.py:85
|
||||||
msgid "Schedule Type"
|
msgid "Started at"
|
||||||
msgstr "Zeitplan-Typ"
|
msgstr ""
|
||||||
|
|
||||||
#: models.py:202
|
#: models.py:86
|
||||||
msgid "Number of minutes for the Minutes type"
|
msgid "When the worker started executing the task."
|
||||||
msgstr "Anzahl Minuten für den Typ 'Minuten'"
|
msgstr ""
|
||||||
|
|
||||||
#: models.py:205
|
#: models.py:90
|
||||||
msgid "Repeats"
|
#, fuzzy
|
||||||
msgstr "Wiederholungen"
|
#| msgid "Stopped"
|
||||||
|
msgid "Stopped at"
|
||||||
|
msgstr "Gestoppt"
|
||||||
|
|
||||||
#: models.py:205
|
#: models.py:91
|
||||||
msgid "n = n times, -1 = forever"
|
msgid "When the worker finished (success or failure)."
|
||||||
msgstr "n = n mal, -1 = für immer"
|
msgstr ""
|
||||||
|
|
||||||
#: models.py:208
|
#: models.py:96 monitor_terminal.py:180
|
||||||
msgid "Next Run"
|
|
||||||
msgstr "Nächste Ausführung"
|
|
||||||
|
|
||||||
#: models.py:215
|
|
||||||
msgid "Cron expression"
|
|
||||||
msgstr "Cron-Ausdruck"
|
|
||||||
|
|
||||||
#: models.py:224
|
|
||||||
msgid "Name of kwarg to pass intended schedule date"
|
|
||||||
msgstr "Name des zu passierenden Kwargs vorgesehenes Datum"
|
|
||||||
|
|
||||||
#: models.py:299
|
|
||||||
msgid "Scheduled task"
|
|
||||||
msgstr "Geplante Aufgabe"
|
|
||||||
|
|
||||||
#: models.py:300
|
|
||||||
msgid "Scheduled tasks"
|
|
||||||
msgstr "Geplante Aufgaben"
|
|
||||||
|
|
||||||
#: models.py:326
|
|
||||||
msgid "Queued task"
|
|
||||||
msgstr "Eingereihte Aufgabe"
|
|
||||||
|
|
||||||
#: models.py:327
|
|
||||||
msgid "Queued tasks"
|
|
||||||
msgstr "Eingereihte Aufgaben"
|
|
||||||
|
|
||||||
#: monitor.py:64 monitor.py:348
|
|
||||||
msgid "Host"
|
|
||||||
msgstr "Host"
|
|
||||||
|
|
||||||
#: monitor.py:68 monitor.py:352 monitor.py:459
|
|
||||||
msgid "Id"
|
|
||||||
msgstr "Id"
|
|
||||||
|
|
||||||
#: monitor.py:72
|
|
||||||
msgid "State"
|
|
||||||
msgstr "Status"
|
|
||||||
|
|
||||||
#: monitor.py:76
|
|
||||||
msgid "Pool"
|
|
||||||
msgstr "Pool"
|
|
||||||
|
|
||||||
#: monitor.py:80
|
|
||||||
msgid "TQ"
|
|
||||||
msgstr "TQ"
|
|
||||||
|
|
||||||
#: monitor.py:84
|
|
||||||
msgid "RQ"
|
|
||||||
msgstr "RQ"
|
|
||||||
|
|
||||||
#: monitor.py:88
|
|
||||||
msgid "RC"
|
|
||||||
msgstr "RC"
|
|
||||||
|
|
||||||
#: monitor.py:92
|
|
||||||
msgid "Up"
|
|
||||||
msgstr "Up"
|
|
||||||
|
|
||||||
#: monitor.py:172 monitor.py:286
|
|
||||||
msgid "Queued"
|
|
||||||
msgstr "Eingereiht"
|
|
||||||
|
|
||||||
#: monitor.py:180
|
|
||||||
msgid "Success"
|
msgid "Success"
|
||||||
msgstr "Erfolg"
|
msgstr "Erfolg"
|
||||||
|
|
||||||
#: monitor.py:190 monitor.py:294
|
#: models.py:97
|
||||||
|
msgid "False if the task raised an exception or timed out."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: models.py:101
|
||||||
|
msgid "Attempt count"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: models.py:102
|
||||||
|
msgid "How many times execution was attempted."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: models.py:172
|
||||||
|
msgid "Task"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: models.py:173
|
||||||
|
msgid "Tasks"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: models.py:194
|
||||||
|
msgid "Successful task"
|
||||||
|
msgstr "Erfolgreiche Aufgabe"
|
||||||
|
|
||||||
|
#: models.py:195
|
||||||
|
msgid "Successful tasks"
|
||||||
|
msgstr "Erfolgreiche Aufgaben"
|
||||||
|
|
||||||
|
#: models.py:210
|
||||||
|
msgid "Failed task"
|
||||||
|
msgstr "Fehlgeschlagene Aufgabe"
|
||||||
|
|
||||||
|
#: models.py:211
|
||||||
|
msgid "Failed tasks"
|
||||||
|
msgstr "Fehlgeschlagene Aufgaben"
|
||||||
|
|
||||||
|
#: models.py:219 models.py:347
|
||||||
|
msgid "Please install croniter to enable cron expressions"
|
||||||
|
msgstr "Bitte installieren Sie croniter, um Cron-Ausdrücke zu aktivieren"
|
||||||
|
|
||||||
|
#: models.py:236
|
||||||
|
msgid "Optional label to identify this schedule in the admin."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: models.py:241
|
||||||
|
msgid "e.g. module.tasks.function"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: models.py:248
|
||||||
|
msgid "e.g. module.tasks.result_function"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: models.py:254
|
||||||
|
msgid "e.g. 1, 2, 'John'"
|
||||||
|
msgstr "zum Beispiel 1, 2, 'John'"
|
||||||
|
|
||||||
|
#: models.py:260
|
||||||
|
msgid "e.g. x=1, y=2, name='John'"
|
||||||
|
msgstr "zum Beispiel x=1, y=2, name='John'"
|
||||||
|
|
||||||
|
#: models.py:274
|
||||||
|
msgid "Once"
|
||||||
|
msgstr "Einmal"
|
||||||
|
|
||||||
|
#: models.py:275 models.py:296
|
||||||
|
msgid "Minutes"
|
||||||
|
msgstr "Minuten"
|
||||||
|
|
||||||
|
#: models.py:276
|
||||||
|
msgid "Hourly"
|
||||||
|
msgstr "Stündlich"
|
||||||
|
|
||||||
|
#: models.py:277
|
||||||
|
msgid "Daily"
|
||||||
|
msgstr "Täglich"
|
||||||
|
|
||||||
|
#: models.py:278
|
||||||
|
msgid "Weekly"
|
||||||
|
msgstr "Wöchentlich"
|
||||||
|
|
||||||
|
#: models.py:279
|
||||||
|
msgid "Biweekly"
|
||||||
|
msgstr "Zweiwöchentlich"
|
||||||
|
|
||||||
|
#: models.py:280
|
||||||
|
msgid "Monthly"
|
||||||
|
msgstr "Monatlich"
|
||||||
|
|
||||||
|
#: models.py:281
|
||||||
|
msgid "Bimonthly"
|
||||||
|
msgstr "Zweimonatlich"
|
||||||
|
|
||||||
|
#: models.py:282
|
||||||
|
msgid "Quarterly"
|
||||||
|
msgstr "Vierteljährlich"
|
||||||
|
|
||||||
|
#: models.py:283
|
||||||
|
msgid "Yearly"
|
||||||
|
msgstr "Jährlich"
|
||||||
|
|
||||||
|
#: models.py:284 models.py:313
|
||||||
|
msgid "Cron"
|
||||||
|
msgstr "Cron"
|
||||||
|
|
||||||
|
#: models.py:290
|
||||||
|
msgid "Schedule Type"
|
||||||
|
msgstr "Zeitplan-Typ"
|
||||||
|
|
||||||
|
#: models.py:291
|
||||||
|
msgid "How often this task should be enqueued."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: models.py:297
|
||||||
|
msgid "Number of minutes for the Minutes type"
|
||||||
|
msgstr "Anzahl Minuten für den Typ 'Minuten'"
|
||||||
|
|
||||||
|
#: models.py:300
|
||||||
|
msgid "Repeats"
|
||||||
|
msgstr "Wiederholungen"
|
||||||
|
|
||||||
|
#: models.py:300
|
||||||
|
msgid "n = n times, -1 = forever"
|
||||||
|
msgstr "n = n mal, -1 = für immer"
|
||||||
|
|
||||||
|
#: models.py:303
|
||||||
|
msgid "Next Run"
|
||||||
|
msgstr "Nächste Ausführung"
|
||||||
|
|
||||||
|
#: models.py:304
|
||||||
|
msgid "When this schedule runs next (stored in UTC)."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: models.py:314
|
||||||
|
msgid "Cron expression"
|
||||||
|
msgstr "Cron-Ausdruck"
|
||||||
|
|
||||||
|
#: models.py:320
|
||||||
|
msgid "Last task id"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: models.py:321
|
||||||
|
msgid "Id of the last task spawned from this schedule (read-only)."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: models.py:329 models.py:427
|
||||||
|
msgid "Name of the target cluster"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: models.py:336
|
||||||
|
msgid "Intended date kwarg"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: models.py:337
|
||||||
|
msgid "Name of kwarg to pass intended schedule date"
|
||||||
|
msgstr "Name des zu passierenden Kwargs vorgesehenes Datum"
|
||||||
|
|
||||||
|
#: models.py:418
|
||||||
|
msgid "Scheduled task"
|
||||||
|
msgstr "Geplante Aufgabe"
|
||||||
|
|
||||||
|
#: models.py:419
|
||||||
|
msgid "Scheduled tasks"
|
||||||
|
msgstr "Geplante Aufgaben"
|
||||||
|
|
||||||
|
#: models.py:426
|
||||||
|
#, fuzzy
|
||||||
|
#| msgid "Clusters"
|
||||||
|
msgid "Cluster key"
|
||||||
|
msgstr "Cluster"
|
||||||
|
|
||||||
|
#: models.py:430
|
||||||
|
msgid "Payload"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: models.py:431
|
||||||
|
msgid "Signed serialized task package (do not edit manually)."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: models.py:435
|
||||||
|
msgid "Lock until"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: models.py:436
|
||||||
|
msgid "Prevent any cluster from pulling until"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: models.py:474
|
||||||
|
#, fuzzy
|
||||||
|
#| msgid "Queued task"
|
||||||
|
msgid "Queue options"
|
||||||
|
msgstr "Eingereihte Aufgabe"
|
||||||
|
|
||||||
|
#: models.py:478
|
||||||
|
msgid "Queued task"
|
||||||
|
msgstr "Eingereihte Aufgabe"
|
||||||
|
|
||||||
|
#: models.py:479
|
||||||
|
msgid "Queued tasks"
|
||||||
|
msgstr "Eingereihte Aufgaben"
|
||||||
|
|
||||||
|
#: monitor.py:41
|
||||||
|
#, python-format
|
||||||
|
msgid "%(name)s monitoring at %(id)s"
|
||||||
|
msgstr "%(name)s beobachtet auf %(id)s"
|
||||||
|
|
||||||
|
#: monitor.py:61
|
||||||
|
#, python-format
|
||||||
|
msgid "Processed '%(info_name)s' (%(task_name)s)"
|
||||||
|
msgstr "[%(task_name)s] - '%(info_name)s' wurde verarbeitet"
|
||||||
|
|
||||||
|
#: monitor.py:67
|
||||||
|
#, python-format
|
||||||
|
msgid "Failed '%(info_name)s' (%(task_name)s) - %(task_result)s"
|
||||||
|
msgstr "'%(info_name)s' (%(task_name)s) ist fehlgeschlagen - %(task_result)s"
|
||||||
|
|
||||||
|
#: monitor.py:74
|
||||||
|
#, python-format
|
||||||
|
msgid "%(name)s stopped monitoring results"
|
||||||
|
msgstr "%(name)s überwacht keine Ergebnisse mehr"
|
||||||
|
|
||||||
|
#: monitor_terminal.py:64 monitor_terminal.py:348
|
||||||
|
msgid "Host"
|
||||||
|
msgstr "Host"
|
||||||
|
|
||||||
|
#: monitor_terminal.py:68 monitor_terminal.py:352 monitor_terminal.py:457
|
||||||
|
msgid "Id"
|
||||||
|
msgstr "Id"
|
||||||
|
|
||||||
|
#: monitor_terminal.py:72
|
||||||
|
msgid "State"
|
||||||
|
msgstr "Status"
|
||||||
|
|
||||||
|
#: monitor_terminal.py:76
|
||||||
|
msgid "Pool"
|
||||||
|
msgstr "Pool"
|
||||||
|
|
||||||
|
#: monitor_terminal.py:80
|
||||||
|
msgid "TQ"
|
||||||
|
msgstr "TQ"
|
||||||
|
|
||||||
|
#: monitor_terminal.py:84
|
||||||
|
msgid "RQ"
|
||||||
|
msgstr "RQ"
|
||||||
|
|
||||||
|
#: monitor_terminal.py:88
|
||||||
|
msgid "RC"
|
||||||
|
msgstr "RC"
|
||||||
|
|
||||||
|
#: monitor_terminal.py:92
|
||||||
|
msgid "Up"
|
||||||
|
msgstr "Up"
|
||||||
|
|
||||||
|
#: monitor_terminal.py:172 monitor_terminal.py:286
|
||||||
|
msgid "Queued"
|
||||||
|
msgstr "Eingereiht"
|
||||||
|
|
||||||
|
#: monitor_terminal.py:190 monitor_terminal.py:294
|
||||||
msgid "Failures"
|
msgid "Failures"
|
||||||
msgstr "Fehlschläge"
|
msgstr "Fehlschläge"
|
||||||
|
|
||||||
#: monitor.py:201 monitor.py:498
|
#: monitor_terminal.py:201 monitor_terminal.py:496
|
||||||
msgid "[Press q to quit]"
|
msgid "[Press q to quit]"
|
||||||
msgstr "[Drücken Sie q zum Beenden]"
|
msgstr "[Drücken Sie q zum Beenden]"
|
||||||
|
|
||||||
#: monitor.py:227
|
#: monitor_terminal.py:227
|
||||||
msgid "day"
|
msgid "day"
|
||||||
msgstr "Tag"
|
msgstr "Tag"
|
||||||
|
|
||||||
#: monitor.py:248
|
#: monitor_terminal.py:248
|
||||||
msgid "second"
|
msgid "second"
|
||||||
msgstr "Sekunde"
|
msgstr "Sekunde"
|
||||||
|
|
||||||
#: monitor.py:251
|
#: monitor_terminal.py:251
|
||||||
msgid "minute"
|
msgid "minute"
|
||||||
msgstr "Minute"
|
msgstr "Minute"
|
||||||
|
|
||||||
#: monitor.py:254
|
#: monitor_terminal.py:254
|
||||||
msgid "hour"
|
msgid "hour"
|
||||||
msgstr "Stunde"
|
msgstr "Stunde"
|
||||||
|
|
||||||
#: monitor.py:263
|
#: monitor_terminal.py:263
|
||||||
#, python-format
|
#, python-format
|
||||||
msgid "-- %(prefix)s %(version)s on %(info)s --"
|
msgid "-- %(prefix)s %(version)s on %(info)s --"
|
||||||
msgstr "-- %(prefix)s %(version)s auf %(info)s --"
|
msgstr "-- %(prefix)s %(version)s auf %(info)s --"
|
||||||
|
|
||||||
#: monitor.py:273
|
#: monitor_terminal.py:273
|
||||||
msgid "Clusters"
|
msgid "Clusters"
|
||||||
msgstr "Cluster"
|
msgstr "Cluster"
|
||||||
|
|
||||||
#: monitor.py:277
|
#: monitor_terminal.py:277
|
||||||
msgid "Workers"
|
msgid "Workers"
|
||||||
msgstr "Arbeiter"
|
msgstr "Arbeiter"
|
||||||
|
|
||||||
#: monitor.py:281
|
#: monitor_terminal.py:281
|
||||||
msgid "Restarts"
|
msgid "Restarts"
|
||||||
msgstr "Neustarts"
|
msgstr "Neustarts"
|
||||||
|
|
||||||
#: monitor.py:290
|
#: monitor_terminal.py:290
|
||||||
msgid "Successes"
|
msgid "Successes"
|
||||||
msgstr "Erfolge"
|
msgstr "Erfolge"
|
||||||
|
|
||||||
#: monitor.py:299
|
#: monitor_terminal.py:299
|
||||||
msgid "Schedules"
|
msgid "Schedules"
|
||||||
msgstr "Zeitpläne"
|
msgstr "Zeitpläne"
|
||||||
|
|
||||||
#: monitor.py:303
|
#: monitor_terminal.py:303
|
||||||
#, python-format
|
#, python-format
|
||||||
msgid "Tasks/%(per)s"
|
msgid "Tasks/%(per)s"
|
||||||
msgstr "Aufgaben/%(per)s"
|
msgstr "Aufgaben/%(per)s"
|
||||||
|
|
||||||
#: monitor.py:307
|
#: monitor_terminal.py:307
|
||||||
msgid "Avg time"
|
msgid "Avg time"
|
||||||
msgstr "Durchschnittl. Zeit"
|
msgstr "Durchschnittl. Zeit"
|
||||||
|
|
||||||
#: monitor.py:357
|
#: monitor_terminal.py:357
|
||||||
msgid "Available (%)"
|
msgid "Available (%)"
|
||||||
msgstr "Verfügbar (%)"
|
msgstr "Verfügbar (%)"
|
||||||
|
|
||||||
#: monitor.py:363
|
#: monitor_terminal.py:363
|
||||||
msgid "Available (MB)"
|
msgid "Available (MB)"
|
||||||
msgstr "Verfügbar (MB)"
|
msgstr "Verfügbar (MB)"
|
||||||
|
|
||||||
#: monitor.py:368
|
#: monitor_terminal.py:368
|
||||||
msgid "Total (MB)"
|
msgid "Total (MB)"
|
||||||
msgstr "Insgesamt (MB)"
|
msgstr "Insgesamt (MB)"
|
||||||
|
|
||||||
#: monitor.py:373
|
#: monitor_terminal.py:373
|
||||||
msgid "Sentinel (MB)"
|
msgid "Sentinel (MB)"
|
||||||
msgstr "Sentinel (MB)"
|
msgstr "Sentinel (MB)"
|
||||||
|
|
||||||
#: monitor.py:379
|
#: monitor_terminal.py:379
|
||||||
msgid "Monitor (MB)"
|
msgid "Monitor (MB)"
|
||||||
msgstr "Monitor (MB)"
|
msgstr "Monitor (MB)"
|
||||||
|
|
||||||
#: monitor.py:385
|
#: monitor_terminal.py:385
|
||||||
msgid "Workers (MB)"
|
msgid "Workers (MB)"
|
||||||
msgstr "Arbeiter (MB)"
|
msgstr "Arbeiter (MB)"
|
||||||
|
|
||||||
#: monitor.py:487
|
#: monitor_terminal.py:485
|
||||||
#, python-format
|
#, python-format
|
||||||
msgid "Available lowest (): %(memory_percent)s ((at)s)"
|
msgid "Available lowest (): %(memory_percent)s ((at)s)"
|
||||||
msgstr "Niedrigste verfügbar (): %(memory_percent)s ((at)s)"
|
msgstr "Niedrigste verfügbar (): %(memory_percent)s ((at)s)"
|
||||||
|
|
||||||
#: monitor.py:509
|
#: monitor_terminal.py:507
|
||||||
msgid "No clusters appear to be running."
|
msgid "No clusters appear to be running."
|
||||||
msgstr "Es scheinen keine Cluster zu laufen."
|
msgstr "Es scheinen keine Cluster zu laufen."
|
||||||
|
|
||||||
|
#: pusher.py:40
|
||||||
|
#, python-format
|
||||||
|
#| msgid "%(process_name)s pushing tasks at %(id)s"
|
||||||
|
msgid "%(name)s pushing tasks at %(id)s"
|
||||||
|
msgstr "%(name)s veröffentlicht Aufagaben auf %(id)s"
|
||||||
|
|
||||||
|
#: pusher.py:67
|
||||||
|
#, python-format
|
||||||
|
msgid "queueing from %(list_key)s"
|
||||||
|
msgstr "Einreihen von %(list_key)s"
|
||||||
|
|
||||||
|
#: pusher.py:71
|
||||||
|
#, python-format
|
||||||
|
msgid "%(name)s stopped pushing tasks"
|
||||||
|
msgstr "%(name)s veröffentlicht keine Aufgaben mehr"
|
||||||
|
|
||||||
|
#: scheduler.py:110
|
||||||
|
#, python-format
|
||||||
|
msgid "%(process_name)s failed to create a task from schedule [%(schedule)s]"
|
||||||
|
msgstr ""
|
||||||
|
"%(process_name)s konnte keine Aufgabe von Zeitplan [%(schedule)s] erstellen"
|
||||||
|
|
||||||
|
#: scheduler.py:121
|
||||||
|
#, fuzzy, python-format
|
||||||
|
#| msgid "%(process_name)s created a task from schedule [%(schedule)s]"
|
||||||
|
msgid ""
|
||||||
|
"%(process_name)s created task %(task_name)s from schedule [%(schedule)s]"
|
||||||
|
msgstr ""
|
||||||
|
"%(process_name)s hat eine Aufgabe des Zeitplans [%(schedule)s] erstellt"
|
||||||
|
|
||||||
#: signals.py:22
|
#: signals.py:22
|
||||||
#, python-format
|
#, python-format
|
||||||
msgid "malformed return hook '%(hook)s' for [%(name)s]"
|
msgid "malformed return hook '%(hook)s' for [%(name)s]"
|
||||||
@@ -493,6 +661,26 @@ msgstr "Ungültiger Return-Hook '%(hook)s' für [%(name)s]"
|
|||||||
msgid "return hook %(hook)s failed on [%(name)s] because %(error)s"
|
msgid "return hook %(hook)s failed on [%(name)s] because %(error)s"
|
||||||
msgstr "Return-Hook %(hook)s für [%(name)s] ist gescheitert: %(error)s"
|
msgstr "Return-Hook %(hook)s für [%(name)s] ist gescheitert: %(error)s"
|
||||||
|
|
||||||
|
#: timeout.py:30 timeout.py:43
|
||||||
|
msgid "SIGALARM is not available on your platform"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: worker.py:49
|
||||||
|
#, python-format
|
||||||
|
msgid "%(proc_name)s ready for work at %(id)s"
|
||||||
|
msgstr "%(proc_name)s ist bereit für Arbeit auf %(id)s"
|
||||||
|
|
||||||
|
#: worker.py:69
|
||||||
|
#, fuzzy, python-format
|
||||||
|
#| msgid "%(proc_name)s processing '%(func_name)s' (%(task_name)s)"
|
||||||
|
msgid "%(proc_name)s processing %(task_name)s '%(func_name)s'"
|
||||||
|
msgstr "%(proc_name)s verarbeitet '%(func_name)s' (%(task_name)s)"
|
||||||
|
|
||||||
|
#: worker.py:135
|
||||||
|
#, python-format
|
||||||
|
msgid "%(proc_name)s stopped doing work"
|
||||||
|
msgstr "%(proc_name)s hat die Arbeit beendet"
|
||||||
|
|
||||||
#, python-format
|
#, python-format
|
||||||
#~ msgid ""
|
#~ msgid ""
|
||||||
#~ "Could not process '%(func_name)s'. Check the location of the function and "
|
#~ "Could not process '%(func_name)s'. Check the location of the function and "
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ msgid ""
|
|||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: \n"
|
"Project-Id-Version: \n"
|
||||||
"Report-Msgid-Bugs-To: \n"
|
"Report-Msgid-Bugs-To: \n"
|
||||||
"POT-Creation-Date: 2023-01-26 01:38+0000\n"
|
"POT-Creation-Date: 2026-04-17 21:10+0000\n"
|
||||||
"PO-Revision-Date: 2018-08-05 18:28+0200\n"
|
"PO-Revision-Date: 2018-08-05 18:28+0200\n"
|
||||||
"Last-Translator: Thierry BOULOGNE <contact@tng-concepts.com>\n"
|
"Last-Translator: Thierry BOULOGNE <contact@tng-concepts.com>\n"
|
||||||
"Language-Team: \n"
|
"Language-Team: \n"
|
||||||
@@ -17,36 +17,44 @@ msgstr ""
|
|||||||
"X-Generator: Poedit 2.1.1\n"
|
"X-Generator: Poedit 2.1.1\n"
|
||||||
"Plural-Forms: nplurals=2; plural=(n > 1);\n"
|
"Plural-Forms: nplurals=2; plural=(n > 1);\n"
|
||||||
|
|
||||||
#: admin.py:43
|
#: admin.py:30
|
||||||
msgid "Resubmit selected tasks to queue"
|
msgid "Resubmit selected tasks to queue"
|
||||||
msgstr "Resoumettre les tâches sélectionnées à la file d'attente"
|
msgstr "Resoumettre les tâches sélectionnées à la file d'attente"
|
||||||
|
|
||||||
#: admin.py:107 models.py:293
|
#: admin.py:64
|
||||||
|
msgid "Time Taken"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: admin.py:95
|
||||||
|
msgid "Short result"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: admin.py:142 models.py:412
|
||||||
#, fuzzy
|
#, fuzzy
|
||||||
#| msgid "Success"
|
#| msgid "Success"
|
||||||
msgid "success"
|
msgid "success"
|
||||||
msgstr "succès"
|
msgstr "succès"
|
||||||
|
|
||||||
#: admin.py:119 models.py:295
|
#: admin.py:154 models.py:414
|
||||||
msgid "last_run"
|
msgid "last_run"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: cluster.py:79
|
#: cluster.py:75
|
||||||
#, python-format
|
#, python-format
|
||||||
msgid "Q Cluster %(name)s starting."
|
msgid "Q Cluster %(name)s starting."
|
||||||
msgstr "Démarrage de Q Cluster-%(name)s."
|
msgstr "Démarrage de Q Cluster-%(name)s."
|
||||||
|
|
||||||
#: cluster.py:87
|
#: cluster.py:83
|
||||||
#, python-format
|
#, python-format
|
||||||
msgid "Q Cluster %(name)s stopping."
|
msgid "Q Cluster %(name)s stopping."
|
||||||
msgstr "Arrêt de Q Cluster-%(name)s."
|
msgstr "Arrêt de Q Cluster-%(name)s."
|
||||||
|
|
||||||
#: cluster.py:90
|
#: cluster.py:86
|
||||||
#, python-format
|
#, python-format
|
||||||
msgid "Q Cluster %(name)s has stopped."
|
msgid "Q Cluster %(name)s has stopped."
|
||||||
msgstr "Q Cluster-%(name)s a été arrêté."
|
msgstr "Q Cluster-%(name)s a été arrêté."
|
||||||
|
|
||||||
#: cluster.py:97
|
#: cluster.py:93
|
||||||
#, python-format
|
#, python-format
|
||||||
msgid "%(name)s got signal %(signal)s"
|
msgid "%(name)s got signal %(signal)s"
|
||||||
msgstr "%(name)s à reçu le signal %(signal)s"
|
msgstr "%(name)s à reçu le signal %(signal)s"
|
||||||
@@ -61,7 +69,7 @@ msgstr "surveillant %(name)s réincarné après un arrêt intempestif"
|
|||||||
msgid "reincarnated pusher %(name)s after sudden death"
|
msgid "reincarnated pusher %(name)s after sudden death"
|
||||||
msgstr "répartiteur %(name)s réincarné après un arrêt intempestif"
|
msgstr "répartiteur %(name)s réincarné après un arrêt intempestif"
|
||||||
|
|
||||||
#: cluster.py:250
|
#: cluster.py:262
|
||||||
#, python-format
|
#, python-format
|
||||||
msgid ""
|
msgid ""
|
||||||
"reincarnated worker %(name)s after timeout while processing task "
|
"reincarnated worker %(name)s after timeout while processing task "
|
||||||
@@ -70,122 +78,57 @@ msgstr ""
|
|||||||
"processus %(name)s réincarné, délai de traitement dépassé pour la tâche "
|
"processus %(name)s réincarné, délai de traitement dépassé pour la tâche "
|
||||||
"%(task_name)s"
|
"%(task_name)s"
|
||||||
|
|
||||||
#: cluster.py:255
|
#: cluster.py:265
|
||||||
#, python-format
|
#, python-format
|
||||||
msgid "reincarnated worker %(name)s after timeout"
|
msgid "reincarnated worker %(name)s after timeout"
|
||||||
msgstr "processus %(name)s réincarné, délai de traitement dépassé"
|
msgstr "processus %(name)s réincarné, délai de traitement dépassé"
|
||||||
|
|
||||||
#: cluster.py:260
|
#: cluster.py:270
|
||||||
#, python-format
|
#, python-format
|
||||||
msgid "recycled worker %(name)s"
|
msgid "recycled worker %(name)s"
|
||||||
msgstr "processus recyclé %(name)s"
|
msgstr "processus recyclé %(name)s"
|
||||||
|
|
||||||
#: cluster.py:263
|
#: cluster.py:273
|
||||||
#, python-format
|
#, python-format
|
||||||
msgid "reincarnated worker %(name)s after death"
|
msgid "reincarnated worker %(name)s after death"
|
||||||
msgstr "processus réintégré %(name)s après arrêt"
|
msgstr "processus réintégré %(name)s après arrêt"
|
||||||
|
|
||||||
#: cluster.py:287
|
#: cluster.py:297
|
||||||
#, python-format
|
#, python-format
|
||||||
msgid "%(name)s guarding cluster %(cluster_name)s"
|
msgid "%(name)s guarding cluster %(cluster_name)s"
|
||||||
msgstr "%(name)s surveillance du cluster à %(cluster_name)s"
|
msgstr "%(name)s surveillance du cluster à %(cluster_name)s"
|
||||||
|
|
||||||
#: cluster.py:296
|
#: cluster.py:307
|
||||||
#, python-format
|
#, python-format
|
||||||
msgid "Q Cluster %(cluster_name)s running."
|
msgid "Q Cluster %(cluster_name)s running."
|
||||||
msgstr "Démarrage de Q Cluster-%(cluster_name)s."
|
msgstr "Démarrage de Q Cluster-%(cluster_name)s."
|
||||||
|
|
||||||
#: cluster.py:332
|
#: cluster.py:346
|
||||||
#, python-format
|
#, python-format
|
||||||
msgid "%(name)s stopping cluster processes"
|
msgid "%(name)s stopping cluster processes"
|
||||||
msgstr "%(name)s arrêt des processus du cluster"
|
msgstr "%(name)s arrêt des processus du cluster"
|
||||||
|
|
||||||
#: cluster.py:357
|
#: cluster.py:371
|
||||||
#, python-format
|
#, python-format
|
||||||
msgid "%(name)s waiting for the monitor."
|
msgid "%(name)s waiting for the monitor."
|
||||||
msgstr "%(name)s en attente du surveillant."
|
msgstr "%(name)s en attente du surveillant."
|
||||||
|
|
||||||
#: cluster.py:383
|
#: cluster.py:394
|
||||||
#, python-format
|
|
||||||
msgid "%(name)s pushing tasks at %(id)s"
|
|
||||||
msgstr "%(name)s répartit les tâches %(id)s"
|
|
||||||
|
|
||||||
#: cluster.py:407
|
|
||||||
#, python-format
|
|
||||||
msgid "queueing from %(list_key)s"
|
|
||||||
msgstr "mise en file d'attente de %(list_key)s"
|
|
||||||
|
|
||||||
#: cluster.py:411
|
|
||||||
#, python-format
|
|
||||||
msgid "%(name)s stopped pushing tasks"
|
|
||||||
msgstr "%(name)s a cessé de répartir les tâches"
|
|
||||||
|
|
||||||
#: cluster.py:426
|
|
||||||
#, python-format
|
|
||||||
msgid "%(name)s monitoring at %(id)s"
|
|
||||||
msgstr "%(name)s surveille les résultats %(id)s"
|
|
||||||
|
|
||||||
#: cluster.py:445
|
|
||||||
#, python-format
|
|
||||||
msgid "Processed '%(info_name)s' (%(task_name)s)"
|
|
||||||
msgstr "traité '%(info_name)s' (%(task_name)s)"
|
|
||||||
|
|
||||||
#: cluster.py:451
|
|
||||||
#, python-format
|
|
||||||
msgid "Failed '%(info_name)s' (%(task_name)s) - %(task_result)s"
|
|
||||||
msgstr "Manqué '%(info_name)s' (%(task_name)s) - %(task_result)s"
|
|
||||||
|
|
||||||
#: cluster.py:458
|
|
||||||
#, python-format
|
|
||||||
msgid "%(name)s stopped monitoring results"
|
|
||||||
msgstr "%(name)s a cessé de de surveiller les résultats"
|
|
||||||
|
|
||||||
#: cluster.py:474
|
|
||||||
#, python-format
|
|
||||||
msgid "%(proc_name)s ready for work at %(id)s"
|
|
||||||
msgstr "%(proc_name)s prêt pour le travail à %(id)s"
|
|
||||||
|
|
||||||
#: cluster.py:494
|
|
||||||
#, fuzzy, python-format
|
|
||||||
msgid "%(proc_name)s processing %(task_name)s '%(func_name)s'"
|
|
||||||
msgstr "%(proc_name)s exécute %(task_name)s '%(func_name)s'"
|
|
||||||
|
|
||||||
#: cluster.py:546
|
|
||||||
#, python-format
|
|
||||||
msgid "%(proc_name)s stopped doing work"
|
|
||||||
msgstr "%(proc_name)s a cessé de travailler"
|
|
||||||
|
|
||||||
#: cluster.py:751
|
|
||||||
#, python-format
|
|
||||||
msgid "%(process_name)s failed to create a task from schedule [%(schedule)s]"
|
|
||||||
msgstr ""
|
|
||||||
"%(process_name)s Echec de la création d'une tâche à partir de Schedule "
|
|
||||||
"[%(schedule)s]"
|
|
||||||
|
|
||||||
#: cluster.py:762
|
|
||||||
#, python-format
|
|
||||||
msgid ""
|
|
||||||
"%(process_name)s created task %(task_name)s from schedule [%(schedule)s]"
|
|
||||||
msgstr ""
|
|
||||||
"%(process_name)s a créé la tâche %(task_name)s à partir de Schedule "
|
|
||||||
"[%(schedule)s]"
|
|
||||||
|
|
||||||
#: cluster.py:808
|
|
||||||
msgid "Skipping cpu affinity because psutil was not found."
|
msgid "Skipping cpu affinity because psutil was not found."
|
||||||
msgstr "L'affinité cpu ne sera pas définie car psutil n'a pas été trouvé."
|
msgstr "L'affinité cpu ne sera pas définie car psutil n'a pas été trouvé."
|
||||||
|
|
||||||
#: cluster.py:813
|
#: cluster.py:399
|
||||||
msgid "Faking cpu affinity because it is not supported on this platform"
|
msgid "Faking cpu affinity because it is not supported on this platform"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Simulation de l'affinité cpu parce qu'elle n'est pas supportée sur cette "
|
"Simulation de l'affinité cpu parce qu'elle n'est pas supportée sur cette "
|
||||||
"plateforme."
|
"plateforme."
|
||||||
|
|
||||||
#: cluster.py:835
|
#: cluster.py:421
|
||||||
#, python-format
|
#, python-format
|
||||||
msgid "%(pid)s will use cpu %(affinity)s"
|
msgid "%(pid)s will use cpu %(affinity)s"
|
||||||
msgstr "%(pid)s utilisera le CPU %(affinity)s"
|
msgstr "%(pid)s utilisera le CPU %(affinity)s"
|
||||||
|
|
||||||
#: conf.py:90
|
#: conf.py:122
|
||||||
#, python-format
|
#, python-format
|
||||||
msgid ""
|
msgid ""
|
||||||
"SAVE_LIMIT_PER (%(option)s) is not a valid option. Options are: 'group', "
|
"SAVE_LIMIT_PER (%(option)s) is not a valid option. Options are: 'group', "
|
||||||
@@ -195,28 +138,28 @@ msgstr ""
|
|||||||
"'group', 'name', 'func' et None. La valeur par défaut est None."
|
"'group', 'name', 'func' et None. La valeur par défaut est None."
|
||||||
|
|
||||||
#. Translators: Cluster status descriptions
|
#. Translators: Cluster status descriptions
|
||||||
#: conf.py:207
|
#: conf.py:239
|
||||||
msgid "Starting"
|
msgid "Starting"
|
||||||
msgstr "Démarrage"
|
msgstr "Démarrage"
|
||||||
|
|
||||||
#: conf.py:208
|
#: conf.py:240
|
||||||
msgid "Working"
|
msgid "Working"
|
||||||
msgstr "Actif"
|
msgstr "Actif"
|
||||||
|
|
||||||
#: conf.py:209
|
#: conf.py:241
|
||||||
msgid "Idle"
|
msgid "Idle"
|
||||||
msgstr "En attente"
|
msgstr "En attente"
|
||||||
|
|
||||||
#: conf.py:210
|
#: conf.py:242
|
||||||
msgid "Stopped"
|
msgid "Stopped"
|
||||||
msgstr "Arrêté"
|
msgstr "Arrêté"
|
||||||
|
|
||||||
#: conf.py:211
|
#: conf.py:243
|
||||||
msgid "Stopping"
|
msgid "Stopping"
|
||||||
msgstr "En cours d’arrêt"
|
msgstr "En cours d’arrêt"
|
||||||
|
|
||||||
#. Translators: help text for qcluster management command
|
#. Translators: help text for qcluster management command
|
||||||
#: management/commands/qcluster.py:9
|
#: management/commands/qcluster.py:11
|
||||||
msgid "Starts a Django Q Cluster."
|
msgid "Starts a Django Q Cluster."
|
||||||
msgstr "Démarre un cluster Django Q."
|
msgstr "Démarre un cluster Django Q."
|
||||||
|
|
||||||
@@ -237,259 +180,485 @@ msgstr "Surveille l'utilisation mémoire du Q cluster"
|
|||||||
msgid "Monitors Q Cluster activity"
|
msgid "Monitors Q Cluster activity"
|
||||||
msgstr "Surveille l'activité de Q cluster"
|
msgstr "Surveille l'activité de Q cluster"
|
||||||
|
|
||||||
#: models.py:125
|
#: models.py:30 models.py:469
|
||||||
|
msgid "Task id"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: models.py:31
|
||||||
|
msgid "32-character task identifier."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: models.py:36 models.py:235 models.py:470
|
||||||
|
msgid "Name"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: models.py:37
|
||||||
|
msgid "Optional human-readable name for lookup and display."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: models.py:41 models.py:240 models.py:468
|
||||||
|
msgid "Function"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: models.py:42
|
||||||
|
msgid "Dotted import path to the callable, e.g. myapp.tasks.job."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: models.py:47 models.py:247
|
||||||
|
msgid "Hook"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: models.py:48
|
||||||
|
msgid "Optional dotted path to a callback that receives the task result."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: models.py:53 models.py:253 models.py:472
|
||||||
|
msgid "Arguments"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: models.py:54
|
||||||
|
msgid "Pickled positional arguments (tuple)."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: models.py:59 models.py:259 models.py:473
|
||||||
|
msgid "Keyword arguments"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: models.py:60
|
||||||
|
msgid "Pickled keyword arguments (dict)."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: models.py:65
|
||||||
|
msgid "Result"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: models.py:66
|
||||||
|
msgid "Pickled return value or error payload."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: models.py:72 models.py:471
|
||||||
|
msgid "Group"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: models.py:73
|
||||||
|
msgid "Optional group id to aggregate related tasks."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: models.py:80 models.py:328
|
||||||
|
#, fuzzy
|
||||||
|
#| msgid "Clusters"
|
||||||
|
msgid "Cluster"
|
||||||
|
msgstr "Grappes"
|
||||||
|
|
||||||
|
#: models.py:81
|
||||||
|
msgid "Name of the cluster that executed this task."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: models.py:85
|
||||||
|
msgid "Started at"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: models.py:86
|
||||||
|
msgid "When the worker started executing the task."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: models.py:90
|
||||||
|
#, fuzzy
|
||||||
|
#| msgid "Stopped"
|
||||||
|
msgid "Stopped at"
|
||||||
|
msgstr "Arrêté"
|
||||||
|
|
||||||
|
#: models.py:91
|
||||||
|
msgid "When the worker finished (success or failure)."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: models.py:96 monitor_terminal.py:180
|
||||||
|
msgid "Success"
|
||||||
|
msgstr "Succès"
|
||||||
|
|
||||||
|
#: models.py:97
|
||||||
|
msgid "False if the task raised an exception or timed out."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: models.py:101
|
||||||
|
msgid "Attempt count"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: models.py:102
|
||||||
|
msgid "How many times execution was attempted."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: models.py:172
|
||||||
|
msgid "Task"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: models.py:173
|
||||||
|
msgid "Tasks"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: models.py:194
|
||||||
msgid "Successful task"
|
msgid "Successful task"
|
||||||
msgstr "Tâche réussie"
|
msgstr "Tâche réussie"
|
||||||
|
|
||||||
#: models.py:126
|
#: models.py:195
|
||||||
msgid "Successful tasks"
|
msgid "Successful tasks"
|
||||||
msgstr "Tâches réussies"
|
msgstr "Tâches réussies"
|
||||||
|
|
||||||
#: models.py:141
|
#: models.py:210
|
||||||
msgid "Failed task"
|
msgid "Failed task"
|
||||||
msgstr "Tâche échoué"
|
msgstr "Tâche échoué"
|
||||||
|
|
||||||
#: models.py:142
|
#: models.py:211
|
||||||
msgid "Failed tasks"
|
msgid "Failed tasks"
|
||||||
msgstr "Tâches échouées"
|
msgstr "Tâches échouées"
|
||||||
|
|
||||||
#: models.py:150 models.py:234
|
#: models.py:219 models.py:347
|
||||||
msgid "Please install croniter to enable cron expressions"
|
msgid "Please install croniter to enable cron expressions"
|
||||||
msgstr "Veuillez installer croniter pour activer les expressions cron."
|
msgstr "Veuillez installer croniter pour activer les expressions cron."
|
||||||
|
|
||||||
#: models.py:170
|
#: models.py:236
|
||||||
|
msgid "Optional label to identify this schedule in the admin."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: models.py:241
|
||||||
|
msgid "e.g. module.tasks.function"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: models.py:248
|
||||||
|
msgid "e.g. module.tasks.result_function"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: models.py:254
|
||||||
msgid "e.g. 1, 2, 'John'"
|
msgid "e.g. 1, 2, 'John'"
|
||||||
msgstr "ex. 1, 2, ‘Jean’"
|
msgstr "ex. 1, 2, ‘Jean’"
|
||||||
|
|
||||||
#: models.py:172
|
#: models.py:260
|
||||||
msgid "e.g. x=1, y=2, name='John'"
|
msgid "e.g. x=1, y=2, name='John'"
|
||||||
msgstr "p. ex. x = 1, y = 2, Nom = ‘Jean’"
|
msgstr "p. ex. x = 1, y = 2, Nom = ‘Jean’"
|
||||||
|
|
||||||
#: models.py:186
|
#: models.py:274
|
||||||
msgid "Once"
|
msgid "Once"
|
||||||
msgstr "Une fois"
|
msgstr "Une fois"
|
||||||
|
|
||||||
#: models.py:187
|
#: models.py:275 models.py:296
|
||||||
msgid "Minutes"
|
msgid "Minutes"
|
||||||
msgstr "Minutes"
|
msgstr "Minutes"
|
||||||
|
|
||||||
#: models.py:188
|
#: models.py:276
|
||||||
msgid "Hourly"
|
msgid "Hourly"
|
||||||
msgstr "Toutes les heures"
|
msgstr "Toutes les heures"
|
||||||
|
|
||||||
#: models.py:189
|
#: models.py:277
|
||||||
msgid "Daily"
|
msgid "Daily"
|
||||||
msgstr "Quotidien"
|
msgstr "Quotidien"
|
||||||
|
|
||||||
#: models.py:190
|
#: models.py:278
|
||||||
msgid "Weekly"
|
msgid "Weekly"
|
||||||
msgstr "Hebdomadaire"
|
msgstr "Hebdomadaire"
|
||||||
|
|
||||||
#: models.py:191
|
#: models.py:279
|
||||||
#, fuzzy
|
#, fuzzy
|
||||||
#| msgid "Weekly"
|
#| msgid "Weekly"
|
||||||
msgid "Biweekly"
|
msgid "Biweekly"
|
||||||
msgstr "Bihebdomadaire"
|
msgstr "Bihebdomadaire"
|
||||||
|
|
||||||
#: models.py:192
|
#: models.py:280
|
||||||
msgid "Monthly"
|
msgid "Monthly"
|
||||||
msgstr "Mensuel"
|
msgstr "Mensuel"
|
||||||
|
|
||||||
#: models.py:193
|
#: models.py:281
|
||||||
#, fuzzy
|
#, fuzzy
|
||||||
#| msgid "Monthly"
|
#| msgid "Monthly"
|
||||||
msgid "Bimonthly"
|
msgid "Bimonthly"
|
||||||
msgstr "Bimestriel"
|
msgstr "Bimestriel"
|
||||||
|
|
||||||
#: models.py:194
|
#: models.py:282
|
||||||
msgid "Quarterly"
|
msgid "Quarterly"
|
||||||
msgstr "Trimestriel"
|
msgstr "Trimestriel"
|
||||||
|
|
||||||
#: models.py:195
|
#: models.py:283
|
||||||
msgid "Yearly"
|
msgid "Yearly"
|
||||||
msgstr "Annuel"
|
msgstr "Annuel"
|
||||||
|
|
||||||
#: models.py:196
|
#: models.py:284 models.py:313
|
||||||
msgid "Cron"
|
msgid "Cron"
|
||||||
msgstr "Cron"
|
msgstr "Cron"
|
||||||
|
|
||||||
#: models.py:199
|
#: models.py:290
|
||||||
msgid "Schedule Type"
|
msgid "Schedule Type"
|
||||||
msgstr "Type de plannification"
|
msgstr "Type de plannification"
|
||||||
|
|
||||||
#: models.py:202
|
#: models.py:291
|
||||||
|
msgid "How often this task should be enqueued."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: models.py:297
|
||||||
msgid "Number of minutes for the Minutes type"
|
msgid "Number of minutes for the Minutes type"
|
||||||
msgstr "Nombre de minutes pour le type de minutes"
|
msgstr "Nombre de minutes pour le type de minutes"
|
||||||
|
|
||||||
#: models.py:205
|
#: models.py:300
|
||||||
msgid "Repeats"
|
msgid "Repeats"
|
||||||
msgstr "Répéter"
|
msgstr "Répéter"
|
||||||
|
|
||||||
#: models.py:205
|
#: models.py:300
|
||||||
msgid "n = n times, -1 = forever"
|
msgid "n = n times, -1 = forever"
|
||||||
msgstr "n = n fois,-1 = Toujours"
|
msgstr "n = n fois,-1 = Toujours"
|
||||||
|
|
||||||
#: models.py:208
|
#: models.py:303
|
||||||
msgid "Next Run"
|
msgid "Next Run"
|
||||||
msgstr "Prochaine exécution"
|
msgstr "Prochaine exécution"
|
||||||
|
|
||||||
#: models.py:215
|
#: models.py:304
|
||||||
|
msgid "When this schedule runs next (stored in UTC)."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: models.py:314
|
||||||
msgid "Cron expression"
|
msgid "Cron expression"
|
||||||
msgstr "Expression Cron"
|
msgstr "Expression Cron"
|
||||||
|
|
||||||
#: models.py:224
|
#: models.py:320
|
||||||
|
msgid "Last task id"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: models.py:321
|
||||||
|
msgid "Id of the last task spawned from this schedule (read-only)."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: models.py:329 models.py:427
|
||||||
|
msgid "Name of the target cluster"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: models.py:336
|
||||||
|
msgid "Intended date kwarg"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: models.py:337
|
||||||
msgid "Name of kwarg to pass intended schedule date"
|
msgid "Name of kwarg to pass intended schedule date"
|
||||||
msgstr "Nom du kwarg à passer Date prévue de l'horaire"
|
msgstr "Nom du kwarg à passer Date prévue de l'horaire"
|
||||||
|
|
||||||
#: models.py:299
|
#: models.py:418
|
||||||
msgid "Scheduled task"
|
msgid "Scheduled task"
|
||||||
msgstr "Tâche planifiée"
|
msgstr "Tâche planifiée"
|
||||||
|
|
||||||
#: models.py:300
|
#: models.py:419
|
||||||
msgid "Scheduled tasks"
|
msgid "Scheduled tasks"
|
||||||
msgstr "Tâches planifiées"
|
msgstr "Tâches planifiées"
|
||||||
|
|
||||||
#: models.py:326
|
#: models.py:426
|
||||||
|
#, fuzzy
|
||||||
|
#| msgid "Clusters"
|
||||||
|
msgid "Cluster key"
|
||||||
|
msgstr "Grappes"
|
||||||
|
|
||||||
|
#: models.py:430
|
||||||
|
msgid "Payload"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: models.py:431
|
||||||
|
msgid "Signed serialized task package (do not edit manually)."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: models.py:435
|
||||||
|
msgid "Lock until"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: models.py:436
|
||||||
|
msgid "Prevent any cluster from pulling until"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: models.py:474
|
||||||
|
#, fuzzy
|
||||||
|
#| msgid "Queued task"
|
||||||
|
msgid "Queue options"
|
||||||
|
msgstr "Tâche en file d'attente"
|
||||||
|
|
||||||
|
#: models.py:478
|
||||||
msgid "Queued task"
|
msgid "Queued task"
|
||||||
msgstr "Tâche en file d'attente"
|
msgstr "Tâche en file d'attente"
|
||||||
|
|
||||||
#: models.py:327
|
#: models.py:479
|
||||||
msgid "Queued tasks"
|
msgid "Queued tasks"
|
||||||
msgstr "Tâches en file d'attente"
|
msgstr "Tâches en file d'attente"
|
||||||
|
|
||||||
#: monitor.py:64 monitor.py:348
|
#: monitor.py:41
|
||||||
|
#, python-format
|
||||||
|
msgid "%(name)s monitoring at %(id)s"
|
||||||
|
msgstr "%(name)s surveille les résultats %(id)s"
|
||||||
|
|
||||||
|
#: monitor.py:61
|
||||||
|
#, python-format
|
||||||
|
msgid "Processed '%(info_name)s' (%(task_name)s)"
|
||||||
|
msgstr "traité '%(info_name)s' (%(task_name)s)"
|
||||||
|
|
||||||
|
#: monitor.py:67
|
||||||
|
#, python-format
|
||||||
|
msgid "Failed '%(info_name)s' (%(task_name)s) - %(task_result)s"
|
||||||
|
msgstr "Manqué '%(info_name)s' (%(task_name)s) - %(task_result)s"
|
||||||
|
|
||||||
|
#: monitor.py:74
|
||||||
|
#, python-format
|
||||||
|
msgid "%(name)s stopped monitoring results"
|
||||||
|
msgstr "%(name)s a cessé de de surveiller les résultats"
|
||||||
|
|
||||||
|
#: monitor_terminal.py:64 monitor_terminal.py:348
|
||||||
msgid "Host"
|
msgid "Host"
|
||||||
msgstr "Hôte"
|
msgstr "Hôte"
|
||||||
|
|
||||||
#: monitor.py:68 monitor.py:352 monitor.py:459
|
#: monitor_terminal.py:68 monitor_terminal.py:352 monitor_terminal.py:457
|
||||||
msgid "Id"
|
msgid "Id"
|
||||||
msgstr "Id"
|
msgstr "Id"
|
||||||
|
|
||||||
#: monitor.py:72
|
#: monitor_terminal.py:72
|
||||||
msgid "State"
|
msgid "State"
|
||||||
msgstr "Statut"
|
msgstr "Statut"
|
||||||
|
|
||||||
#: monitor.py:76
|
#: monitor_terminal.py:76
|
||||||
msgid "Pool"
|
msgid "Pool"
|
||||||
msgstr "Piscine"
|
msgstr "Piscine"
|
||||||
|
|
||||||
#: monitor.py:80
|
#: monitor_terminal.py:80
|
||||||
msgid "TQ"
|
msgid "TQ"
|
||||||
msgstr "TQ"
|
msgstr "TQ"
|
||||||
|
|
||||||
#: monitor.py:84
|
#: monitor_terminal.py:84
|
||||||
msgid "RQ"
|
msgid "RQ"
|
||||||
msgstr "RQ"
|
msgstr "RQ"
|
||||||
|
|
||||||
#: monitor.py:88
|
#: monitor_terminal.py:88
|
||||||
msgid "RC"
|
msgid "RC"
|
||||||
msgstr "RC"
|
msgstr "RC"
|
||||||
|
|
||||||
#: monitor.py:92
|
#: monitor_terminal.py:92
|
||||||
msgid "Up"
|
msgid "Up"
|
||||||
msgstr "Haut"
|
msgstr "Haut"
|
||||||
|
|
||||||
#: monitor.py:172 monitor.py:286
|
#: monitor_terminal.py:172 monitor_terminal.py:286
|
||||||
msgid "Queued"
|
msgid "Queued"
|
||||||
msgstr "En file d'attente"
|
msgstr "En file d'attente"
|
||||||
|
|
||||||
#: monitor.py:180
|
#: monitor_terminal.py:190 monitor_terminal.py:294
|
||||||
msgid "Success"
|
|
||||||
msgstr "Succès"
|
|
||||||
|
|
||||||
#: monitor.py:190 monitor.py:294
|
|
||||||
msgid "Failures"
|
msgid "Failures"
|
||||||
msgstr "Défaillances"
|
msgstr "Défaillances"
|
||||||
|
|
||||||
#: monitor.py:201 monitor.py:498
|
#: monitor_terminal.py:201 monitor_terminal.py:496
|
||||||
msgid "[Press q to quit]"
|
msgid "[Press q to quit]"
|
||||||
msgstr "[appuyez sur q pour quitter]"
|
msgstr "[appuyez sur q pour quitter]"
|
||||||
|
|
||||||
#: monitor.py:227
|
#: monitor_terminal.py:227
|
||||||
msgid "day"
|
msgid "day"
|
||||||
msgstr "jour"
|
msgstr "jour"
|
||||||
|
|
||||||
#: monitor.py:248
|
#: monitor_terminal.py:248
|
||||||
msgid "second"
|
msgid "second"
|
||||||
msgstr "seconde"
|
msgstr "seconde"
|
||||||
|
|
||||||
#: monitor.py:251
|
#: monitor_terminal.py:251
|
||||||
msgid "minute"
|
msgid "minute"
|
||||||
msgstr "minute"
|
msgstr "minute"
|
||||||
|
|
||||||
#: monitor.py:254
|
#: monitor_terminal.py:254
|
||||||
msgid "hour"
|
msgid "hour"
|
||||||
msgstr "heure"
|
msgstr "heure"
|
||||||
|
|
||||||
#: monitor.py:263
|
#: monitor_terminal.py:263
|
||||||
#, python-format
|
#, python-format
|
||||||
msgid "-- %(prefix)s %(version)s on %(info)s --"
|
msgid "-- %(prefix)s %(version)s on %(info)s --"
|
||||||
msgstr "--%(prefix)s %(version)s sur %(info)s --"
|
msgstr "--%(prefix)s %(version)s sur %(info)s --"
|
||||||
|
|
||||||
#: monitor.py:273
|
#: monitor_terminal.py:273
|
||||||
msgid "Clusters"
|
msgid "Clusters"
|
||||||
msgstr "Grappes"
|
msgstr "Grappes"
|
||||||
|
|
||||||
#: monitor.py:277
|
#: monitor_terminal.py:277
|
||||||
msgid "Workers"
|
msgid "Workers"
|
||||||
msgstr "Processus"
|
msgstr "Processus"
|
||||||
|
|
||||||
#: monitor.py:281
|
#: monitor_terminal.py:281
|
||||||
msgid "Restarts"
|
msgid "Restarts"
|
||||||
msgstr "Redémarrages"
|
msgstr "Redémarrages"
|
||||||
|
|
||||||
#: monitor.py:290
|
#: monitor_terminal.py:290
|
||||||
msgid "Successes"
|
msgid "Successes"
|
||||||
msgstr "Succès"
|
msgstr "Succès"
|
||||||
|
|
||||||
#: monitor.py:299
|
#: monitor_terminal.py:299
|
||||||
msgid "Schedules"
|
msgid "Schedules"
|
||||||
msgstr "Planifications"
|
msgstr "Planifications"
|
||||||
|
|
||||||
#: monitor.py:303
|
#: monitor_terminal.py:303
|
||||||
#, python-format
|
#, python-format
|
||||||
msgid "Tasks/%(per)s"
|
msgid "Tasks/%(per)s"
|
||||||
msgstr "Tâches/%(per)s"
|
msgstr "Tâches/%(per)s"
|
||||||
|
|
||||||
#: monitor.py:307
|
#: monitor_terminal.py:307
|
||||||
msgid "Avg time"
|
msgid "Avg time"
|
||||||
msgstr "Temps Moyen"
|
msgstr "Temps Moyen"
|
||||||
|
|
||||||
#: monitor.py:357
|
#: monitor_terminal.py:357
|
||||||
msgid "Available (%)"
|
msgid "Available (%)"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: monitor.py:363
|
#: monitor_terminal.py:363
|
||||||
msgid "Available (MB)"
|
msgid "Available (MB)"
|
||||||
msgstr "Disponible sur (MB)"
|
msgstr "Disponible sur (MB)"
|
||||||
|
|
||||||
#: monitor.py:368
|
#: monitor_terminal.py:368
|
||||||
msgid "Total (MB)"
|
msgid "Total (MB)"
|
||||||
msgstr "Total (MB)"
|
msgstr "Total (MB)"
|
||||||
|
|
||||||
#: monitor.py:373
|
#: monitor_terminal.py:373
|
||||||
msgid "Sentinel (MB)"
|
msgid "Sentinel (MB)"
|
||||||
msgstr "Sentinel (MB)"
|
msgstr "Sentinel (MB)"
|
||||||
|
|
||||||
#: monitor.py:379
|
#: monitor_terminal.py:379
|
||||||
msgid "Monitor (MB)"
|
msgid "Monitor (MB)"
|
||||||
msgstr "Monitor (MB)"
|
msgstr "Monitor (MB)"
|
||||||
|
|
||||||
#: monitor.py:385
|
#: monitor_terminal.py:385
|
||||||
#, fuzzy
|
#, fuzzy
|
||||||
#| msgid "Workers"
|
#| msgid "Workers"
|
||||||
msgid "Workers (MB)"
|
msgid "Workers (MB)"
|
||||||
msgstr "Processus (MB)"
|
msgstr "Processus (MB)"
|
||||||
|
|
||||||
#: monitor.py:487
|
#: monitor_terminal.py:485
|
||||||
#, python-format
|
#, python-format
|
||||||
msgid "Available lowest (): %(memory_percent)s ((at)s)"
|
msgid "Available lowest (): %(memory_percent)s ((at)s)"
|
||||||
msgstr "Disponible le plus bas () : %(memory_percent)s ((at)s)"
|
msgstr "Disponible le plus bas () : %(memory_percent)s ((at)s)"
|
||||||
|
|
||||||
#: monitor.py:509
|
#: monitor_terminal.py:507
|
||||||
msgid "No clusters appear to be running."
|
msgid "No clusters appear to be running."
|
||||||
msgstr "Aucun cluster ne semble être en cours d'exécution."
|
msgstr "Aucun cluster ne semble être en cours d'exécution."
|
||||||
|
|
||||||
|
#: pusher.py:40
|
||||||
|
#, python-format
|
||||||
|
msgid "%(name)s pushing tasks at %(id)s"
|
||||||
|
msgstr "%(name)s répartit les tâches %(id)s"
|
||||||
|
|
||||||
|
#: pusher.py:67
|
||||||
|
#, python-format
|
||||||
|
msgid "queueing from %(list_key)s"
|
||||||
|
msgstr "mise en file d'attente de %(list_key)s"
|
||||||
|
|
||||||
|
#: pusher.py:71
|
||||||
|
#, python-format
|
||||||
|
msgid "%(name)s stopped pushing tasks"
|
||||||
|
msgstr "%(name)s a cessé de répartir les tâches"
|
||||||
|
|
||||||
|
#: scheduler.py:110
|
||||||
|
#, python-format
|
||||||
|
msgid "%(process_name)s failed to create a task from schedule [%(schedule)s]"
|
||||||
|
msgstr ""
|
||||||
|
"%(process_name)s Echec de la création d'une tâche à partir de Schedule "
|
||||||
|
"[%(schedule)s]"
|
||||||
|
|
||||||
|
#: scheduler.py:121
|
||||||
|
#, python-format
|
||||||
|
msgid ""
|
||||||
|
"%(process_name)s created task %(task_name)s from schedule [%(schedule)s]"
|
||||||
|
msgstr ""
|
||||||
|
"%(process_name)s a créé la tâche %(task_name)s à partir de Schedule "
|
||||||
|
"[%(schedule)s]"
|
||||||
|
|
||||||
#: signals.py:22
|
#: signals.py:22
|
||||||
#, python-format
|
#, python-format
|
||||||
msgid "malformed return hook '%(hook)s' for [%(name)s]"
|
msgid "malformed return hook '%(hook)s' for [%(name)s]"
|
||||||
@@ -500,6 +669,25 @@ msgstr "hook de retour '%(hook)s' mal formé pour [%(name)s]"
|
|||||||
msgid "return hook %(hook)s failed on [%(name)s] because %(error)s"
|
msgid "return hook %(hook)s failed on [%(name)s] because %(error)s"
|
||||||
msgstr "hook de retour %(hook)s a échoué sur [%(name)s] à cause de %(error)s"
|
msgstr "hook de retour %(hook)s a échoué sur [%(name)s] à cause de %(error)s"
|
||||||
|
|
||||||
|
#: timeout.py:30 timeout.py:43
|
||||||
|
msgid "SIGALARM is not available on your platform"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: worker.py:49
|
||||||
|
#, python-format
|
||||||
|
msgid "%(proc_name)s ready for work at %(id)s"
|
||||||
|
msgstr "%(proc_name)s prêt pour le travail à %(id)s"
|
||||||
|
|
||||||
|
#: worker.py:69
|
||||||
|
#, fuzzy, python-format
|
||||||
|
msgid "%(proc_name)s processing %(task_name)s '%(func_name)s'"
|
||||||
|
msgstr "%(proc_name)s exécute %(task_name)s '%(func_name)s'"
|
||||||
|
|
||||||
|
#: worker.py:135
|
||||||
|
#, python-format
|
||||||
|
msgid "%(proc_name)s stopped doing work"
|
||||||
|
msgstr "%(proc_name)s a cessé de travailler"
|
||||||
|
|
||||||
#, python-format
|
#, python-format
|
||||||
#~ msgid ""
|
#~ msgid ""
|
||||||
#~ "Could not process '%(func_name)s'. Check the location of the function and "
|
#~ "Could not process '%(func_name)s'. Check the location of the function and "
|
||||||
|
|||||||
@@ -0,0 +1,676 @@
|
|||||||
|
# Russian translation for django-q.
|
||||||
|
# Copyright (C) Django Q authors
|
||||||
|
# This file is distributed under the same license as the django-q package.
|
||||||
|
#
|
||||||
|
msgid ""
|
||||||
|
msgstr ""
|
||||||
|
"Project-Id-Version: django-q\n"
|
||||||
|
"Report-Msgid-Bugs-To: \n"
|
||||||
|
"POT-Creation-Date: 2026-04-17 21:07+0000\n"
|
||||||
|
"PO-Revision-Date: 2026-04-04 12:00+0000\n"
|
||||||
|
"Last-Translator: \n"
|
||||||
|
"Language-Team: Russian\n"
|
||||||
|
"Language: ru\n"
|
||||||
|
"MIME-Version: 1.0\n"
|
||||||
|
"Content-Type: text/plain; charset=UTF-8\n"
|
||||||
|
"Content-Transfer-Encoding: 8bit\n"
|
||||||
|
"Plural-Forms: nplurals=4; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && "
|
||||||
|
"n%10<=4 && (n%100<12 || n%100>14) ? 1 : n%10==0 || (n%10>=5 && n%10<=9) || "
|
||||||
|
"(n%100>=11 && n%100<=14)? 2 : 3);\n"
|
||||||
|
|
||||||
|
#: django_q/admin.py:30
|
||||||
|
msgid "Resubmit selected tasks to queue"
|
||||||
|
msgstr "Повторно отправить выбранные задачи в очередь"
|
||||||
|
|
||||||
|
#: django_q/admin.py:64
|
||||||
|
msgid "Time Taken"
|
||||||
|
msgstr "Время выполнения"
|
||||||
|
|
||||||
|
#: django_q/admin.py:95
|
||||||
|
msgid "Short result"
|
||||||
|
msgstr "Краткий результат"
|
||||||
|
|
||||||
|
#: django_q/admin.py:142 django_q/models.py:412
|
||||||
|
msgid "success"
|
||||||
|
msgstr "успех"
|
||||||
|
|
||||||
|
#: django_q/admin.py:154 django_q/models.py:414
|
||||||
|
msgid "last_run"
|
||||||
|
msgstr "последний запуск"
|
||||||
|
|
||||||
|
#: django_q/cluster.py:75
|
||||||
|
#, python-format
|
||||||
|
msgid "Q Cluster %(name)s starting."
|
||||||
|
msgstr "Запуск кластера Q %(name)s."
|
||||||
|
|
||||||
|
#: django_q/cluster.py:83
|
||||||
|
#, python-format
|
||||||
|
msgid "Q Cluster %(name)s stopping."
|
||||||
|
msgstr "Остановка кластера Q %(name)s."
|
||||||
|
|
||||||
|
#: django_q/cluster.py:86
|
||||||
|
#, python-format
|
||||||
|
msgid "Q Cluster %(name)s has stopped."
|
||||||
|
msgstr "Кластер Q %(name)s остановлен."
|
||||||
|
|
||||||
|
#: django_q/cluster.py:93
|
||||||
|
#, python-format
|
||||||
|
msgid "%(name)s got signal %(signal)s"
|
||||||
|
msgstr "%(name)s получил сигнал %(signal)s"
|
||||||
|
|
||||||
|
#: django_q/cluster.py:224
|
||||||
|
#, python-format
|
||||||
|
msgid "reincarnated monitor %(name)s after sudden death"
|
||||||
|
msgstr "монитор %(name)s перезапущен после аварийного завершения"
|
||||||
|
|
||||||
|
#: django_q/cluster.py:230
|
||||||
|
#, python-format
|
||||||
|
msgid "reincarnated pusher %(name)s after sudden death"
|
||||||
|
msgstr "пушер %(name)s перезапущен после аварийного завершения"
|
||||||
|
|
||||||
|
#: django_q/cluster.py:262
|
||||||
|
#, python-format
|
||||||
|
msgid ""
|
||||||
|
"reincarnated worker %(name)s after timeout while processing task "
|
||||||
|
"%(task_name)s"
|
||||||
|
msgstr ""
|
||||||
|
"воркер %(name)s перезапущен по таймауту при выполнении задачи %(task_name)s"
|
||||||
|
|
||||||
|
#: django_q/cluster.py:265
|
||||||
|
#, python-format
|
||||||
|
msgid "reincarnated worker %(name)s after timeout"
|
||||||
|
msgstr "воркер %(name)s перезапущен по таймауту"
|
||||||
|
|
||||||
|
#: django_q/cluster.py:270
|
||||||
|
#, python-format
|
||||||
|
msgid "recycled worker %(name)s"
|
||||||
|
msgstr "воркер %(name)s перезапущен (recycle)"
|
||||||
|
|
||||||
|
#: django_q/cluster.py:273
|
||||||
|
#, python-format
|
||||||
|
msgid "reincarnated worker %(name)s after death"
|
||||||
|
msgstr "воркер %(name)s перезапущен после сбоя"
|
||||||
|
|
||||||
|
#: django_q/cluster.py:297
|
||||||
|
#, python-format
|
||||||
|
msgid "%(name)s guarding cluster %(cluster_name)s"
|
||||||
|
msgstr "%(name)s обслуживает кластер %(cluster_name)s"
|
||||||
|
|
||||||
|
#: django_q/cluster.py:307
|
||||||
|
#, python-format
|
||||||
|
msgid "Q Cluster %(cluster_name)s running."
|
||||||
|
msgstr "Кластер Q %(cluster_name)s работает."
|
||||||
|
|
||||||
|
#: django_q/cluster.py:346
|
||||||
|
#, python-format
|
||||||
|
msgid "%(name)s stopping cluster processes"
|
||||||
|
msgstr "%(name)s останавливает процессы кластера"
|
||||||
|
|
||||||
|
#: django_q/cluster.py:371
|
||||||
|
#, python-format
|
||||||
|
msgid "%(name)s waiting for the monitor."
|
||||||
|
msgstr "%(name)s ожидает монитор."
|
||||||
|
|
||||||
|
#: django_q/cluster.py:394
|
||||||
|
msgid "Skipping cpu affinity because psutil was not found."
|
||||||
|
msgstr "Привязка к CPU пропущена: не найден psutil."
|
||||||
|
|
||||||
|
#: django_q/cluster.py:399
|
||||||
|
msgid "Faking cpu affinity because it is not supported on this platform"
|
||||||
|
msgstr "Имитация привязки к CPU: на этой платформе не поддерживается"
|
||||||
|
|
||||||
|
#: django_q/cluster.py:421
|
||||||
|
#, python-format
|
||||||
|
msgid "%(pid)s will use cpu %(affinity)s"
|
||||||
|
msgstr "%(pid)s будет использовать CPU %(affinity)s"
|
||||||
|
|
||||||
|
#: django_q/conf.py:122
|
||||||
|
#, python-format
|
||||||
|
msgid ""
|
||||||
|
"SAVE_LIMIT_PER (%(option)s) is not a valid option. Options are: 'group', "
|
||||||
|
"'name', 'func' and None. Default is None."
|
||||||
|
msgstr ""
|
||||||
|
"SAVE_LIMIT_PER (%(option)s) — недопустимое значение. Допустимо: «group», "
|
||||||
|
"«name», «func» и None. По умолчанию None."
|
||||||
|
|
||||||
|
#. Translators: Cluster status descriptions
|
||||||
|
#: django_q/conf.py:239
|
||||||
|
msgid "Starting"
|
||||||
|
msgstr "Запуск"
|
||||||
|
|
||||||
|
#: django_q/conf.py:240
|
||||||
|
msgid "Working"
|
||||||
|
msgstr "Работает"
|
||||||
|
|
||||||
|
#: django_q/conf.py:241
|
||||||
|
msgid "Idle"
|
||||||
|
msgstr "Простой"
|
||||||
|
|
||||||
|
#: django_q/conf.py:242
|
||||||
|
msgid "Stopped"
|
||||||
|
msgstr "Остановлен"
|
||||||
|
|
||||||
|
#: django_q/conf.py:243
|
||||||
|
msgid "Stopping"
|
||||||
|
msgstr "Останавливается"
|
||||||
|
|
||||||
|
#. Translators: help text for qcluster management command
|
||||||
|
#: django_q/management/commands/qcluster.py:11
|
||||||
|
msgid "Starts a Django Q Cluster."
|
||||||
|
msgstr "Запускает кластер Django Q."
|
||||||
|
|
||||||
|
#. Translators: help text for qinfo management command
|
||||||
|
#: django_q/management/commands/qinfo.py:11
|
||||||
|
msgid "General information over all clusters."
|
||||||
|
msgstr "Общая информация по всем кластерам."
|
||||||
|
|
||||||
|
#. Translators: help text for qmemory management command
|
||||||
|
#: django_q/management/commands/qmemory.py:9
|
||||||
|
msgid "Monitors Q Cluster memory usage"
|
||||||
|
msgstr "Мониторинг использования памяти кластером Q"
|
||||||
|
|
||||||
|
#. Translators: help text for qmonitor management command
|
||||||
|
#: django_q/management/commands/qmonitor.py:9
|
||||||
|
msgid "Monitors Q Cluster activity"
|
||||||
|
msgstr "Мониторинг активности кластера Q"
|
||||||
|
|
||||||
|
#: django_q/models.py:30 django_q/models.py:469
|
||||||
|
msgid "Task id"
|
||||||
|
msgstr "Идентификатор задачи"
|
||||||
|
|
||||||
|
#: django_q/models.py:31
|
||||||
|
msgid "32-character task identifier."
|
||||||
|
msgstr "32-символьный идентификатор задачи."
|
||||||
|
|
||||||
|
#: django_q/models.py:36 django_q/models.py:235 django_q/models.py:470
|
||||||
|
msgid "Name"
|
||||||
|
msgstr "Имя"
|
||||||
|
|
||||||
|
#: django_q/models.py:37
|
||||||
|
msgid "Optional human-readable name for lookup and display."
|
||||||
|
msgstr "Необязательное имя для поиска и отображения."
|
||||||
|
|
||||||
|
#: django_q/models.py:41 django_q/models.py:240 django_q/models.py:468
|
||||||
|
msgid "Function"
|
||||||
|
msgstr "Функция"
|
||||||
|
|
||||||
|
#: django_q/models.py:42
|
||||||
|
msgid "Dotted import path to the callable, e.g. myapp.tasks.job."
|
||||||
|
msgstr "Путь импорта к вызываемому объекту, напр. myapp.tasks.job."
|
||||||
|
|
||||||
|
#: django_q/models.py:47 django_q/models.py:247
|
||||||
|
msgid "Hook"
|
||||||
|
msgstr "Обработчик"
|
||||||
|
|
||||||
|
#: django_q/models.py:48
|
||||||
|
msgid "Optional dotted path to a callback that receives the task result."
|
||||||
|
msgstr "Необязательный путь к функции, получающей результат задачи."
|
||||||
|
|
||||||
|
#: django_q/models.py:53 django_q/models.py:253 django_q/models.py:472
|
||||||
|
msgid "Arguments"
|
||||||
|
msgstr "Аргументы"
|
||||||
|
|
||||||
|
#: django_q/models.py:54
|
||||||
|
msgid "Pickled positional arguments (tuple)."
|
||||||
|
msgstr "Сериализованные позиционные аргументы (tuple)."
|
||||||
|
|
||||||
|
#: django_q/models.py:59 django_q/models.py:259 django_q/models.py:473
|
||||||
|
msgid "Keyword arguments"
|
||||||
|
msgstr "Именованные аргументы"
|
||||||
|
|
||||||
|
#: django_q/models.py:60
|
||||||
|
msgid "Pickled keyword arguments (dict)."
|
||||||
|
msgstr "Сериализованные именованные аргументы (dict)."
|
||||||
|
|
||||||
|
#: django_q/models.py:65
|
||||||
|
msgid "Result"
|
||||||
|
msgstr "Результат"
|
||||||
|
|
||||||
|
#: django_q/models.py:66
|
||||||
|
msgid "Pickled return value or error payload."
|
||||||
|
msgstr "Сериализованный результат или данные об ошибке."
|
||||||
|
|
||||||
|
#: django_q/models.py:72 django_q/models.py:471
|
||||||
|
msgid "Group"
|
||||||
|
msgstr "Группа"
|
||||||
|
|
||||||
|
#: django_q/models.py:73
|
||||||
|
msgid "Optional group id to aggregate related tasks."
|
||||||
|
msgstr "Необязательный идентификатор группы связанных задач."
|
||||||
|
|
||||||
|
#: django_q/models.py:80 django_q/models.py:328
|
||||||
|
msgid "Cluster"
|
||||||
|
msgstr "Кластер"
|
||||||
|
|
||||||
|
#: django_q/models.py:81
|
||||||
|
msgid "Name of the cluster that executed this task."
|
||||||
|
msgstr "Имя кластера, выполнившего эту задачу."
|
||||||
|
|
||||||
|
#: django_q/models.py:85
|
||||||
|
msgid "Started at"
|
||||||
|
msgstr "Начало выполнения"
|
||||||
|
|
||||||
|
#: django_q/models.py:86
|
||||||
|
msgid "When the worker started executing the task."
|
||||||
|
msgstr "Когда воркер начал выполнение задачи."
|
||||||
|
|
||||||
|
#: django_q/models.py:90
|
||||||
|
msgid "Stopped at"
|
||||||
|
msgstr "Окончание выполнения"
|
||||||
|
|
||||||
|
#: django_q/models.py:91
|
||||||
|
msgid "When the worker finished (success or failure)."
|
||||||
|
msgstr "Когда воркер завершил выполнение (успех или ошибка)."
|
||||||
|
|
||||||
|
#: django_q/models.py:96 django_q/monitor_terminal.py:180
|
||||||
|
msgid "Success"
|
||||||
|
msgstr "Успех"
|
||||||
|
|
||||||
|
#: django_q/models.py:97
|
||||||
|
msgid "False if the task raised an exception or timed out."
|
||||||
|
msgstr "Ложь, если задача завершилась исключением или таймаутом."
|
||||||
|
|
||||||
|
#: django_q/models.py:101
|
||||||
|
msgid "Attempt count"
|
||||||
|
msgstr "Число попыток"
|
||||||
|
|
||||||
|
#: django_q/models.py:102
|
||||||
|
msgid "How many times execution was attempted."
|
||||||
|
msgstr "Сколько раз выполнялась попытка запуска."
|
||||||
|
|
||||||
|
#: django_q/models.py:172
|
||||||
|
msgid "Task"
|
||||||
|
msgstr "Задача"
|
||||||
|
|
||||||
|
#: django_q/models.py:173
|
||||||
|
msgid "Tasks"
|
||||||
|
msgstr "Задачи"
|
||||||
|
|
||||||
|
#: django_q/models.py:194
|
||||||
|
msgid "Successful task"
|
||||||
|
msgstr "Успешная задача"
|
||||||
|
|
||||||
|
#: django_q/models.py:195
|
||||||
|
msgid "Successful tasks"
|
||||||
|
msgstr "Успешные задачи"
|
||||||
|
|
||||||
|
#: django_q/models.py:210
|
||||||
|
msgid "Failed task"
|
||||||
|
msgstr "Неудачная задача"
|
||||||
|
|
||||||
|
#: django_q/models.py:211
|
||||||
|
msgid "Failed tasks"
|
||||||
|
msgstr "Неудачные задачи"
|
||||||
|
|
||||||
|
#: django_q/models.py:219 django_q/models.py:347
|
||||||
|
msgid "Please install croniter to enable cron expressions"
|
||||||
|
msgstr "Установите croniter для поддержки cron-выражений"
|
||||||
|
|
||||||
|
#: django_q/models.py:236
|
||||||
|
msgid "Optional label to identify this schedule in the admin."
|
||||||
|
msgstr "Необязательная подпись для расписания в админке."
|
||||||
|
|
||||||
|
#: django_q/models.py:241
|
||||||
|
msgid "e.g. module.tasks.function"
|
||||||
|
msgstr "например: module.tasks.function"
|
||||||
|
|
||||||
|
#: django_q/models.py:248
|
||||||
|
msgid "e.g. module.tasks.result_function"
|
||||||
|
msgstr "например: module.tasks.result_function "
|
||||||
|
|
||||||
|
#: django_q/models.py:254
|
||||||
|
msgid "e.g. 1, 2, 'John'"
|
||||||
|
msgstr "например: 1, 2, 'Алимхан'"
|
||||||
|
|
||||||
|
#: django_q/models.py:260
|
||||||
|
msgid "e.g. x=1, y=2, name='John'"
|
||||||
|
msgstr "например: x=1, y=2, name='Алимхан'"
|
||||||
|
|
||||||
|
#: django_q/models.py:274
|
||||||
|
msgid "Once"
|
||||||
|
msgstr "Один раз"
|
||||||
|
|
||||||
|
#: django_q/models.py:275 django_q/models.py:296
|
||||||
|
msgid "Minutes"
|
||||||
|
msgstr "Минуты"
|
||||||
|
|
||||||
|
#: django_q/models.py:276
|
||||||
|
msgid "Hourly"
|
||||||
|
msgstr "Ежечасно"
|
||||||
|
|
||||||
|
#: django_q/models.py:277
|
||||||
|
msgid "Daily"
|
||||||
|
msgstr "Ежедневно"
|
||||||
|
|
||||||
|
#: django_q/models.py:278
|
||||||
|
msgid "Weekly"
|
||||||
|
msgstr "Еженедельно"
|
||||||
|
|
||||||
|
#: django_q/models.py:279
|
||||||
|
msgid "Biweekly"
|
||||||
|
msgstr "Раз в две недели"
|
||||||
|
|
||||||
|
#: django_q/models.py:280
|
||||||
|
msgid "Monthly"
|
||||||
|
msgstr "Ежемесячно"
|
||||||
|
|
||||||
|
#: django_q/models.py:281
|
||||||
|
msgid "Bimonthly"
|
||||||
|
msgstr "Раз в два месяца"
|
||||||
|
|
||||||
|
#: django_q/models.py:282
|
||||||
|
msgid "Quarterly"
|
||||||
|
msgstr "Ежеквартально"
|
||||||
|
|
||||||
|
#: django_q/models.py:283
|
||||||
|
msgid "Yearly"
|
||||||
|
msgstr "Ежегодно"
|
||||||
|
|
||||||
|
#: django_q/models.py:284 django_q/models.py:313
|
||||||
|
msgid "Cron"
|
||||||
|
msgstr "Cron"
|
||||||
|
|
||||||
|
#: django_q/models.py:290
|
||||||
|
msgid "Schedule Type"
|
||||||
|
msgstr "Тип расписания"
|
||||||
|
|
||||||
|
#: django_q/models.py:291
|
||||||
|
msgid "How often this task should be enqueued."
|
||||||
|
msgstr "Как часто ставить эту задачу в очередь."
|
||||||
|
|
||||||
|
#: django_q/models.py:297
|
||||||
|
msgid "Number of minutes for the Minutes type"
|
||||||
|
msgstr "Число минут для типа «Минуты»"
|
||||||
|
|
||||||
|
#: django_q/models.py:300
|
||||||
|
msgid "Repeats"
|
||||||
|
msgstr "Повторы"
|
||||||
|
|
||||||
|
#: django_q/models.py:300
|
||||||
|
msgid "n = n times, -1 = forever"
|
||||||
|
msgstr "n — число повторов, -1 — бесконечно"
|
||||||
|
|
||||||
|
#: django_q/models.py:303
|
||||||
|
msgid "Next Run"
|
||||||
|
msgstr "Следующий запуск"
|
||||||
|
|
||||||
|
#: django_q/models.py:304
|
||||||
|
msgid "When this schedule runs next (stored in UTC)."
|
||||||
|
msgstr "Когда следующий запуск по расписанию (в UTC)."
|
||||||
|
|
||||||
|
#: django_q/models.py:314
|
||||||
|
msgid "Cron expression"
|
||||||
|
msgstr "Cron-выражение"
|
||||||
|
|
||||||
|
#: django_q/models.py:320
|
||||||
|
msgid "Last task id"
|
||||||
|
msgstr "ID последней задачи"
|
||||||
|
|
||||||
|
#: django_q/models.py:321
|
||||||
|
msgid "Id of the last task spawned from this schedule (read-only)."
|
||||||
|
msgstr "Идентификатор последней задачи по этому расписанию (read-only)."
|
||||||
|
|
||||||
|
#: django_q/models.py:329 django_q/models.py:427
|
||||||
|
msgid "Name of the target cluster"
|
||||||
|
msgstr "Имя целевого кластера"
|
||||||
|
|
||||||
|
#: django_q/models.py:336
|
||||||
|
msgid "Intended date kwarg"
|
||||||
|
msgstr "Имя аргумента для даты запуска"
|
||||||
|
|
||||||
|
#: django_q/models.py:337
|
||||||
|
msgid "Name of kwarg to pass intended schedule date"
|
||||||
|
msgstr "Имя kwargs для передачи запланированной даты"
|
||||||
|
|
||||||
|
#: django_q/models.py:418
|
||||||
|
msgid "Scheduled task"
|
||||||
|
msgstr "Запланированная задача"
|
||||||
|
|
||||||
|
#: django_q/models.py:419
|
||||||
|
msgid "Scheduled tasks"
|
||||||
|
msgstr "Запланированные задачи"
|
||||||
|
|
||||||
|
#: django_q/models.py:426
|
||||||
|
msgid "Cluster key"
|
||||||
|
msgstr "Ключ кластера"
|
||||||
|
|
||||||
|
#: django_q/models.py:430
|
||||||
|
msgid "Payload"
|
||||||
|
msgstr "Данные задачи"
|
||||||
|
|
||||||
|
#: django_q/models.py:431
|
||||||
|
msgid "Signed serialized task package (do not edit manually)."
|
||||||
|
msgstr "Подписанный сериализованный пакет задачи (не редактировать вручную)."
|
||||||
|
|
||||||
|
#: django_q/models.py:435
|
||||||
|
msgid "Lock until"
|
||||||
|
msgstr "Блокировка до"
|
||||||
|
|
||||||
|
#: django_q/models.py:436
|
||||||
|
msgid "Prevent any cluster from pulling until"
|
||||||
|
msgstr "Не забирать задачи кластерами до"
|
||||||
|
|
||||||
|
#: django_q/models.py:474
|
||||||
|
msgid "Queue options"
|
||||||
|
msgstr "Дополнительные параметры очереди"
|
||||||
|
|
||||||
|
#: django_q/models.py:478
|
||||||
|
msgid "Queued task"
|
||||||
|
msgstr "Задача в очереди"
|
||||||
|
|
||||||
|
#: django_q/models.py:479
|
||||||
|
msgid "Queued tasks"
|
||||||
|
msgstr "Задачи в очереди"
|
||||||
|
|
||||||
|
#: django_q/monitor.py:41
|
||||||
|
#, python-format
|
||||||
|
msgid "%(name)s monitoring at %(id)s"
|
||||||
|
msgstr "%(name)s мониторинг на %(id)s"
|
||||||
|
|
||||||
|
#: django_q/monitor.py:61
|
||||||
|
#, python-format
|
||||||
|
msgid "Processed '%(info_name)s' (%(task_name)s)"
|
||||||
|
msgstr "Обработано «%(info_name)s» (%(task_name)s)"
|
||||||
|
|
||||||
|
#: django_q/monitor.py:67
|
||||||
|
#, python-format
|
||||||
|
msgid "Failed '%(info_name)s' (%(task_name)s) - %(task_result)s"
|
||||||
|
msgstr "Ошибка «%(info_name)s» (%(task_name)s) — %(task_result)s"
|
||||||
|
|
||||||
|
#: django_q/monitor.py:74
|
||||||
|
#, python-format
|
||||||
|
msgid "%(name)s stopped monitoring results"
|
||||||
|
msgstr "%(name)s прекратил отслеживание результатов"
|
||||||
|
|
||||||
|
#: django_q/monitor_terminal.py:64 django_q/monitor_terminal.py:348
|
||||||
|
msgid "Host"
|
||||||
|
msgstr "Хост"
|
||||||
|
|
||||||
|
#: django_q/monitor_terminal.py:68 django_q/monitor_terminal.py:352
|
||||||
|
#: django_q/monitor_terminal.py:457
|
||||||
|
msgid "Id"
|
||||||
|
msgstr "Id"
|
||||||
|
|
||||||
|
#: django_q/monitor_terminal.py:72
|
||||||
|
msgid "State"
|
||||||
|
msgstr "Состояние"
|
||||||
|
|
||||||
|
#: django_q/monitor_terminal.py:76
|
||||||
|
msgid "Pool"
|
||||||
|
msgstr "Пул"
|
||||||
|
|
||||||
|
#: django_q/monitor_terminal.py:80
|
||||||
|
msgid "TQ"
|
||||||
|
msgstr "TQ"
|
||||||
|
|
||||||
|
#: django_q/monitor_terminal.py:84
|
||||||
|
msgid "RQ"
|
||||||
|
msgstr "RQ"
|
||||||
|
|
||||||
|
#: django_q/monitor_terminal.py:88
|
||||||
|
msgid "RC"
|
||||||
|
msgstr "RC"
|
||||||
|
|
||||||
|
#: django_q/monitor_terminal.py:92
|
||||||
|
msgid "Up"
|
||||||
|
msgstr "Аптайм"
|
||||||
|
|
||||||
|
#: django_q/monitor_terminal.py:172 django_q/monitor_terminal.py:286
|
||||||
|
msgid "Queued"
|
||||||
|
msgstr "В очереди"
|
||||||
|
|
||||||
|
#: django_q/monitor_terminal.py:190 django_q/monitor_terminal.py:294
|
||||||
|
msgid "Failures"
|
||||||
|
msgstr "Сбои"
|
||||||
|
|
||||||
|
#: django_q/monitor_terminal.py:201 django_q/monitor_terminal.py:496
|
||||||
|
msgid "[Press q to quit]"
|
||||||
|
msgstr "[Нажмите q для выхода]"
|
||||||
|
|
||||||
|
#: django_q/monitor_terminal.py:227
|
||||||
|
msgid "day"
|
||||||
|
msgstr "день"
|
||||||
|
|
||||||
|
#: django_q/monitor_terminal.py:248
|
||||||
|
msgid "second"
|
||||||
|
msgstr "секунда"
|
||||||
|
|
||||||
|
#: django_q/monitor_terminal.py:251
|
||||||
|
msgid "minute"
|
||||||
|
msgstr "минута"
|
||||||
|
|
||||||
|
#: django_q/monitor_terminal.py:254
|
||||||
|
msgid "hour"
|
||||||
|
msgstr "час"
|
||||||
|
|
||||||
|
#: django_q/monitor_terminal.py:263
|
||||||
|
#, python-format
|
||||||
|
msgid "-- %(prefix)s %(version)s on %(info)s --"
|
||||||
|
msgstr "-- %(prefix)s %(version)s на %(info)s --"
|
||||||
|
|
||||||
|
#: django_q/monitor_terminal.py:273
|
||||||
|
msgid "Clusters"
|
||||||
|
msgstr "Кластеры"
|
||||||
|
|
||||||
|
#: django_q/monitor_terminal.py:277
|
||||||
|
msgid "Workers"
|
||||||
|
msgstr "Воркеры"
|
||||||
|
|
||||||
|
#: django_q/monitor_terminal.py:281
|
||||||
|
msgid "Restarts"
|
||||||
|
msgstr "Перезапуски"
|
||||||
|
|
||||||
|
#: django_q/monitor_terminal.py:290
|
||||||
|
msgid "Successes"
|
||||||
|
msgstr "Успехи"
|
||||||
|
|
||||||
|
#: django_q/monitor_terminal.py:299
|
||||||
|
msgid "Schedules"
|
||||||
|
msgstr "Расписания"
|
||||||
|
|
||||||
|
#: django_q/monitor_terminal.py:303
|
||||||
|
#, python-format
|
||||||
|
msgid "Tasks/%(per)s"
|
||||||
|
msgstr "Задач/%(per)s"
|
||||||
|
|
||||||
|
#: django_q/monitor_terminal.py:307
|
||||||
|
msgid "Avg time"
|
||||||
|
msgstr "Среднее время"
|
||||||
|
|
||||||
|
#: django_q/monitor_terminal.py:357
|
||||||
|
msgid "Available (%)"
|
||||||
|
msgstr "Доступно (%)"
|
||||||
|
|
||||||
|
#: django_q/monitor_terminal.py:363
|
||||||
|
msgid "Available (MB)"
|
||||||
|
msgstr "Доступно (МБ)"
|
||||||
|
|
||||||
|
#: django_q/monitor_terminal.py:368
|
||||||
|
msgid "Total (MB)"
|
||||||
|
msgstr "Всего (МБ)"
|
||||||
|
|
||||||
|
#: django_q/monitor_terminal.py:373
|
||||||
|
msgid "Sentinel (MB)"
|
||||||
|
msgstr "Sentinel (МБ)"
|
||||||
|
|
||||||
|
#: django_q/monitor_terminal.py:379
|
||||||
|
msgid "Monitor (MB)"
|
||||||
|
msgstr "Монитор (МБ)"
|
||||||
|
|
||||||
|
#: django_q/monitor_terminal.py:385
|
||||||
|
msgid "Workers (MB)"
|
||||||
|
msgstr "Воркеры (МБ)"
|
||||||
|
|
||||||
|
#: django_q/monitor_terminal.py:485
|
||||||
|
#, python-format
|
||||||
|
msgid "Available lowest (): %(memory_percent)s ((at)s)"
|
||||||
|
msgstr "Минимум доступно (): %(memory_percent)s ((at)s)"
|
||||||
|
|
||||||
|
#: django_q/monitor_terminal.py:507
|
||||||
|
msgid "No clusters appear to be running."
|
||||||
|
msgstr "Похоже, ни один кластер не запущен."
|
||||||
|
|
||||||
|
#: django_q/pusher.py:40
|
||||||
|
#, python-format
|
||||||
|
msgid "%(name)s pushing tasks at %(id)s"
|
||||||
|
msgstr "%(name)s отправляет задачи на %(id)s"
|
||||||
|
|
||||||
|
#: django_q/pusher.py:67
|
||||||
|
#, python-format
|
||||||
|
msgid "queueing from %(list_key)s"
|
||||||
|
msgstr "очередь из %(list_key)s"
|
||||||
|
|
||||||
|
#: django_q/pusher.py:71
|
||||||
|
#, python-format
|
||||||
|
msgid "%(name)s stopped pushing tasks"
|
||||||
|
msgstr "%(name)s прекратил отправку задач"
|
||||||
|
|
||||||
|
#: django_q/scheduler.py:110
|
||||||
|
#, python-format
|
||||||
|
msgid "%(process_name)s failed to create a task from schedule [%(schedule)s]"
|
||||||
|
msgstr ""
|
||||||
|
"%(process_name)s не удалось создать задачу по расписанию [%(schedule)s]"
|
||||||
|
|
||||||
|
#: django_q/scheduler.py:121
|
||||||
|
#, python-format
|
||||||
|
msgid ""
|
||||||
|
"%(process_name)s created task %(task_name)s from schedule [%(schedule)s]"
|
||||||
|
msgstr ""
|
||||||
|
"%(process_name)s создал задачу %(task_name)s по расписанию [%(schedule)s]"
|
||||||
|
|
||||||
|
#: django_q/signals.py:22
|
||||||
|
#, python-format
|
||||||
|
msgid "malformed return hook '%(hook)s' for [%(name)s]"
|
||||||
|
msgstr "некорректный return hook «%(hook)s» для [%(name)s]"
|
||||||
|
|
||||||
|
#: django_q/signals.py:30
|
||||||
|
#, python-format
|
||||||
|
msgid "return hook %(hook)s failed on [%(name)s] because %(error)s"
|
||||||
|
msgstr "return hook %(hook)s для [%(name)s] завершился ошибкой: %(error)s"
|
||||||
|
|
||||||
|
#: django_q/timeout.py:30 django_q/timeout.py:43
|
||||||
|
msgid "SIGALARM is not available on your platform"
|
||||||
|
msgstr "SIGALRM недоступен на вашей платформе"
|
||||||
|
|
||||||
|
#: django_q/worker.py:49
|
||||||
|
#, python-format
|
||||||
|
msgid "%(proc_name)s ready for work at %(id)s"
|
||||||
|
msgstr "%(proc_name)s готов к работе на %(id)s"
|
||||||
|
|
||||||
|
#: django_q/worker.py:69
|
||||||
|
#, python-format
|
||||||
|
msgid "%(proc_name)s processing %(task_name)s '%(func_name)s'"
|
||||||
|
msgstr "%(proc_name)s выполняет %(task_name)s «%(func_name)s»"
|
||||||
|
|
||||||
|
#: django_q/worker.py:135
|
||||||
|
#, python-format
|
||||||
|
msgid "%(proc_name)s stopped doing work"
|
||||||
|
msgstr "%(proc_name)s прекратил работу"
|
||||||
|
|
||||||
|
#, python-format
|
||||||
|
#~ msgid ""
|
||||||
|
#~ "Could not process '%(func_name)s'. Check the location of the function and "
|
||||||
|
#~ "the args/kwargs."
|
||||||
|
#~ msgstr ""
|
||||||
|
#~ "Не удалось обработать «%(func_name)s». Проверьте путь к функции и args/"
|
||||||
|
#~ "kwargs."
|
||||||
@@ -8,7 +8,7 @@ msgid ""
|
|||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: \n"
|
"Project-Id-Version: \n"
|
||||||
"Report-Msgid-Bugs-To: \n"
|
"Report-Msgid-Bugs-To: \n"
|
||||||
"POT-Creation-Date: 2023-01-26 01:38+0000\n"
|
"POT-Creation-Date: 2026-04-17 21:10+0000\n"
|
||||||
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
||||||
"Last-Translator: Ethem Güner <ethemguener@gmail.com>\n"
|
"Last-Translator: Ethem Güner <ethemguener@gmail.com>\n"
|
||||||
"Language-Team: \n"
|
"Language-Team: \n"
|
||||||
@@ -18,36 +18,44 @@ msgstr ""
|
|||||||
"Content-Transfer-Encoding: 8bit\n"
|
"Content-Transfer-Encoding: 8bit\n"
|
||||||
"Plural-Forms: nplurals=2; plural=(n > 1);\n"
|
"Plural-Forms: nplurals=2; plural=(n > 1);\n"
|
||||||
|
|
||||||
#: admin.py:43
|
#: admin.py:30
|
||||||
msgid "Resubmit selected tasks to queue"
|
msgid "Resubmit selected tasks to queue"
|
||||||
msgstr "Seçili işleri kuyruğa tekrar gönder"
|
msgstr "Seçili işleri kuyruğa tekrar gönder"
|
||||||
|
|
||||||
#: admin.py:107 models.py:293
|
#: admin.py:64
|
||||||
|
msgid "Time Taken"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: admin.py:95
|
||||||
|
msgid "Short result"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: admin.py:142 models.py:412
|
||||||
#, fuzzy
|
#, fuzzy
|
||||||
#| msgid "Success"
|
#| msgid "Success"
|
||||||
msgid "success"
|
msgid "success"
|
||||||
msgstr "başarılı olanlar"
|
msgstr "başarılı olanlar"
|
||||||
|
|
||||||
#: admin.py:119 models.py:295
|
#: admin.py:154 models.py:414
|
||||||
msgid "last_run"
|
msgid "last_run"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: cluster.py:79
|
#: cluster.py:75
|
||||||
#, python-format
|
#, python-format
|
||||||
msgid "Q Cluster %(name)s starting."
|
msgid "Q Cluster %(name)s starting."
|
||||||
msgstr "Q Cluster %(name)s başlatılıyor."
|
msgstr "Q Cluster %(name)s başlatılıyor."
|
||||||
|
|
||||||
#: cluster.py:87
|
#: cluster.py:83
|
||||||
#, python-format
|
#, python-format
|
||||||
msgid "Q Cluster %(name)s stopping."
|
msgid "Q Cluster %(name)s stopping."
|
||||||
msgstr "Q Cluster %(name)s durduruluyor."
|
msgstr "Q Cluster %(name)s durduruluyor."
|
||||||
|
|
||||||
#: cluster.py:90
|
#: cluster.py:86
|
||||||
#, python-format
|
#, python-format
|
||||||
msgid "Q Cluster %(name)s has stopped."
|
msgid "Q Cluster %(name)s has stopped."
|
||||||
msgstr "Q Cluster %(name)s durduruldu."
|
msgstr "Q Cluster %(name)s durduruldu."
|
||||||
|
|
||||||
#: cluster.py:97
|
#: cluster.py:93
|
||||||
#, python-format
|
#, python-format
|
||||||
msgid "%(name)s got signal %(signal)s"
|
msgid "%(name)s got signal %(signal)s"
|
||||||
msgstr "%(name)s, %(signal)s pid'inde izleniyor/monitoring yapılıyor."
|
msgstr "%(name)s, %(signal)s pid'inde izleniyor/monitoring yapılıyor."
|
||||||
@@ -62,7 +70,7 @@ msgstr "Monitor %(name)s ani ölüm sonrası tekrar dirildi"
|
|||||||
msgid "reincarnated pusher %(name)s after sudden death"
|
msgid "reincarnated pusher %(name)s after sudden death"
|
||||||
msgstr "Pusher %(name)s ani ölüm sonrası tekrar dirildi"
|
msgstr "Pusher %(name)s ani ölüm sonrası tekrar dirildi"
|
||||||
|
|
||||||
#: cluster.py:250
|
#: cluster.py:262
|
||||||
#, fuzzy, python-format
|
#, fuzzy, python-format
|
||||||
#| msgid "reincarnated worker %(name)s after timeout"
|
#| msgid "reincarnated worker %(name)s after timeout"
|
||||||
msgid ""
|
msgid ""
|
||||||
@@ -70,119 +78,55 @@ msgid ""
|
|||||||
"%(task_name)s"
|
"%(task_name)s"
|
||||||
msgstr "Worker %(name)s zaman aşımı sonrası tekrar dirildi"
|
msgstr "Worker %(name)s zaman aşımı sonrası tekrar dirildi"
|
||||||
|
|
||||||
#: cluster.py:255
|
#: cluster.py:265
|
||||||
#, python-format
|
#, python-format
|
||||||
msgid "reincarnated worker %(name)s after timeout"
|
msgid "reincarnated worker %(name)s after timeout"
|
||||||
msgstr "Worker %(name)s zaman aşımı sonrası tekrar dirildi"
|
msgstr "Worker %(name)s zaman aşımı sonrası tekrar dirildi"
|
||||||
|
|
||||||
#: cluster.py:260
|
#: cluster.py:270
|
||||||
#, python-format
|
#, python-format
|
||||||
msgid "recycled worker %(name)s"
|
msgid "recycled worker %(name)s"
|
||||||
msgstr "Worker %(name)s geri döndürüldü"
|
msgstr "Worker %(name)s geri döndürüldü"
|
||||||
|
|
||||||
#: cluster.py:263
|
#: cluster.py:273
|
||||||
#, python-format
|
#, python-format
|
||||||
msgid "reincarnated worker %(name)s after death"
|
msgid "reincarnated worker %(name)s after death"
|
||||||
msgstr "Worker %(name)s ani ölüm sonrası tekrar dirildi"
|
msgstr "Worker %(name)s ani ölüm sonrası tekrar dirildi"
|
||||||
|
|
||||||
#: cluster.py:287
|
#: cluster.py:297
|
||||||
#, python-format
|
#, python-format
|
||||||
msgid "%(name)s guarding cluster %(cluster_name)s"
|
msgid "%(name)s guarding cluster %(cluster_name)s"
|
||||||
msgstr "%(name)s, %(cluster_name)s cluster'ını koruyor"
|
msgstr "%(name)s, %(cluster_name)s cluster'ını koruyor"
|
||||||
|
|
||||||
#: cluster.py:296
|
#: cluster.py:307
|
||||||
#, python-format
|
#, python-format
|
||||||
msgid "Q Cluster %(cluster_name)s running."
|
msgid "Q Cluster %(cluster_name)s running."
|
||||||
msgstr "Q Cluster %(cluster_name)s başlatılıyor."
|
msgstr "Q Cluster %(cluster_name)s başlatılıyor."
|
||||||
|
|
||||||
#: cluster.py:332
|
#: cluster.py:346
|
||||||
#, python-format
|
#, python-format
|
||||||
msgid "%(name)s stopping cluster processes"
|
msgid "%(name)s stopping cluster processes"
|
||||||
msgstr "Cluster %(name)s işlemleri durduruluyor."
|
msgstr "Cluster %(name)s işlemleri durduruluyor."
|
||||||
|
|
||||||
#: cluster.py:357
|
#: cluster.py:371
|
||||||
#, python-format
|
#, python-format
|
||||||
msgid "%(name)s waiting for the monitor."
|
msgid "%(name)s waiting for the monitor."
|
||||||
msgstr "%(name)s monitor için bekliyor."
|
msgstr "%(name)s monitor için bekliyor."
|
||||||
|
|
||||||
#: cluster.py:383
|
#: cluster.py:394
|
||||||
#, fuzzy, python-format
|
|
||||||
#| msgid "%(process_name)s pushing tasks at %(id)s"
|
|
||||||
msgid "%(name)s pushing tasks at %(id)s"
|
|
||||||
msgstr "%(process_name)s, işleri %(id)s pid'ine gönderiyor."
|
|
||||||
|
|
||||||
#: cluster.py:407
|
|
||||||
#, python-format
|
|
||||||
msgid "queueing from %(list_key)s"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: cluster.py:411
|
|
||||||
#, python-format
|
|
||||||
msgid "%(name)s stopped pushing tasks"
|
|
||||||
msgstr "%(name)s işleri göndermeyi durdurdu"
|
|
||||||
|
|
||||||
#: cluster.py:426
|
|
||||||
#, python-format
|
|
||||||
msgid "%(name)s monitoring at %(id)s"
|
|
||||||
msgstr "%(name)s, %(id)s pid'inde izleniyor/monitoring yapılıyor."
|
|
||||||
|
|
||||||
#: cluster.py:445
|
|
||||||
#, python-format
|
|
||||||
msgid "Processed '%(info_name)s' (%(task_name)s)"
|
|
||||||
msgstr "[%(task_name)s] - '%(info_name)s işlendi."
|
|
||||||
|
|
||||||
#: cluster.py:451
|
|
||||||
#, python-format
|
|
||||||
msgid "Failed '%(info_name)s' (%(task_name)s) - %(task_result)s"
|
|
||||||
msgstr "[%(task_name)s] - '%(info_name)s' - %(task_result)s başarısız oldu"
|
|
||||||
|
|
||||||
#: cluster.py:458
|
|
||||||
#, python-format
|
|
||||||
msgid "%(name)s stopped monitoring results"
|
|
||||||
msgstr "%(name)s sonuçları göstermeyi bıraktı"
|
|
||||||
|
|
||||||
#: cluster.py:474
|
|
||||||
#, python-format
|
|
||||||
msgid "%(proc_name)s ready for work at %(id)s"
|
|
||||||
msgstr "%(proc_name)s, %(id)s pid'inde çalışmaya hazır"
|
|
||||||
|
|
||||||
#: cluster.py:494
|
|
||||||
#, fuzzy, python-format
|
|
||||||
#| msgid "%(proc_name)s processing '%(func_name)s' (%(task_name)s)"
|
|
||||||
msgid "%(proc_name)s processing %(task_name)s '%(func_name)s'"
|
|
||||||
msgstr "%(proc_name)s, '%(func_name)s' [%(task_name)s] işlerini işiyor"
|
|
||||||
|
|
||||||
#: cluster.py:546
|
|
||||||
#, python-format
|
|
||||||
msgid "%(proc_name)s stopped doing work"
|
|
||||||
msgstr "%(proc_name)s çalışmayı bıraktı"
|
|
||||||
|
|
||||||
#: cluster.py:751
|
|
||||||
#, python-format
|
|
||||||
msgid "%(process_name)s failed to create a task from schedule [%(schedule)s]"
|
|
||||||
msgstr "%(process_name)s programdan bir görev oluşturamadı [%(schedule)s]"
|
|
||||||
|
|
||||||
#: cluster.py:762
|
|
||||||
#, fuzzy, python-format
|
|
||||||
#| msgid "%(process_name)s created a task from schedule [%(schedule)s]"
|
|
||||||
msgid ""
|
|
||||||
"%(process_name)s created task %(task_name)s from schedule [%(schedule)s]"
|
|
||||||
msgstr "%(process_name)s programdan bir görev oluşturamadı [%(schedule)s]"
|
|
||||||
|
|
||||||
#: cluster.py:808
|
|
||||||
msgid "Skipping cpu affinity because psutil was not found."
|
msgid "Skipping cpu affinity because psutil was not found."
|
||||||
msgstr "Psutil bulunamadığı için cpu benzeşimi atlanıyor."
|
msgstr "Psutil bulunamadığı için cpu benzeşimi atlanıyor."
|
||||||
|
|
||||||
#: cluster.py:813
|
#: cluster.py:399
|
||||||
msgid "Faking cpu affinity because it is not supported on this platform"
|
msgid "Faking cpu affinity because it is not supported on this platform"
|
||||||
msgstr "Bu platformda desteklenmediği için sahte cpu benzeşimi"
|
msgstr "Bu platformda desteklenmediği için sahte cpu benzeşimi"
|
||||||
|
|
||||||
#: cluster.py:835
|
#: cluster.py:421
|
||||||
#, python-format
|
#, python-format
|
||||||
msgid "%(pid)s will use cpu %(affinity)s"
|
msgid "%(pid)s will use cpu %(affinity)s"
|
||||||
msgstr "%(pid)s cpu %(affinity)s kullanacaktır"
|
msgstr "%(pid)s cpu %(affinity)s kullanacaktır"
|
||||||
|
|
||||||
#: conf.py:90
|
#: conf.py:122
|
||||||
#, python-format
|
#, python-format
|
||||||
msgid ""
|
msgid ""
|
||||||
"SAVE_LIMIT_PER (%(option)s) is not a valid option. Options are: 'group', "
|
"SAVE_LIMIT_PER (%(option)s) is not a valid option. Options are: 'group', "
|
||||||
@@ -192,28 +136,28 @@ msgstr ""
|
|||||||
"'group', 'name', 'func' ve None. Varsayılan değer None'dır."
|
"'group', 'name', 'func' ve None. Varsayılan değer None'dır."
|
||||||
|
|
||||||
#. Translators: Cluster status descriptions
|
#. Translators: Cluster status descriptions
|
||||||
#: conf.py:207
|
#: conf.py:239
|
||||||
msgid "Starting"
|
msgid "Starting"
|
||||||
msgstr "Başlıyor"
|
msgstr "Başlıyor"
|
||||||
|
|
||||||
#: conf.py:208
|
#: conf.py:240
|
||||||
msgid "Working"
|
msgid "Working"
|
||||||
msgstr "Çalışıyor"
|
msgstr "Çalışıyor"
|
||||||
|
|
||||||
#: conf.py:209
|
#: conf.py:241
|
||||||
msgid "Idle"
|
msgid "Idle"
|
||||||
msgstr "Boşta"
|
msgstr "Boşta"
|
||||||
|
|
||||||
#: conf.py:210
|
#: conf.py:242
|
||||||
msgid "Stopped"
|
msgid "Stopped"
|
||||||
msgstr "Durdu"
|
msgstr "Durdu"
|
||||||
|
|
||||||
#: conf.py:211
|
#: conf.py:243
|
||||||
msgid "Stopping"
|
msgid "Stopping"
|
||||||
msgstr "Durduruluyor"
|
msgstr "Durduruluyor"
|
||||||
|
|
||||||
#. Translators: help text for qcluster management command
|
#. Translators: help text for qcluster management command
|
||||||
#: management/commands/qcluster.py:9
|
#: management/commands/qcluster.py:11
|
||||||
msgid "Starts a Django Q Cluster."
|
msgid "Starts a Django Q Cluster."
|
||||||
msgstr "Bir Django Q Cluster çalıştırır."
|
msgstr "Bir Django Q Cluster çalıştırır."
|
||||||
|
|
||||||
@@ -232,257 +176,475 @@ msgstr "Q Cluster'ın bellek kullanımını izler"
|
|||||||
msgid "Monitors Q Cluster activity"
|
msgid "Monitors Q Cluster activity"
|
||||||
msgstr "Q Cluster'ın aktivitelerini izler"
|
msgstr "Q Cluster'ın aktivitelerini izler"
|
||||||
|
|
||||||
#: models.py:125
|
#: models.py:30 models.py:469
|
||||||
|
msgid "Task id"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: models.py:31
|
||||||
|
msgid "32-character task identifier."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: models.py:36 models.py:235 models.py:470
|
||||||
|
msgid "Name"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: models.py:37
|
||||||
|
msgid "Optional human-readable name for lookup and display."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: models.py:41 models.py:240 models.py:468
|
||||||
|
msgid "Function"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: models.py:42
|
||||||
|
msgid "Dotted import path to the callable, e.g. myapp.tasks.job."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: models.py:47 models.py:247
|
||||||
|
msgid "Hook"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: models.py:48
|
||||||
|
msgid "Optional dotted path to a callback that receives the task result."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: models.py:53 models.py:253 models.py:472
|
||||||
|
msgid "Arguments"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: models.py:54
|
||||||
|
msgid "Pickled positional arguments (tuple)."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: models.py:59 models.py:259 models.py:473
|
||||||
|
msgid "Keyword arguments"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: models.py:60
|
||||||
|
msgid "Pickled keyword arguments (dict)."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: models.py:65
|
||||||
|
msgid "Result"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: models.py:66
|
||||||
|
msgid "Pickled return value or error payload."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: models.py:72 models.py:471
|
||||||
|
msgid "Group"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: models.py:73
|
||||||
|
msgid "Optional group id to aggregate related tasks."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: models.py:80 models.py:328
|
||||||
|
msgid "Cluster"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: models.py:81
|
||||||
|
msgid "Name of the cluster that executed this task."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: models.py:85
|
||||||
|
msgid "Started at"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: models.py:86
|
||||||
|
msgid "When the worker started executing the task."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: models.py:90
|
||||||
|
#, fuzzy
|
||||||
|
#| msgid "Stopped"
|
||||||
|
msgid "Stopped at"
|
||||||
|
msgstr "Durdu"
|
||||||
|
|
||||||
|
#: models.py:91
|
||||||
|
msgid "When the worker finished (success or failure)."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: models.py:96 monitor_terminal.py:180
|
||||||
|
msgid "Success"
|
||||||
|
msgstr "Başarılı olanlar"
|
||||||
|
|
||||||
|
#: models.py:97
|
||||||
|
msgid "False if the task raised an exception or timed out."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: models.py:101
|
||||||
|
msgid "Attempt count"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: models.py:102
|
||||||
|
msgid "How many times execution was attempted."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: models.py:172
|
||||||
|
msgid "Task"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: models.py:173
|
||||||
|
msgid "Tasks"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: models.py:194
|
||||||
msgid "Successful task"
|
msgid "Successful task"
|
||||||
msgstr "Başarılı iş"
|
msgstr "Başarılı iş"
|
||||||
|
|
||||||
#: models.py:126
|
#: models.py:195
|
||||||
msgid "Successful tasks"
|
msgid "Successful tasks"
|
||||||
msgstr "Başarılı işler"
|
msgstr "Başarılı işler"
|
||||||
|
|
||||||
#: models.py:141
|
#: models.py:210
|
||||||
msgid "Failed task"
|
msgid "Failed task"
|
||||||
msgstr "Başarısız iş"
|
msgstr "Başarısız iş"
|
||||||
|
|
||||||
#: models.py:142
|
#: models.py:211
|
||||||
msgid "Failed tasks"
|
msgid "Failed tasks"
|
||||||
msgstr "Başarısız işler"
|
msgstr "Başarısız işler"
|
||||||
|
|
||||||
#: models.py:150 models.py:234
|
#: models.py:219 models.py:347
|
||||||
msgid "Please install croniter to enable cron expressions"
|
msgid "Please install croniter to enable cron expressions"
|
||||||
msgstr "Cron expressions'ları açmak için croniter yükleyin"
|
msgstr "Cron expressions'ları açmak için croniter yükleyin"
|
||||||
|
|
||||||
#: models.py:170
|
#: models.py:236
|
||||||
|
msgid "Optional label to identify this schedule in the admin."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: models.py:241
|
||||||
|
msgid "e.g. module.tasks.function"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: models.py:248
|
||||||
|
msgid "e.g. module.tasks.result_function"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: models.py:254
|
||||||
msgid "e.g. 1, 2, 'John'"
|
msgid "e.g. 1, 2, 'John'"
|
||||||
msgstr "Örneğin: 1, 2, 'Melih'"
|
msgstr "Örneğin: 1, 2, 'Melih'"
|
||||||
|
|
||||||
#: models.py:172
|
#: models.py:260
|
||||||
msgid "e.g. x=1, y=2, name='John'"
|
msgid "e.g. x=1, y=2, name='John'"
|
||||||
msgstr "Örneğin: x=1, y=2, name='Melih'"
|
msgstr "Örneğin: x=1, y=2, name='Melih'"
|
||||||
|
|
||||||
#: models.py:186
|
#: models.py:274
|
||||||
msgid "Once"
|
msgid "Once"
|
||||||
msgstr "Bir kere"
|
msgstr "Bir kere"
|
||||||
|
|
||||||
#: models.py:187
|
#: models.py:275 models.py:296
|
||||||
msgid "Minutes"
|
msgid "Minutes"
|
||||||
msgstr "Dakika"
|
msgstr "Dakika"
|
||||||
|
|
||||||
#: models.py:188
|
#: models.py:276
|
||||||
msgid "Hourly"
|
msgid "Hourly"
|
||||||
msgstr "Saatlik"
|
msgstr "Saatlik"
|
||||||
|
|
||||||
#: models.py:189
|
#: models.py:277
|
||||||
msgid "Daily"
|
msgid "Daily"
|
||||||
msgstr "Günlük"
|
msgstr "Günlük"
|
||||||
|
|
||||||
#: models.py:190
|
#: models.py:278
|
||||||
msgid "Weekly"
|
msgid "Weekly"
|
||||||
msgstr "Haftalık"
|
msgstr "Haftalık"
|
||||||
|
|
||||||
#: models.py:191
|
#: models.py:279
|
||||||
#, fuzzy
|
#, fuzzy
|
||||||
#| msgid "Weekly"
|
#| msgid "Weekly"
|
||||||
msgid "Biweekly"
|
msgid "Biweekly"
|
||||||
msgstr "İki haftada bir"
|
msgstr "İki haftada bir"
|
||||||
|
|
||||||
#: models.py:192
|
#: models.py:280
|
||||||
msgid "Monthly"
|
msgid "Monthly"
|
||||||
msgstr "Aylık"
|
msgstr "Aylık"
|
||||||
|
|
||||||
#: models.py:193
|
#: models.py:281
|
||||||
#, fuzzy
|
#, fuzzy
|
||||||
#| msgid "Monthly"
|
#| msgid "Monthly"
|
||||||
msgid "Bimonthly"
|
msgid "Bimonthly"
|
||||||
msgstr "İki ayda bir"
|
msgstr "İki ayda bir"
|
||||||
|
|
||||||
#: models.py:194
|
#: models.py:282
|
||||||
msgid "Quarterly"
|
msgid "Quarterly"
|
||||||
msgstr "Bir Çeyrek (3 Ay)"
|
msgstr "Bir Çeyrek (3 Ay)"
|
||||||
|
|
||||||
#: models.py:195
|
#: models.py:283
|
||||||
msgid "Yearly"
|
msgid "Yearly"
|
||||||
msgstr "Yıllık"
|
msgstr "Yıllık"
|
||||||
|
|
||||||
#: models.py:196
|
#: models.py:284 models.py:313
|
||||||
msgid "Cron"
|
msgid "Cron"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: models.py:199
|
#: models.py:290
|
||||||
msgid "Schedule Type"
|
msgid "Schedule Type"
|
||||||
msgstr "Zamanlama Tipi"
|
msgstr "Zamanlama Tipi"
|
||||||
|
|
||||||
#: models.py:202
|
#: models.py:291
|
||||||
|
msgid "How often this task should be enqueued."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: models.py:297
|
||||||
msgid "Number of minutes for the Minutes type"
|
msgid "Number of minutes for the Minutes type"
|
||||||
msgstr "Dakika tipine göre dakika sayısı"
|
msgstr "Dakika tipine göre dakika sayısı"
|
||||||
|
|
||||||
#: models.py:205
|
#: models.py:300
|
||||||
msgid "Repeats"
|
msgid "Repeats"
|
||||||
msgstr "Tekrar eder"
|
msgstr "Tekrar eder"
|
||||||
|
|
||||||
#: models.py:205
|
#: models.py:300
|
||||||
msgid "n = n times, -1 = forever"
|
msgid "n = n times, -1 = forever"
|
||||||
msgstr "n = n kere, -1 = sonsuza kadar"
|
msgstr "n = n kere, -1 = sonsuza kadar"
|
||||||
|
|
||||||
#: models.py:208
|
#: models.py:303
|
||||||
msgid "Next Run"
|
msgid "Next Run"
|
||||||
msgstr "Bir dahaki çalışma tarihi"
|
msgstr "Bir dahaki çalışma tarihi"
|
||||||
|
|
||||||
#: models.py:215
|
#: models.py:304
|
||||||
|
msgid "When this schedule runs next (stored in UTC)."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: models.py:314
|
||||||
msgid "Cron expression"
|
msgid "Cron expression"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: models.py:224
|
#: models.py:320
|
||||||
|
msgid "Last task id"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: models.py:321
|
||||||
|
msgid "Id of the last task spawned from this schedule (read-only)."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: models.py:329 models.py:427
|
||||||
|
msgid "Name of the target cluster"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: models.py:336
|
||||||
|
msgid "Intended date kwarg"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: models.py:337
|
||||||
msgid "Name of kwarg to pass intended schedule date"
|
msgid "Name of kwarg to pass intended schedule date"
|
||||||
msgstr "Geçilecek kwarg'ın adı öngörülen program tarihi"
|
msgstr "Geçilecek kwarg'ın adı öngörülen program tarihi"
|
||||||
|
|
||||||
#: models.py:299
|
#: models.py:418
|
||||||
msgid "Scheduled task"
|
msgid "Scheduled task"
|
||||||
msgstr "Zamanlanmış iş"
|
msgstr "Zamanlanmış iş"
|
||||||
|
|
||||||
#: models.py:300
|
#: models.py:419
|
||||||
msgid "Scheduled tasks"
|
msgid "Scheduled tasks"
|
||||||
msgstr "Zamanlanmış işler"
|
msgstr "Zamanlanmış işler"
|
||||||
|
|
||||||
#: models.py:326
|
#: models.py:426
|
||||||
|
msgid "Cluster key"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: models.py:430
|
||||||
|
msgid "Payload"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: models.py:431
|
||||||
|
msgid "Signed serialized task package (do not edit manually)."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: models.py:435
|
||||||
|
msgid "Lock until"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: models.py:436
|
||||||
|
msgid "Prevent any cluster from pulling until"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: models.py:474
|
||||||
|
#, fuzzy
|
||||||
|
#| msgid "Queued task"
|
||||||
|
msgid "Queue options"
|
||||||
|
msgstr "Sıraya alınmış iş"
|
||||||
|
|
||||||
|
#: models.py:478
|
||||||
msgid "Queued task"
|
msgid "Queued task"
|
||||||
msgstr "Sıraya alınmış iş"
|
msgstr "Sıraya alınmış iş"
|
||||||
|
|
||||||
#: models.py:327
|
#: models.py:479
|
||||||
msgid "Queued tasks"
|
msgid "Queued tasks"
|
||||||
msgstr "Sıraya alınmış işler"
|
msgstr "Sıraya alınmış işler"
|
||||||
|
|
||||||
#: monitor.py:64 monitor.py:348
|
#: monitor.py:41
|
||||||
|
#, python-format
|
||||||
|
msgid "%(name)s monitoring at %(id)s"
|
||||||
|
msgstr "%(name)s, %(id)s pid'inde izleniyor/monitoring yapılıyor."
|
||||||
|
|
||||||
|
#: monitor.py:61
|
||||||
|
#, python-format
|
||||||
|
msgid "Processed '%(info_name)s' (%(task_name)s)"
|
||||||
|
msgstr "[%(task_name)s] - '%(info_name)s işlendi."
|
||||||
|
|
||||||
|
#: monitor.py:67
|
||||||
|
#, python-format
|
||||||
|
msgid "Failed '%(info_name)s' (%(task_name)s) - %(task_result)s"
|
||||||
|
msgstr "[%(task_name)s] - '%(info_name)s' - %(task_result)s başarısız oldu"
|
||||||
|
|
||||||
|
#: monitor.py:74
|
||||||
|
#, python-format
|
||||||
|
msgid "%(name)s stopped monitoring results"
|
||||||
|
msgstr "%(name)s sonuçları göstermeyi bıraktı"
|
||||||
|
|
||||||
|
#: monitor_terminal.py:64 monitor_terminal.py:348
|
||||||
msgid "Host"
|
msgid "Host"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: monitor.py:68 monitor.py:352 monitor.py:459
|
#: monitor_terminal.py:68 monitor_terminal.py:352 monitor_terminal.py:457
|
||||||
msgid "Id"
|
msgid "Id"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: monitor.py:72
|
#: monitor_terminal.py:72
|
||||||
msgid "State"
|
msgid "State"
|
||||||
msgstr "Durum"
|
msgstr "Durum"
|
||||||
|
|
||||||
#: monitor.py:76
|
#: monitor_terminal.py:76
|
||||||
msgid "Pool"
|
msgid "Pool"
|
||||||
msgstr "Havuz"
|
msgstr "Havuz"
|
||||||
|
|
||||||
#: monitor.py:80
|
#: monitor_terminal.py:80
|
||||||
msgid "TQ"
|
msgid "TQ"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: monitor.py:84
|
#: monitor_terminal.py:84
|
||||||
msgid "RQ"
|
msgid "RQ"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: monitor.py:88
|
#: monitor_terminal.py:88
|
||||||
msgid "RC"
|
msgid "RC"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: monitor.py:92
|
#: monitor_terminal.py:92
|
||||||
msgid "Up"
|
msgid "Up"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: monitor.py:172 monitor.py:286
|
#: monitor_terminal.py:172 monitor_terminal.py:286
|
||||||
msgid "Queued"
|
msgid "Queued"
|
||||||
msgstr "Sıraya alınmış"
|
msgstr "Sıraya alınmış"
|
||||||
|
|
||||||
#: monitor.py:180
|
#: monitor_terminal.py:190 monitor_terminal.py:294
|
||||||
msgid "Success"
|
|
||||||
msgstr "Başarılı olanlar"
|
|
||||||
|
|
||||||
#: monitor.py:190 monitor.py:294
|
|
||||||
msgid "Failures"
|
msgid "Failures"
|
||||||
msgstr "Başarısız olanlar"
|
msgstr "Başarısız olanlar"
|
||||||
|
|
||||||
#: monitor.py:201 monitor.py:498
|
#: monitor_terminal.py:201 monitor_terminal.py:496
|
||||||
msgid "[Press q to quit]"
|
msgid "[Press q to quit]"
|
||||||
msgstr "[Çıkmak için q'ya basın]"
|
msgstr "[Çıkmak için q'ya basın]"
|
||||||
|
|
||||||
#: monitor.py:227
|
#: monitor_terminal.py:227
|
||||||
msgid "day"
|
msgid "day"
|
||||||
msgstr "gün"
|
msgstr "gün"
|
||||||
|
|
||||||
#: monitor.py:248
|
#: monitor_terminal.py:248
|
||||||
msgid "second"
|
msgid "second"
|
||||||
msgstr "saniye"
|
msgstr "saniye"
|
||||||
|
|
||||||
#: monitor.py:251
|
#: monitor_terminal.py:251
|
||||||
msgid "minute"
|
msgid "minute"
|
||||||
msgstr "dakika"
|
msgstr "dakika"
|
||||||
|
|
||||||
#: monitor.py:254
|
#: monitor_terminal.py:254
|
||||||
msgid "hour"
|
msgid "hour"
|
||||||
msgstr "saat"
|
msgstr "saat"
|
||||||
|
|
||||||
#: monitor.py:263
|
#: monitor_terminal.py:263
|
||||||
#, python-format
|
#, python-format
|
||||||
msgid "-- %(prefix)s %(version)s on %(info)s --"
|
msgid "-- %(prefix)s %(version)s on %(info)s --"
|
||||||
msgstr "-- %(prefix)s %(version)s üzerinde %(info)s --"
|
msgstr "-- %(prefix)s %(version)s üzerinde %(info)s --"
|
||||||
|
|
||||||
#: monitor.py:273
|
#: monitor_terminal.py:273
|
||||||
msgid "Clusters"
|
msgid "Clusters"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: monitor.py:277
|
#: monitor_terminal.py:277
|
||||||
msgid "Workers"
|
msgid "Workers"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: monitor.py:281
|
#: monitor_terminal.py:281
|
||||||
msgid "Restarts"
|
msgid "Restarts"
|
||||||
msgstr "Yeniden çalıştırmalar"
|
msgstr "Yeniden çalıştırmalar"
|
||||||
|
|
||||||
#: monitor.py:290
|
#: monitor_terminal.py:290
|
||||||
msgid "Successes"
|
msgid "Successes"
|
||||||
msgstr "Başarılı olanlar"
|
msgstr "Başarılı olanlar"
|
||||||
|
|
||||||
#: monitor.py:299
|
#: monitor_terminal.py:299
|
||||||
msgid "Schedules"
|
msgid "Schedules"
|
||||||
msgstr "Zamanlanmışlar"
|
msgstr "Zamanlanmışlar"
|
||||||
|
|
||||||
#: monitor.py:303
|
#: monitor_terminal.py:303
|
||||||
#, python-format
|
#, python-format
|
||||||
msgid "Tasks/%(per)s"
|
msgid "Tasks/%(per)s"
|
||||||
msgstr "İş/%(per)s"
|
msgstr "İş/%(per)s"
|
||||||
|
|
||||||
#: monitor.py:307
|
#: monitor_terminal.py:307
|
||||||
msgid "Avg time"
|
msgid "Avg time"
|
||||||
msgstr "Ortalama süre"
|
msgstr "Ortalama süre"
|
||||||
|
|
||||||
#: monitor.py:357
|
#: monitor_terminal.py:357
|
||||||
msgid "Available (%)"
|
msgid "Available (%)"
|
||||||
msgstr "Müsait (%) "
|
msgstr "Müsait (%) "
|
||||||
|
|
||||||
#: monitor.py:363
|
#: monitor_terminal.py:363
|
||||||
msgid "Available (MB)"
|
msgid "Available (MB)"
|
||||||
msgstr "Müsait (MB)"
|
msgstr "Müsait (MB)"
|
||||||
|
|
||||||
#: monitor.py:368
|
#: monitor_terminal.py:368
|
||||||
msgid "Total (MB)"
|
msgid "Total (MB)"
|
||||||
msgstr "Toplam (MB)"
|
msgstr "Toplam (MB)"
|
||||||
|
|
||||||
#: monitor.py:373
|
#: monitor_terminal.py:373
|
||||||
msgid "Sentinel (MB)"
|
msgid "Sentinel (MB)"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: monitor.py:379
|
#: monitor_terminal.py:379
|
||||||
msgid "Monitor (MB)"
|
msgid "Monitor (MB)"
|
||||||
msgstr "İzleme (MB)"
|
msgstr "İzleme (MB)"
|
||||||
|
|
||||||
#: monitor.py:385
|
#: monitor_terminal.py:385
|
||||||
msgid "Workers (MB)"
|
msgid "Workers (MB)"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: monitor.py:487
|
#: monitor_terminal.py:485
|
||||||
#, python-format
|
#, python-format
|
||||||
msgid "Available lowest (): %(memory_percent)s ((at)s)"
|
msgid "Available lowest (): %(memory_percent)s ((at)s)"
|
||||||
msgstr "Mevcut en düşük (): %(memory_percent)s ((at)s)"
|
msgstr "Mevcut en düşük (): %(memory_percent)s ((at)s)"
|
||||||
|
|
||||||
#: monitor.py:509
|
#: monitor_terminal.py:507
|
||||||
msgid "No clusters appear to be running."
|
msgid "No clusters appear to be running."
|
||||||
msgstr "Hiçbir küme çalışıyor görünmüyor."
|
msgstr "Hiçbir küme çalışıyor görünmüyor."
|
||||||
|
|
||||||
|
#: pusher.py:40
|
||||||
|
#, python-format
|
||||||
|
msgid "%(name)s pushing tasks at %(id)s"
|
||||||
|
msgstr "%(name)s, işleri %(id)s pid'ine gönderiyor."
|
||||||
|
|
||||||
|
#: pusher.py:67
|
||||||
|
#, python-format
|
||||||
|
msgid "queueing from %(list_key)s"
|
||||||
|
msgstr "%(list_key)s kuyruğa alınıyor"
|
||||||
|
|
||||||
|
#: pusher.py:71
|
||||||
|
#, python-format
|
||||||
|
msgid "%(name)s stopped pushing tasks"
|
||||||
|
msgstr "%(name)s işleri göndermeyi durdurdu"
|
||||||
|
|
||||||
|
#: scheduler.py:110
|
||||||
|
#, python-format
|
||||||
|
msgid "%(process_name)s failed to create a task from schedule [%(schedule)s]"
|
||||||
|
msgstr "%(process_name)s programdan bir görev oluşturamadı [%(schedule)s]"
|
||||||
|
|
||||||
|
#: scheduler.py:121
|
||||||
|
#, python-format
|
||||||
|
msgid ""
|
||||||
|
"%(process_name)s created task %(task_name)s from schedule [%(schedule)s]"
|
||||||
|
msgstr "%(process_name)s programdan %(task_name)s görevini oluşturdu [%(schedule)s]"
|
||||||
|
|
||||||
#: signals.py:22
|
#: signals.py:22
|
||||||
#, python-format
|
#, python-format
|
||||||
msgid "malformed return hook '%(hook)s' for [%(name)s]"
|
msgid "malformed return hook '%(hook)s' for [%(name)s]"
|
||||||
@@ -493,6 +655,26 @@ msgstr ""
|
|||||||
msgid "return hook %(hook)s failed on [%(name)s] because %(error)s"
|
msgid "return hook %(hook)s failed on [%(name)s] because %(error)s"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
#: timeout.py:30 timeout.py:43
|
||||||
|
msgid "SIGALARM is not available on your platform"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: worker.py:49
|
||||||
|
#, python-format
|
||||||
|
msgid "%(proc_name)s ready for work at %(id)s"
|
||||||
|
msgstr "%(proc_name)s, %(id)s pid'inde çalışmaya hazır"
|
||||||
|
|
||||||
|
#: worker.py:69
|
||||||
|
#, fuzzy, python-format
|
||||||
|
#| msgid "%(proc_name)s processing '%(func_name)s' (%(task_name)s)"
|
||||||
|
msgid "%(proc_name)s processing %(task_name)s '%(func_name)s'"
|
||||||
|
msgstr "%(proc_name)s, '%(func_name)s' [%(task_name)s] işlerini işiyor"
|
||||||
|
|
||||||
|
#: worker.py:135
|
||||||
|
#, python-format
|
||||||
|
msgid "%(proc_name)s stopped doing work"
|
||||||
|
msgstr "%(proc_name)s çalışmayı bıraktı"
|
||||||
|
|
||||||
#, python-format
|
#, python-format
|
||||||
#~ msgid ""
|
#~ msgid ""
|
||||||
#~ "Could not process '%(func_name)s'. Check the location of the function and "
|
#~ "Could not process '%(func_name)s'. Check the location of the function and "
|
||||||
|
|||||||
@@ -0,0 +1,682 @@
|
|||||||
|
# SOME DESCRIPTIVE TITLE.
|
||||||
|
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
|
||||||
|
# This file is distributed under the same license as the PACKAGE package.
|
||||||
|
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
|
||||||
|
msgid ""
|
||||||
|
msgstr ""
|
||||||
|
"Project-Id-Version: django-q\n"
|
||||||
|
"Report-Msgid-Bugs-To: \n"
|
||||||
|
"POT-Creation-Date: 2026-04-17 21:10+0000\n"
|
||||||
|
"PO-Revision-Date: 2026-01-14 16:36+0800\n"
|
||||||
|
"Last-Translator: Yibo Li <lybcyd@outlook.com>\n"
|
||||||
|
"Language-Team: Simplified Chinese\n"
|
||||||
|
"Language: zh_Hans\n"
|
||||||
|
"MIME-Version: 1.0\n"
|
||||||
|
"Content-Type: text/plain; charset=UTF-8\n"
|
||||||
|
"Content-Transfer-Encoding: 8bit\n"
|
||||||
|
"X-Generator: \n"
|
||||||
|
"Plural-Forms: nplurals=1; plural=0;\n"
|
||||||
|
|
||||||
|
#: admin.py:30
|
||||||
|
msgid "Resubmit selected tasks to queue"
|
||||||
|
msgstr "将选定的任务重新提交到队列"
|
||||||
|
|
||||||
|
#: admin.py:64
|
||||||
|
msgid "Time Taken"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: admin.py:95
|
||||||
|
msgid "Short result"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: admin.py:142 models.py:412
|
||||||
|
#, fuzzy
|
||||||
|
#| msgid "Success"
|
||||||
|
msgid "success"
|
||||||
|
msgstr "成功"
|
||||||
|
|
||||||
|
#: admin.py:154 models.py:414
|
||||||
|
msgid "last_run"
|
||||||
|
msgstr "最后运行"
|
||||||
|
|
||||||
|
#: cluster.py:75
|
||||||
|
#, python-format
|
||||||
|
msgid "Q Cluster %(name)s starting."
|
||||||
|
msgstr "Q 集群 %(name)s 正在启动。"
|
||||||
|
|
||||||
|
#: cluster.py:83
|
||||||
|
#, fuzzy, python-format
|
||||||
|
#| msgid "Q Cluster-{} stopping."
|
||||||
|
msgid "Q Cluster %(name)s stopping."
|
||||||
|
msgstr "Q 集群 %(name)s 正在停止。"
|
||||||
|
|
||||||
|
#: cluster.py:86
|
||||||
|
#, python-format
|
||||||
|
msgid "Q Cluster %(name)s has stopped."
|
||||||
|
msgstr "Q 集群 %(name)s 已停止。"
|
||||||
|
|
||||||
|
#: cluster.py:93
|
||||||
|
#, python-format
|
||||||
|
msgid "%(name)s got signal %(signal)s"
|
||||||
|
msgstr "%(name)s 收到信号 %(signal)s"
|
||||||
|
|
||||||
|
#: cluster.py:224
|
||||||
|
#, python-format
|
||||||
|
msgid "reincarnated monitor %(name)s after sudden death"
|
||||||
|
msgstr "意外宕机后monitor %(name)s 已重生"
|
||||||
|
|
||||||
|
#: cluster.py:230
|
||||||
|
#, python-format
|
||||||
|
msgid "reincarnated pusher %(name)s after sudden death"
|
||||||
|
msgstr "意外宕机后pusher %(name)s 已重生"
|
||||||
|
|
||||||
|
#: cluster.py:262
|
||||||
|
#, fuzzy, python-format
|
||||||
|
#| msgid "reincarnated worker %(name)s after timeout"
|
||||||
|
msgid ""
|
||||||
|
"reincarnated worker %(name)s after timeout while processing task "
|
||||||
|
"%(task_name)s"
|
||||||
|
msgstr "处理任务 %(task_name)s 时超时,worker %(name)s 已重生"
|
||||||
|
|
||||||
|
#: cluster.py:265
|
||||||
|
#, python-format
|
||||||
|
msgid "reincarnated worker %(name)s after timeout"
|
||||||
|
msgstr "超时后worker %(name)s 已重生"
|
||||||
|
|
||||||
|
#: cluster.py:270
|
||||||
|
#, python-format
|
||||||
|
msgid "recycled worker %(name)s"
|
||||||
|
msgstr "worker %(name)s 已回收"
|
||||||
|
|
||||||
|
#: cluster.py:273
|
||||||
|
#, python-format
|
||||||
|
msgid "reincarnated worker %(name)s after death"
|
||||||
|
msgstr "意外宕机后worker %(name)s 已重生"
|
||||||
|
|
||||||
|
#: cluster.py:297
|
||||||
|
#, python-format
|
||||||
|
msgid "%(name)s guarding cluster %(cluster_name)s"
|
||||||
|
msgstr "%(name)s 正在保护Cluster %(cluster_name)s"
|
||||||
|
|
||||||
|
#: cluster.py:307
|
||||||
|
#, python-format
|
||||||
|
msgid "Q Cluster %(cluster_name)s running."
|
||||||
|
msgstr "Q 集群 %(cluster_name)s 正在运行。"
|
||||||
|
|
||||||
|
#: cluster.py:346
|
||||||
|
#, python-format
|
||||||
|
msgid "%(name)s stopping cluster processes"
|
||||||
|
msgstr "%(name)s 正在停止集群进程"
|
||||||
|
|
||||||
|
#: cluster.py:371
|
||||||
|
#, python-format
|
||||||
|
msgid "%(name)s waiting for the monitor."
|
||||||
|
msgstr "%(name)s 正在等待监视器。"
|
||||||
|
|
||||||
|
#: cluster.py:394
|
||||||
|
msgid "Skipping cpu affinity because psutil was not found."
|
||||||
|
msgstr "跳过 CPU 亲和性,因为未找到 psutil。"
|
||||||
|
|
||||||
|
#: cluster.py:399
|
||||||
|
msgid "Faking cpu affinity because it is not supported on this platform"
|
||||||
|
msgstr "伪造 CPU 亲和性,因为此平台不支持此功能"
|
||||||
|
|
||||||
|
#: cluster.py:421
|
||||||
|
#, python-format
|
||||||
|
msgid "%(pid)s will use cpu %(affinity)s"
|
||||||
|
msgstr "%(pid)s 将使用 CPU %(affinity)s"
|
||||||
|
|
||||||
|
#: conf.py:122
|
||||||
|
#, python-format
|
||||||
|
msgid ""
|
||||||
|
"SAVE_LIMIT_PER (%(option)s) is not a valid option. Options are: 'group', "
|
||||||
|
"'name', 'func' and None. Default is None."
|
||||||
|
msgstr ""
|
||||||
|
"SAVE_LIMIT_PER (%(option)s) 不是有效的选项。选项包"
|
||||||
|
"括:'group'、'name'、'func' 和 None。默认值是 None。"
|
||||||
|
|
||||||
|
#. Translators: Cluster status descriptions
|
||||||
|
#: conf.py:239
|
||||||
|
msgid "Starting"
|
||||||
|
msgstr "正在启动"
|
||||||
|
|
||||||
|
#: conf.py:240
|
||||||
|
msgid "Working"
|
||||||
|
msgstr "工作中"
|
||||||
|
|
||||||
|
#: conf.py:241
|
||||||
|
msgid "Idle"
|
||||||
|
msgstr "空闲"
|
||||||
|
|
||||||
|
#: conf.py:242
|
||||||
|
msgid "Stopped"
|
||||||
|
msgstr "已停止"
|
||||||
|
|
||||||
|
#: conf.py:243
|
||||||
|
msgid "Stopping"
|
||||||
|
msgstr "正在停止"
|
||||||
|
|
||||||
|
#. Translators: help text for qcluster management command
|
||||||
|
#: management/commands/qcluster.py:11
|
||||||
|
msgid "Starts a Django Q Cluster."
|
||||||
|
msgstr "启动 Django Q 集群。"
|
||||||
|
|
||||||
|
#. Translators: help text for qinfo management command
|
||||||
|
#: management/commands/qinfo.py:11
|
||||||
|
msgid "General information over all clusters."
|
||||||
|
msgstr "所有集群的常规信息。"
|
||||||
|
|
||||||
|
#. Translators: help text for qmemory management command
|
||||||
|
#: management/commands/qmemory.py:9
|
||||||
|
msgid "Monitors Q Cluster memory usage"
|
||||||
|
msgstr "监视 Q 集群内存使用情况"
|
||||||
|
|
||||||
|
#. Translators: help text for qmonitor management command
|
||||||
|
#: management/commands/qmonitor.py:9
|
||||||
|
msgid "Monitors Q Cluster activity"
|
||||||
|
msgstr "监视 Q 集群活动"
|
||||||
|
|
||||||
|
#: models.py:30 models.py:469
|
||||||
|
msgid "Task id"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: models.py:31
|
||||||
|
msgid "32-character task identifier."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: models.py:36 models.py:235 models.py:470
|
||||||
|
msgid "Name"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: models.py:37
|
||||||
|
msgid "Optional human-readable name for lookup and display."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: models.py:41 models.py:240 models.py:468
|
||||||
|
msgid "Function"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: models.py:42
|
||||||
|
msgid "Dotted import path to the callable, e.g. myapp.tasks.job."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: models.py:47 models.py:247
|
||||||
|
msgid "Hook"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: models.py:48
|
||||||
|
msgid "Optional dotted path to a callback that receives the task result."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: models.py:53 models.py:253 models.py:472
|
||||||
|
msgid "Arguments"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: models.py:54
|
||||||
|
msgid "Pickled positional arguments (tuple)."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: models.py:59 models.py:259 models.py:473
|
||||||
|
msgid "Keyword arguments"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: models.py:60
|
||||||
|
msgid "Pickled keyword arguments (dict)."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: models.py:65
|
||||||
|
msgid "Result"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: models.py:66
|
||||||
|
msgid "Pickled return value or error payload."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: models.py:72 models.py:471
|
||||||
|
msgid "Group"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: models.py:73
|
||||||
|
msgid "Optional group id to aggregate related tasks."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: models.py:80 models.py:328
|
||||||
|
#, fuzzy
|
||||||
|
#| msgid "Clusters"
|
||||||
|
msgid "Cluster"
|
||||||
|
msgstr "集群"
|
||||||
|
|
||||||
|
#: models.py:81
|
||||||
|
msgid "Name of the cluster that executed this task."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: models.py:85
|
||||||
|
msgid "Started at"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: models.py:86
|
||||||
|
msgid "When the worker started executing the task."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: models.py:90
|
||||||
|
#, fuzzy
|
||||||
|
#| msgid "Stopped"
|
||||||
|
msgid "Stopped at"
|
||||||
|
msgstr "已停止"
|
||||||
|
|
||||||
|
#: models.py:91
|
||||||
|
msgid "When the worker finished (success or failure)."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: models.py:96 monitor_terminal.py:180
|
||||||
|
msgid "Success"
|
||||||
|
msgstr "成功"
|
||||||
|
|
||||||
|
#: models.py:97
|
||||||
|
msgid "False if the task raised an exception or timed out."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: models.py:101
|
||||||
|
msgid "Attempt count"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: models.py:102
|
||||||
|
msgid "How many times execution was attempted."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: models.py:172
|
||||||
|
msgid "Task"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: models.py:173
|
||||||
|
msgid "Tasks"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: models.py:194
|
||||||
|
msgid "Successful task"
|
||||||
|
msgstr "成功的任务"
|
||||||
|
|
||||||
|
#: models.py:195
|
||||||
|
msgid "Successful tasks"
|
||||||
|
msgstr "成功的任务"
|
||||||
|
|
||||||
|
#: models.py:210
|
||||||
|
msgid "Failed task"
|
||||||
|
msgstr "失败的任务"
|
||||||
|
|
||||||
|
#: models.py:211
|
||||||
|
msgid "Failed tasks"
|
||||||
|
msgstr "失败的任务"
|
||||||
|
|
||||||
|
#: models.py:219 models.py:347
|
||||||
|
msgid "Please install croniter to enable cron expressions"
|
||||||
|
msgstr "请安装 croniter 以启用 cron 表达式"
|
||||||
|
|
||||||
|
#: models.py:236
|
||||||
|
msgid "Optional label to identify this schedule in the admin."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: models.py:241
|
||||||
|
msgid "e.g. module.tasks.function"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: models.py:248
|
||||||
|
msgid "e.g. module.tasks.result_function"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: models.py:254
|
||||||
|
msgid "e.g. 1, 2, 'John'"
|
||||||
|
msgstr "例如 1, 2, 'John'"
|
||||||
|
|
||||||
|
#: models.py:260
|
||||||
|
msgid "e.g. x=1, y=2, name='John'"
|
||||||
|
msgstr "例如 x=1, y=2, name='John'"
|
||||||
|
|
||||||
|
#: models.py:274
|
||||||
|
msgid "Once"
|
||||||
|
msgstr "一次"
|
||||||
|
|
||||||
|
#: models.py:275 models.py:296
|
||||||
|
msgid "Minutes"
|
||||||
|
msgstr "分钟"
|
||||||
|
|
||||||
|
#: models.py:276
|
||||||
|
msgid "Hourly"
|
||||||
|
msgstr "每小时"
|
||||||
|
|
||||||
|
#: models.py:277
|
||||||
|
msgid "Daily"
|
||||||
|
msgstr "每天"
|
||||||
|
|
||||||
|
#: models.py:278
|
||||||
|
msgid "Weekly"
|
||||||
|
msgstr "每周"
|
||||||
|
|
||||||
|
#: models.py:279
|
||||||
|
msgid "Biweekly"
|
||||||
|
msgstr "每两周"
|
||||||
|
|
||||||
|
#: models.py:280
|
||||||
|
msgid "Monthly"
|
||||||
|
msgstr "每月"
|
||||||
|
|
||||||
|
#: models.py:281
|
||||||
|
msgid "Bimonthly"
|
||||||
|
msgstr "每两个月"
|
||||||
|
|
||||||
|
#: models.py:282
|
||||||
|
msgid "Quarterly"
|
||||||
|
msgstr "每季度"
|
||||||
|
|
||||||
|
#: models.py:283
|
||||||
|
msgid "Yearly"
|
||||||
|
msgstr "每年"
|
||||||
|
|
||||||
|
#: models.py:284 models.py:313
|
||||||
|
msgid "Cron"
|
||||||
|
msgstr "Cron"
|
||||||
|
|
||||||
|
#: models.py:290
|
||||||
|
msgid "Schedule Type"
|
||||||
|
msgstr "计划类型"
|
||||||
|
|
||||||
|
#: models.py:291
|
||||||
|
msgid "How often this task should be enqueued."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: models.py:297
|
||||||
|
msgid "Number of minutes for the Minutes type"
|
||||||
|
msgstr "'分钟'类型的分钟数"
|
||||||
|
|
||||||
|
#: models.py:300
|
||||||
|
msgid "Repeats"
|
||||||
|
msgstr "重复次数"
|
||||||
|
|
||||||
|
#: models.py:300
|
||||||
|
msgid "n = n times, -1 = forever"
|
||||||
|
msgstr "n = n 次,-1 = 永远"
|
||||||
|
|
||||||
|
#: models.py:303
|
||||||
|
msgid "Next Run"
|
||||||
|
msgstr "下次运行"
|
||||||
|
|
||||||
|
#: models.py:304
|
||||||
|
msgid "When this schedule runs next (stored in UTC)."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: models.py:314
|
||||||
|
msgid "Cron expression"
|
||||||
|
msgstr "Cron 表达式"
|
||||||
|
|
||||||
|
#: models.py:320
|
||||||
|
msgid "Last task id"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: models.py:321
|
||||||
|
msgid "Id of the last task spawned from this schedule (read-only)."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: models.py:329 models.py:427
|
||||||
|
msgid "Name of the target cluster"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: models.py:336
|
||||||
|
msgid "Intended date kwarg"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: models.py:337
|
||||||
|
msgid "Name of kwarg to pass intended schedule date"
|
||||||
|
msgstr "传递预定计划日期的 kwarg 的名称"
|
||||||
|
|
||||||
|
#: models.py:418
|
||||||
|
msgid "Scheduled task"
|
||||||
|
msgstr "计划任务"
|
||||||
|
|
||||||
|
#: models.py:419
|
||||||
|
msgid "Scheduled tasks"
|
||||||
|
msgstr "计划任务"
|
||||||
|
|
||||||
|
#: models.py:426
|
||||||
|
#, fuzzy
|
||||||
|
#| msgid "Clusters"
|
||||||
|
msgid "Cluster key"
|
||||||
|
msgstr "集群"
|
||||||
|
|
||||||
|
#: models.py:430
|
||||||
|
msgid "Payload"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: models.py:431
|
||||||
|
msgid "Signed serialized task package (do not edit manually)."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: models.py:435
|
||||||
|
msgid "Lock until"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: models.py:436
|
||||||
|
msgid "Prevent any cluster from pulling until"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: models.py:474
|
||||||
|
#, fuzzy
|
||||||
|
#| msgid "Queued task"
|
||||||
|
msgid "Queue options"
|
||||||
|
msgstr "排队的任务"
|
||||||
|
|
||||||
|
#: models.py:478
|
||||||
|
msgid "Queued task"
|
||||||
|
msgstr "排队的任务"
|
||||||
|
|
||||||
|
#: models.py:479
|
||||||
|
msgid "Queued tasks"
|
||||||
|
msgstr "排队的任务"
|
||||||
|
|
||||||
|
#: monitor.py:41
|
||||||
|
#, python-format
|
||||||
|
msgid "%(name)s monitoring at %(id)s"
|
||||||
|
msgstr "%(name)s 正在 %(id)s 处监视"
|
||||||
|
|
||||||
|
#: monitor.py:61
|
||||||
|
#, python-format
|
||||||
|
msgid "Processed '%(info_name)s' (%(task_name)s)"
|
||||||
|
msgstr "已处理 '%(info_name)s' (%(task_name)s)"
|
||||||
|
|
||||||
|
#: monitor.py:67
|
||||||
|
#, python-format
|
||||||
|
msgid "Failed '%(info_name)s' (%(task_name)s) - %(task_result)s"
|
||||||
|
msgstr "'%(info_name)s' (%(task_name)s) 失败 - %(task_result)s"
|
||||||
|
|
||||||
|
#: monitor.py:74
|
||||||
|
#, python-format
|
||||||
|
msgid "%(name)s stopped monitoring results"
|
||||||
|
msgstr "%(name)s 已停止监视结果"
|
||||||
|
|
||||||
|
#: monitor_terminal.py:64 monitor_terminal.py:348
|
||||||
|
msgid "Host"
|
||||||
|
msgstr "主机"
|
||||||
|
|
||||||
|
#: monitor_terminal.py:68 monitor_terminal.py:352 monitor_terminal.py:457
|
||||||
|
msgid "Id"
|
||||||
|
msgstr "ID"
|
||||||
|
|
||||||
|
#: monitor_terminal.py:72
|
||||||
|
msgid "State"
|
||||||
|
msgstr "状态"
|
||||||
|
|
||||||
|
#: monitor_terminal.py:76
|
||||||
|
msgid "Pool"
|
||||||
|
msgstr "连接池"
|
||||||
|
|
||||||
|
#: monitor_terminal.py:80
|
||||||
|
msgid "TQ"
|
||||||
|
msgstr "TQ"
|
||||||
|
|
||||||
|
#: monitor_terminal.py:84
|
||||||
|
msgid "RQ"
|
||||||
|
msgstr "RQ"
|
||||||
|
|
||||||
|
#: monitor_terminal.py:88
|
||||||
|
msgid "RC"
|
||||||
|
msgstr "RC"
|
||||||
|
|
||||||
|
#: monitor_terminal.py:92
|
||||||
|
msgid "Up"
|
||||||
|
msgstr "运行中"
|
||||||
|
|
||||||
|
#: monitor_terminal.py:172 monitor_terminal.py:286
|
||||||
|
msgid "Queued"
|
||||||
|
msgstr "已排队"
|
||||||
|
|
||||||
|
#: monitor_terminal.py:190 monitor_terminal.py:294
|
||||||
|
msgid "Failures"
|
||||||
|
msgstr "失败"
|
||||||
|
|
||||||
|
#: monitor_terminal.py:201 monitor_terminal.py:496
|
||||||
|
msgid "[Press q to quit]"
|
||||||
|
msgstr "[按 q 键退出]"
|
||||||
|
|
||||||
|
#: monitor_terminal.py:227
|
||||||
|
msgid "day"
|
||||||
|
msgstr "天"
|
||||||
|
|
||||||
|
#: monitor_terminal.py:248
|
||||||
|
msgid "second"
|
||||||
|
msgstr "秒"
|
||||||
|
|
||||||
|
#: monitor_terminal.py:251
|
||||||
|
msgid "minute"
|
||||||
|
msgstr "分钟"
|
||||||
|
|
||||||
|
#: monitor_terminal.py:254
|
||||||
|
msgid "hour"
|
||||||
|
msgstr "小时"
|
||||||
|
|
||||||
|
#: monitor_terminal.py:263
|
||||||
|
#, python-format
|
||||||
|
msgid "-- %(prefix)s %(version)s on %(info)s --"
|
||||||
|
msgstr "-- %(prefix)s %(version)s 在 %(info)s 上 --"
|
||||||
|
|
||||||
|
#: monitor_terminal.py:273
|
||||||
|
msgid "Clusters"
|
||||||
|
msgstr "集群"
|
||||||
|
|
||||||
|
#: monitor_terminal.py:277
|
||||||
|
msgid "Workers"
|
||||||
|
msgstr "工作进程"
|
||||||
|
|
||||||
|
#: monitor_terminal.py:281
|
||||||
|
msgid "Restarts"
|
||||||
|
msgstr "重启次数"
|
||||||
|
|
||||||
|
#: monitor_terminal.py:290
|
||||||
|
msgid "Successes"
|
||||||
|
msgstr "成功次数"
|
||||||
|
|
||||||
|
#: monitor_terminal.py:299
|
||||||
|
msgid "Schedules"
|
||||||
|
msgstr "计划"
|
||||||
|
|
||||||
|
#: monitor_terminal.py:303
|
||||||
|
#, python-format
|
||||||
|
msgid "Tasks/%(per)s"
|
||||||
|
msgstr "任务/%(per)s"
|
||||||
|
|
||||||
|
#: monitor_terminal.py:307
|
||||||
|
msgid "Avg time"
|
||||||
|
msgstr "平均时间"
|
||||||
|
|
||||||
|
#: monitor_terminal.py:357
|
||||||
|
msgid "Available (%)"
|
||||||
|
msgstr "可用 (%)"
|
||||||
|
|
||||||
|
#: monitor_terminal.py:363
|
||||||
|
msgid "Available (MB)"
|
||||||
|
msgstr "可用 (MB)"
|
||||||
|
|
||||||
|
#: monitor_terminal.py:368
|
||||||
|
msgid "Total (MB)"
|
||||||
|
msgstr "总计 (MB)"
|
||||||
|
|
||||||
|
#: monitor_terminal.py:373
|
||||||
|
msgid "Sentinel (MB)"
|
||||||
|
msgstr "哨兵 (MB)"
|
||||||
|
|
||||||
|
#: monitor_terminal.py:379
|
||||||
|
msgid "Monitor (MB)"
|
||||||
|
msgstr "监视器 (MB)"
|
||||||
|
|
||||||
|
#: monitor_terminal.py:385
|
||||||
|
msgid "Workers (MB)"
|
||||||
|
msgstr "工作进程 (MB)"
|
||||||
|
|
||||||
|
#: monitor_terminal.py:485
|
||||||
|
#, python-format
|
||||||
|
msgid "Available lowest (): %(memory_percent)s ((at)s)"
|
||||||
|
msgstr "最低可用 (): %(memory_percent)s ((at)s)"
|
||||||
|
|
||||||
|
#: monitor_terminal.py:507
|
||||||
|
msgid "No clusters appear to be running."
|
||||||
|
msgstr "似乎没有集群正在运行。"
|
||||||
|
|
||||||
|
#: pusher.py:40
|
||||||
|
#, python-format
|
||||||
|
msgid "%(name)s pushing tasks at %(id)s"
|
||||||
|
msgstr "%(name)s 正在 %(id)s 处推送任务"
|
||||||
|
|
||||||
|
#: pusher.py:67
|
||||||
|
#, python-format
|
||||||
|
msgid "queueing from %(list_key)s"
|
||||||
|
msgstr "从 %(list_key)s 排队"
|
||||||
|
|
||||||
|
#: pusher.py:71
|
||||||
|
#, python-format
|
||||||
|
msgid "%(name)s stopped pushing tasks"
|
||||||
|
msgstr "%(name)s 已停止推送任务"
|
||||||
|
|
||||||
|
#: scheduler.py:110
|
||||||
|
#, python-format
|
||||||
|
msgid "%(process_name)s failed to create a task from schedule [%(schedule)s]"
|
||||||
|
msgstr "%(process_name)s 无法从计划 [%(schedule)s] 创建任务"
|
||||||
|
|
||||||
|
#: scheduler.py:121
|
||||||
|
#, python-format
|
||||||
|
msgid ""
|
||||||
|
"%(process_name)s created task %(task_name)s from schedule [%(schedule)s]"
|
||||||
|
msgstr "%(process_name)s 从计划 [%(schedule)s] 创建了任务 %(task_name)s"
|
||||||
|
|
||||||
|
#: signals.py:22
|
||||||
|
#, python-format
|
||||||
|
msgid "malformed return hook '%(hook)s' for [%(name)s]"
|
||||||
|
msgstr "格式错误的返回钩子 '%(hook)s' 用于 [%(name)s]"
|
||||||
|
|
||||||
|
#: signals.py:30
|
||||||
|
#, python-format
|
||||||
|
msgid "return hook %(hook)s failed on [%(name)s] because %(error)s"
|
||||||
|
msgstr "返回钩子 %(hook)s 在 [%(name)s] 上失败,原因是 %(error)s"
|
||||||
|
|
||||||
|
#: timeout.py:30 timeout.py:43
|
||||||
|
msgid "SIGALARM is not available on your platform"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: worker.py:49
|
||||||
|
#, python-format
|
||||||
|
msgid "%(proc_name)s ready for work at %(id)s"
|
||||||
|
msgstr "%(proc_name)s 已准备好在 %(id)s 处工作"
|
||||||
|
|
||||||
|
#: worker.py:69
|
||||||
|
#, fuzzy, python-format
|
||||||
|
#| msgid "%(proc_name)s processing '%(func_name)s' (%(task_name)s)"
|
||||||
|
msgid "%(proc_name)s processing %(task_name)s '%(func_name)s'"
|
||||||
|
msgstr "%(proc_name)s 正在处理任务 %(task_name)s '%(func_name)s'"
|
||||||
|
|
||||||
|
#: worker.py:135
|
||||||
|
#, python-format
|
||||||
|
msgid "%(proc_name)s stopped doing work"
|
||||||
|
msgstr "%(proc_name)s 已停止工作"
|
||||||
|
|
||||||
|
#, python-format
|
||||||
|
#~ msgid ""
|
||||||
|
#~ "Could not process '%(func_name)s'. Check the location of the function and "
|
||||||
|
#~ "the args/kwargs."
|
||||||
|
#~ msgstr "无法处理函数 '%(func_name)s'。检查函数的位置和args/kwargs。"
|
||||||
+325
@@ -0,0 +1,325 @@
|
|||||||
|
# Generated by Django 6.0.4 on 2026-04-17 20:55
|
||||||
|
|
||||||
|
import django.utils.timezone
|
||||||
|
import picklefield.fields
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
import django_q.models
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
dependencies = [
|
||||||
|
("django_q", "0018_task_success_index"),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AlterModelOptions(
|
||||||
|
name="task",
|
||||||
|
options={
|
||||||
|
"ordering": ["-stopped"],
|
||||||
|
"verbose_name": "Task",
|
||||||
|
"verbose_name_plural": "Tasks",
|
||||||
|
},
|
||||||
|
),
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name="ormq",
|
||||||
|
name="key",
|
||||||
|
field=models.CharField(
|
||||||
|
help_text="Name of the target cluster",
|
||||||
|
max_length=100,
|
||||||
|
verbose_name="Cluster key",
|
||||||
|
),
|
||||||
|
),
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name="ormq",
|
||||||
|
name="lock",
|
||||||
|
field=models.DateTimeField(
|
||||||
|
help_text="Prevent any cluster from pulling until",
|
||||||
|
null=True,
|
||||||
|
verbose_name="Lock until",
|
||||||
|
),
|
||||||
|
),
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name="ormq",
|
||||||
|
name="payload",
|
||||||
|
field=models.TextField(
|
||||||
|
help_text="Signed serialized task package (do not edit manually).",
|
||||||
|
verbose_name="Payload",
|
||||||
|
),
|
||||||
|
),
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name="schedule",
|
||||||
|
name="args",
|
||||||
|
field=models.TextField(
|
||||||
|
blank=True,
|
||||||
|
help_text="e.g. 1, 2, 'John'",
|
||||||
|
null=True,
|
||||||
|
verbose_name="Arguments",
|
||||||
|
),
|
||||||
|
),
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name="schedule",
|
||||||
|
name="cluster",
|
||||||
|
field=models.CharField(
|
||||||
|
blank=True,
|
||||||
|
default=None,
|
||||||
|
help_text="Name of the target cluster",
|
||||||
|
max_length=100,
|
||||||
|
null=True,
|
||||||
|
verbose_name="Cluster",
|
||||||
|
),
|
||||||
|
),
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name="schedule",
|
||||||
|
name="cron",
|
||||||
|
field=models.CharField(
|
||||||
|
blank=True,
|
||||||
|
help_text="Cron expression",
|
||||||
|
max_length=100,
|
||||||
|
null=True,
|
||||||
|
validators=[django_q.models.validate_cron],
|
||||||
|
verbose_name="Cron",
|
||||||
|
),
|
||||||
|
),
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name="schedule",
|
||||||
|
name="func",
|
||||||
|
field=models.CharField(
|
||||||
|
help_text="e.g. module.tasks.function",
|
||||||
|
max_length=256,
|
||||||
|
verbose_name="Function",
|
||||||
|
),
|
||||||
|
),
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name="schedule",
|
||||||
|
name="hook",
|
||||||
|
field=models.CharField(
|
||||||
|
blank=True,
|
||||||
|
help_text="e.g. module.tasks.result_function",
|
||||||
|
max_length=256,
|
||||||
|
null=True,
|
||||||
|
verbose_name="Hook",
|
||||||
|
),
|
||||||
|
),
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name="schedule",
|
||||||
|
name="intended_date_kwarg",
|
||||||
|
field=models.CharField(
|
||||||
|
blank=True,
|
||||||
|
help_text="Name of kwarg to pass intended schedule date",
|
||||||
|
max_length=100,
|
||||||
|
null=True,
|
||||||
|
validators=[django_q.models.validate_kwarg],
|
||||||
|
verbose_name="Intended date kwarg",
|
||||||
|
),
|
||||||
|
),
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name="schedule",
|
||||||
|
name="kwargs",
|
||||||
|
field=models.TextField(
|
||||||
|
blank=True,
|
||||||
|
help_text="e.g. x=1, y=2, name='John'",
|
||||||
|
null=True,
|
||||||
|
verbose_name="Keyword arguments",
|
||||||
|
),
|
||||||
|
),
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name="schedule",
|
||||||
|
name="minutes",
|
||||||
|
field=models.PositiveSmallIntegerField(
|
||||||
|
blank=True,
|
||||||
|
help_text="Number of minutes for the Minutes type",
|
||||||
|
null=True,
|
||||||
|
verbose_name="Minutes",
|
||||||
|
),
|
||||||
|
),
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name="schedule",
|
||||||
|
name="name",
|
||||||
|
field=models.CharField(
|
||||||
|
blank=True,
|
||||||
|
help_text="Optional label to identify this schedule in the admin.",
|
||||||
|
max_length=100,
|
||||||
|
null=True,
|
||||||
|
verbose_name="Name",
|
||||||
|
),
|
||||||
|
),
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name="schedule",
|
||||||
|
name="next_run",
|
||||||
|
field=models.DateTimeField(
|
||||||
|
default=django.utils.timezone.now,
|
||||||
|
help_text="When this schedule runs next (stored in UTC).",
|
||||||
|
null=True,
|
||||||
|
verbose_name="Next Run",
|
||||||
|
),
|
||||||
|
),
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name="schedule",
|
||||||
|
name="schedule_type",
|
||||||
|
field=models.CharField(
|
||||||
|
choices=[
|
||||||
|
("O", "Once"),
|
||||||
|
("I", "Minutes"),
|
||||||
|
("H", "Hourly"),
|
||||||
|
("D", "Daily"),
|
||||||
|
("W", "Weekly"),
|
||||||
|
("BW", "Biweekly"),
|
||||||
|
("M", "Monthly"),
|
||||||
|
("BM", "Bimonthly"),
|
||||||
|
("Q", "Quarterly"),
|
||||||
|
("Y", "Yearly"),
|
||||||
|
("C", "Cron"),
|
||||||
|
],
|
||||||
|
default="O",
|
||||||
|
help_text="How often this task should be enqueued.",
|
||||||
|
max_length=2,
|
||||||
|
verbose_name="Schedule Type",
|
||||||
|
),
|
||||||
|
),
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name="schedule",
|
||||||
|
name="task",
|
||||||
|
field=models.CharField(
|
||||||
|
editable=False,
|
||||||
|
help_text="Id of the last task spawned from this schedule (read-only).",
|
||||||
|
max_length=100,
|
||||||
|
null=True,
|
||||||
|
verbose_name="Last task id",
|
||||||
|
),
|
||||||
|
),
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name="task",
|
||||||
|
name="args",
|
||||||
|
field=picklefield.fields.PickledObjectField(
|
||||||
|
editable=False,
|
||||||
|
help_text="Pickled positional arguments (tuple).",
|
||||||
|
null=True,
|
||||||
|
protocol=-1,
|
||||||
|
verbose_name="Arguments",
|
||||||
|
),
|
||||||
|
),
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name="task",
|
||||||
|
name="attempt_count",
|
||||||
|
field=models.IntegerField(
|
||||||
|
default=0,
|
||||||
|
help_text="How many times execution was attempted.",
|
||||||
|
verbose_name="Attempt count",
|
||||||
|
),
|
||||||
|
),
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name="task",
|
||||||
|
name="cluster",
|
||||||
|
field=models.CharField(
|
||||||
|
blank=True,
|
||||||
|
default=None,
|
||||||
|
help_text="Name of the cluster that executed this task.",
|
||||||
|
max_length=100,
|
||||||
|
null=True,
|
||||||
|
verbose_name="Cluster",
|
||||||
|
),
|
||||||
|
),
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name="task",
|
||||||
|
name="func",
|
||||||
|
field=models.CharField(
|
||||||
|
help_text="Dotted import path to the callable, e.g. myapp.tasks.job.",
|
||||||
|
max_length=256,
|
||||||
|
verbose_name="Function",
|
||||||
|
),
|
||||||
|
),
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name="task",
|
||||||
|
name="group",
|
||||||
|
field=models.CharField(
|
||||||
|
editable=False,
|
||||||
|
help_text="Optional group id to aggregate related tasks.",
|
||||||
|
max_length=100,
|
||||||
|
null=True,
|
||||||
|
verbose_name="Group",
|
||||||
|
),
|
||||||
|
),
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name="task",
|
||||||
|
name="hook",
|
||||||
|
field=models.CharField(
|
||||||
|
help_text="Optional dotted path to a callback that receives the task result.",
|
||||||
|
max_length=256,
|
||||||
|
null=True,
|
||||||
|
verbose_name="Hook",
|
||||||
|
),
|
||||||
|
),
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name="task",
|
||||||
|
name="id",
|
||||||
|
field=models.CharField(
|
||||||
|
editable=False,
|
||||||
|
help_text="32-character task identifier.",
|
||||||
|
max_length=32,
|
||||||
|
primary_key=True,
|
||||||
|
serialize=False,
|
||||||
|
verbose_name="Task id",
|
||||||
|
),
|
||||||
|
),
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name="task",
|
||||||
|
name="kwargs",
|
||||||
|
field=picklefield.fields.PickledObjectField(
|
||||||
|
editable=False,
|
||||||
|
help_text="Pickled keyword arguments (dict).",
|
||||||
|
null=True,
|
||||||
|
protocol=-1,
|
||||||
|
verbose_name="Keyword arguments",
|
||||||
|
),
|
||||||
|
),
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name="task",
|
||||||
|
name="name",
|
||||||
|
field=models.CharField(
|
||||||
|
editable=False,
|
||||||
|
help_text="Optional human-readable name for lookup and display.",
|
||||||
|
max_length=100,
|
||||||
|
verbose_name="Name",
|
||||||
|
),
|
||||||
|
),
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name="task",
|
||||||
|
name="result",
|
||||||
|
field=picklefield.fields.PickledObjectField(
|
||||||
|
editable=False,
|
||||||
|
help_text="Pickled return value or error payload.",
|
||||||
|
null=True,
|
||||||
|
protocol=-1,
|
||||||
|
verbose_name="Result",
|
||||||
|
),
|
||||||
|
),
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name="task",
|
||||||
|
name="started",
|
||||||
|
field=models.DateTimeField(
|
||||||
|
editable=False,
|
||||||
|
help_text="When the worker started executing the task.",
|
||||||
|
verbose_name="Started at",
|
||||||
|
),
|
||||||
|
),
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name="task",
|
||||||
|
name="stopped",
|
||||||
|
field=models.DateTimeField(
|
||||||
|
editable=False,
|
||||||
|
help_text="When the worker finished (success or failure).",
|
||||||
|
verbose_name="Stopped at",
|
||||||
|
),
|
||||||
|
),
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name="task",
|
||||||
|
name="success",
|
||||||
|
field=models.BooleanField(
|
||||||
|
default=True,
|
||||||
|
editable=False,
|
||||||
|
help_text="False if the task raised an exception or timed out.",
|
||||||
|
verbose_name="Success",
|
||||||
|
),
|
||||||
|
),
|
||||||
|
]
|
||||||
+157
-42
@@ -2,11 +2,9 @@ from datetime import datetime, timedelta
|
|||||||
from keyword import iskeyword
|
from keyword import iskeyword
|
||||||
|
|
||||||
# Django
|
# Django
|
||||||
from django import get_version
|
|
||||||
from django.core.exceptions import ValidationError
|
from django.core.exceptions import ValidationError
|
||||||
from django.db import models
|
from django.db import models
|
||||||
from django.db.models import Q
|
from django.db.models import Q
|
||||||
from django.template.defaultfilters import truncatechars
|
|
||||||
from django.urls import reverse
|
from django.urls import reverse
|
||||||
from django.utils import timezone
|
from django.utils import timezone
|
||||||
from django.utils.functional import cached_property
|
from django.utils.functional import cached_property
|
||||||
@@ -15,7 +13,6 @@ from django.utils.translation import gettext_lazy as _
|
|||||||
|
|
||||||
# External
|
# External
|
||||||
from picklefield import PickledObjectField
|
from picklefield import PickledObjectField
|
||||||
from picklefield.fields import dbsafe_decode
|
|
||||||
|
|
||||||
# Local
|
# Local
|
||||||
from django_q.conf import croniter
|
from django_q.conf import croniter
|
||||||
@@ -26,19 +23,86 @@ from .utils import get_func_repr
|
|||||||
|
|
||||||
|
|
||||||
class Task(models.Model):
|
class Task(models.Model):
|
||||||
id = models.CharField(max_length=32, primary_key=True, editable=False)
|
id = models.CharField(
|
||||||
name = models.CharField(max_length=100, editable=False)
|
max_length=32,
|
||||||
func = models.CharField(max_length=256)
|
primary_key=True,
|
||||||
hook = models.CharField(max_length=256, null=True)
|
editable=False,
|
||||||
args = PickledObjectField(null=True, protocol=-1)
|
verbose_name=_("Task id"),
|
||||||
kwargs = PickledObjectField(null=True, protocol=-1)
|
help_text=_("32-character task identifier."),
|
||||||
result = PickledObjectField(null=True, protocol=-1)
|
)
|
||||||
group = models.CharField(max_length=100, editable=False, null=True)
|
name = models.CharField(
|
||||||
cluster = models.CharField(max_length=100, default=None, null=True, blank=True)
|
max_length=100,
|
||||||
started = models.DateTimeField(editable=False)
|
editable=False,
|
||||||
stopped = models.DateTimeField(editable=False)
|
verbose_name=_("Name"),
|
||||||
success = models.BooleanField(default=True, editable=False)
|
help_text=_("Optional human-readable name for lookup and display."),
|
||||||
attempt_count = models.IntegerField(default=0)
|
)
|
||||||
|
func = models.CharField(
|
||||||
|
max_length=256,
|
||||||
|
verbose_name=_("Function"),
|
||||||
|
help_text=_("Dotted import path to the callable, e.g. myapp.tasks.job."),
|
||||||
|
)
|
||||||
|
hook = models.CharField(
|
||||||
|
max_length=256,
|
||||||
|
null=True,
|
||||||
|
verbose_name=_("Hook"),
|
||||||
|
help_text=_(
|
||||||
|
"Optional dotted path to a callback that receives the task result."
|
||||||
|
),
|
||||||
|
)
|
||||||
|
args = PickledObjectField(
|
||||||
|
null=True,
|
||||||
|
protocol=-1,
|
||||||
|
verbose_name=_("Arguments"),
|
||||||
|
help_text=_("Pickled positional arguments (tuple)."),
|
||||||
|
)
|
||||||
|
kwargs = PickledObjectField(
|
||||||
|
null=True,
|
||||||
|
protocol=-1,
|
||||||
|
verbose_name=_("Keyword arguments"),
|
||||||
|
help_text=_("Pickled keyword arguments (dict)."),
|
||||||
|
)
|
||||||
|
result = PickledObjectField(
|
||||||
|
null=True,
|
||||||
|
protocol=-1,
|
||||||
|
verbose_name=_("Result"),
|
||||||
|
help_text=_("Pickled return value or error payload."),
|
||||||
|
)
|
||||||
|
group = models.CharField(
|
||||||
|
max_length=100,
|
||||||
|
editable=False,
|
||||||
|
null=True,
|
||||||
|
verbose_name=_("Group"),
|
||||||
|
help_text=_("Optional group id to aggregate related tasks."),
|
||||||
|
)
|
||||||
|
cluster = models.CharField(
|
||||||
|
max_length=100,
|
||||||
|
default=None,
|
||||||
|
null=True,
|
||||||
|
blank=True,
|
||||||
|
verbose_name=_("Cluster"),
|
||||||
|
help_text=_("Name of the cluster that executed this task."),
|
||||||
|
)
|
||||||
|
started = models.DateTimeField(
|
||||||
|
editable=False,
|
||||||
|
verbose_name=_("Started at"),
|
||||||
|
help_text=_("When the worker started executing the task."),
|
||||||
|
)
|
||||||
|
stopped = models.DateTimeField(
|
||||||
|
editable=False,
|
||||||
|
verbose_name=_("Stopped at"),
|
||||||
|
help_text=_("When the worker finished (success or failure)."),
|
||||||
|
)
|
||||||
|
success = models.BooleanField(
|
||||||
|
default=True,
|
||||||
|
editable=False,
|
||||||
|
verbose_name=_("Success"),
|
||||||
|
help_text=_("False if the task raised an exception or timed out."),
|
||||||
|
)
|
||||||
|
attempt_count = models.IntegerField(
|
||||||
|
default=0,
|
||||||
|
verbose_name=_("Attempt count"),
|
||||||
|
help_text=_("How many times execution was attempted."),
|
||||||
|
)
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def get_result(task_id):
|
def get_result(task_id):
|
||||||
@@ -59,7 +123,7 @@ class Task(models.Model):
|
|||||||
.exclude(success=False)
|
.exclude(success=False)
|
||||||
.values_list("result", flat=True)
|
.values_list("result", flat=True)
|
||||||
)
|
)
|
||||||
return decode_results(values)
|
return values
|
||||||
|
|
||||||
def group_result(self, failures=False):
|
def group_result(self, failures=False):
|
||||||
if self.group:
|
if self.group:
|
||||||
@@ -102,15 +166,13 @@ class Task(models.Model):
|
|||||||
def time_taken(self):
|
def time_taken(self):
|
||||||
return (self.stopped - self.started).total_seconds()
|
return (self.stopped - self.started).total_seconds()
|
||||||
|
|
||||||
@property
|
|
||||||
def short_result(self):
|
|
||||||
return truncatechars(self.result, 100)
|
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return f"{self.name or self.id}"
|
return f"{self.name or self.id}"
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
app_label = "django_q"
|
app_label = "django_q"
|
||||||
|
verbose_name = _("Task")
|
||||||
|
verbose_name_plural = _("Tasks")
|
||||||
ordering = ["-stopped"]
|
ordering = ["-stopped"]
|
||||||
indexes = [
|
indexes = [
|
||||||
models.Index(
|
models.Index(
|
||||||
@@ -168,17 +230,36 @@ def validate_kwarg(value):
|
|||||||
|
|
||||||
|
|
||||||
class Schedule(models.Model):
|
class Schedule(models.Model):
|
||||||
name = models.CharField(max_length=100, null=True, blank=True)
|
name = models.CharField(
|
||||||
func = models.CharField(max_length=256, help_text="e.g. module.tasks.function")
|
max_length=100,
|
||||||
|
null=True,
|
||||||
|
blank=True,
|
||||||
|
verbose_name=_("Name"),
|
||||||
|
help_text=_("Optional label to identify this schedule in the admin."),
|
||||||
|
)
|
||||||
|
func = models.CharField(
|
||||||
|
max_length=256,
|
||||||
|
verbose_name=_("Function"),
|
||||||
|
help_text=_("e.g. module.tasks.function"),
|
||||||
|
)
|
||||||
hook = models.CharField(
|
hook = models.CharField(
|
||||||
max_length=256,
|
max_length=256,
|
||||||
null=True,
|
null=True,
|
||||||
blank=True,
|
blank=True,
|
||||||
help_text="e.g. module.tasks.result_function",
|
verbose_name=_("Hook"),
|
||||||
|
help_text=_("e.g. module.tasks.result_function"),
|
||||||
|
)
|
||||||
|
args = models.TextField(
|
||||||
|
null=True,
|
||||||
|
blank=True,
|
||||||
|
verbose_name=_("Arguments"),
|
||||||
|
help_text=_("e.g. 1, 2, 'John'"),
|
||||||
)
|
)
|
||||||
args = models.TextField(null=True, blank=True, help_text=_("e.g. 1, 2, 'John'"))
|
|
||||||
kwargs = models.TextField(
|
kwargs = models.TextField(
|
||||||
null=True, blank=True, help_text=_("e.g. x=1, y=2, name='John'")
|
null=True,
|
||||||
|
blank=True,
|
||||||
|
verbose_name=_("Keyword arguments"),
|
||||||
|
help_text=_("e.g. x=1, y=2, name='John'"),
|
||||||
)
|
)
|
||||||
ONCE = "O"
|
ONCE = "O"
|
||||||
MINUTES = "I"
|
MINUTES = "I"
|
||||||
@@ -205,30 +286,48 @@ class Schedule(models.Model):
|
|||||||
(CRON, _("Cron")),
|
(CRON, _("Cron")),
|
||||||
)
|
)
|
||||||
schedule_type = models.CharField(
|
schedule_type = models.CharField(
|
||||||
max_length=2, choices=TYPE, default=TYPE[0][0], verbose_name=_("Schedule Type")
|
max_length=2,
|
||||||
|
choices=TYPE,
|
||||||
|
default=TYPE[0][0],
|
||||||
|
verbose_name=_("Schedule Type"),
|
||||||
|
help_text=_("How often this task should be enqueued."),
|
||||||
)
|
)
|
||||||
minutes = models.PositiveSmallIntegerField(
|
minutes = models.PositiveSmallIntegerField(
|
||||||
null=True, blank=True, help_text=_("Number of minutes for the Minutes type")
|
null=True,
|
||||||
|
blank=True,
|
||||||
|
verbose_name=_("Minutes"),
|
||||||
|
help_text=_("Number of minutes for the Minutes type"),
|
||||||
)
|
)
|
||||||
repeats = models.IntegerField(
|
repeats = models.IntegerField(
|
||||||
default=-1, verbose_name=_("Repeats"), help_text=_("n = n times, -1 = forever")
|
default=-1, verbose_name=_("Repeats"), help_text=_("n = n times, -1 = forever")
|
||||||
)
|
)
|
||||||
next_run = models.DateTimeField(
|
next_run = models.DateTimeField(
|
||||||
verbose_name=_("Next Run"), default=timezone.now, null=True
|
verbose_name=_("Next Run"),
|
||||||
|
help_text=_("When this schedule runs next (stored in UTC)."),
|
||||||
|
default=timezone.now,
|
||||||
|
null=True,
|
||||||
)
|
)
|
||||||
cron = models.CharField(
|
cron = models.CharField(
|
||||||
max_length=100,
|
max_length=100,
|
||||||
null=True,
|
null=True,
|
||||||
blank=True,
|
blank=True,
|
||||||
validators=[validate_cron],
|
validators=[validate_cron],
|
||||||
|
verbose_name=_("Cron"),
|
||||||
help_text=_("Cron expression"),
|
help_text=_("Cron expression"),
|
||||||
)
|
)
|
||||||
task = models.CharField(max_length=100, null=True, editable=False)
|
task = models.CharField(
|
||||||
|
max_length=100,
|
||||||
|
null=True,
|
||||||
|
editable=False,
|
||||||
|
verbose_name=_("Last task id"),
|
||||||
|
help_text=_("Id of the last task spawned from this schedule (read-only)."),
|
||||||
|
)
|
||||||
cluster = models.CharField(
|
cluster = models.CharField(
|
||||||
max_length=100,
|
max_length=100,
|
||||||
default=None,
|
default=None,
|
||||||
null=True,
|
null=True,
|
||||||
blank=True,
|
blank=True,
|
||||||
|
verbose_name=_("Cluster"),
|
||||||
help_text=_("Name of the target cluster"),
|
help_text=_("Name of the target cluster"),
|
||||||
)
|
)
|
||||||
intended_date_kwarg = models.CharField(
|
intended_date_kwarg = models.CharField(
|
||||||
@@ -236,6 +335,7 @@ class Schedule(models.Model):
|
|||||||
null=True,
|
null=True,
|
||||||
blank=True,
|
blank=True,
|
||||||
validators=[validate_kwarg],
|
validators=[validate_kwarg],
|
||||||
|
verbose_name=_("Intended date kwarg"),
|
||||||
help_text=_("Name of kwarg to pass intended schedule date"),
|
help_text=_("Name of kwarg to pass intended schedule date"),
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -298,12 +398,18 @@ class Schedule(models.Model):
|
|||||||
url = reverse("admin:django_q_success_change", args=(task.id,))
|
url = reverse("admin:django_q_success_change", args=(task.id,))
|
||||||
else:
|
else:
|
||||||
url = reverse("admin:django_q_failure_change", args=(task.id,))
|
url = reverse("admin:django_q_failure_change", args=(task.id,))
|
||||||
return format_html(f'<a href="{url}">[{task.name}]</a>')
|
return format_html('<a href="{}">[{}]</a>', url, task.name)
|
||||||
return None
|
return None
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return self.func
|
return self.func
|
||||||
|
|
||||||
|
def save(self, *args, **kwargs):
|
||||||
|
if self.pk is None and self.schedule_type == self.CRON:
|
||||||
|
self.next_run = self.calculate_next_run()
|
||||||
|
|
||||||
|
return super().save(*args, **kwargs)
|
||||||
|
|
||||||
success.boolean = True
|
success.boolean = True
|
||||||
success.short_description = _("success")
|
success.short_description = _("success")
|
||||||
last_run.allow_tags = True
|
last_run.allow_tags = True
|
||||||
@@ -317,10 +423,19 @@ class Schedule(models.Model):
|
|||||||
|
|
||||||
|
|
||||||
class OrmQ(models.Model):
|
class OrmQ(models.Model):
|
||||||
key = models.CharField(max_length=100, help_text=_("Name of the target cluster"))
|
key = models.CharField(
|
||||||
payload = models.TextField()
|
max_length=100,
|
||||||
|
verbose_name=_("Cluster key"),
|
||||||
|
help_text=_("Name of the target cluster"),
|
||||||
|
)
|
||||||
|
payload = models.TextField(
|
||||||
|
verbose_name=_("Payload"),
|
||||||
|
help_text=_("Signed serialized task package (do not edit manually)."),
|
||||||
|
)
|
||||||
lock = models.DateTimeField(
|
lock = models.DateTimeField(
|
||||||
null=True, help_text=_("Prevent any cluster from pulling until")
|
null=True,
|
||||||
|
verbose_name=_("Lock until"),
|
||||||
|
help_text=_("Prevent any cluster from pulling until"),
|
||||||
)
|
)
|
||||||
|
|
||||||
@cached_property
|
@cached_property
|
||||||
@@ -352,15 +467,15 @@ class OrmQ(models.Model):
|
|||||||
exclude = {"id", "name", "group", "func", "args", "kwargs"}
|
exclude = {"id", "name", "group", "func", "args", "kwargs"}
|
||||||
return {k: v for k, v in self.task.items() if k not in exclude}
|
return {k: v for k, v in self.task.items() if k not in exclude}
|
||||||
|
|
||||||
|
func.short_description = _("Function")
|
||||||
|
task_id.short_description = _("Task id")
|
||||||
|
name.short_description = _("Name")
|
||||||
|
group.short_description = _("Group")
|
||||||
|
args.short_description = _("Arguments")
|
||||||
|
kwargs.short_description = _("Keyword arguments")
|
||||||
|
q_options.short_description = _("Queue options")
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
app_label = "django_q"
|
app_label = "django_q"
|
||||||
verbose_name = _("Queued task")
|
verbose_name = _("Queued task")
|
||||||
verbose_name_plural = _("Queued tasks")
|
verbose_name_plural = _("Queued tasks")
|
||||||
|
|
||||||
|
|
||||||
# Backwards compatibility for Django 1.7
|
|
||||||
def decode_results(values):
|
|
||||||
if get_version().split(".")[1] == "7":
|
|
||||||
# decode values in 1.7
|
|
||||||
return [dbsafe_decode(v) for v in values]
|
|
||||||
return values
|
|
||||||
|
|||||||
+18
-10
@@ -93,7 +93,8 @@ def save_task(task, broker: Broker):
|
|||||||
broker=broker,
|
broker=broker,
|
||||||
)
|
)
|
||||||
# SAVE LIMIT > 0: Prune database, SAVE_LIMIT 0: No pruning
|
# SAVE LIMIT > 0: Prune database, SAVE_LIMIT 0: No pruning
|
||||||
close_old_django_connections()
|
if not task.get("sync", False):
|
||||||
|
close_old_django_connections()
|
||||||
|
|
||||||
try:
|
try:
|
||||||
filters = {}
|
filters = {}
|
||||||
@@ -107,13 +108,16 @@ def save_task(task, broker: Broker):
|
|||||||
value = get_func_repr(value)
|
value = get_func_repr(value)
|
||||||
filters[Conf.SAVE_LIMIT_PER] = value
|
filters[Conf.SAVE_LIMIT_PER] = value
|
||||||
|
|
||||||
with db.transaction.atomic(using=db.router.db_for_write(Success)):
|
# check if we should clean the success tasks
|
||||||
list(Success.objects.filter(**filters).select_for_update())
|
if Conf.SAVE_LIMIT > 0:
|
||||||
if (
|
with db.transaction.atomic(using=db.router.db_for_write(Success)):
|
||||||
task["success"]
|
success_tasks_qs = Success.objects.filter(**filters)
|
||||||
and 0 < Conf.SAVE_LIMIT <= Success.objects.filter(**filters).count()
|
success_tasks_pks = [
|
||||||
):
|
success_task.pk
|
||||||
Success.objects.filter(**filters).last().delete()
|
for success_task in success_tasks_qs.select_for_update()
|
||||||
|
]
|
||||||
|
if task["success"] and len(success_tasks_pks) >= Conf.SAVE_LIMIT:
|
||||||
|
success_tasks_qs.last().delete()
|
||||||
|
|
||||||
# check if this task has previous results
|
# check if this task has previous results
|
||||||
try:
|
try:
|
||||||
@@ -145,7 +149,11 @@ def save_task(task, broker: Broker):
|
|||||||
attempt_count=1,
|
attempt_count=1,
|
||||||
)
|
)
|
||||||
|
|
||||||
if Conf.MAX_ATTEMPTS > 0 and task_obj.attempt_count >= Conf.MAX_ATTEMPTS:
|
if (
|
||||||
|
Conf.MAX_ATTEMPTS > 0
|
||||||
|
and task_obj.attempt_count >= Conf.MAX_ATTEMPTS
|
||||||
|
and task.get("ack_id")
|
||||||
|
):
|
||||||
broker.acknowledge(task["ack_id"])
|
broker.acknowledge(task["ack_id"])
|
||||||
|
|
||||||
except Exception:
|
except Exception:
|
||||||
@@ -153,7 +161,7 @@ def save_task(task, broker: Broker):
|
|||||||
|
|
||||||
|
|
||||||
def save_cached(task, broker: Broker):
|
def save_cached(task, broker: Broker):
|
||||||
task_key = f'{broker.list_key}:{task["id"]}'
|
task_key = f"{broker.list_key}:{task['id']}"
|
||||||
timeout = task["cached"]
|
timeout = task["cached"]
|
||||||
if timeout is True:
|
if timeout is True:
|
||||||
timeout = None
|
timeout = None
|
||||||
|
|||||||
@@ -97,6 +97,8 @@ def monitor(run_once=False, broker=None):
|
|||||||
for stat in stats:
|
for stat in stats:
|
||||||
status = stat.status
|
status = stat.status
|
||||||
# color status
|
# color status
|
||||||
|
if stat.status == Conf.STARTING:
|
||||||
|
status = term.yellow(str(Conf.STARTING))
|
||||||
if stat.status == Conf.WORKING:
|
if stat.status == Conf.WORKING:
|
||||||
status = term.green(str(Conf.WORKING))
|
status = term.green(str(Conf.WORKING))
|
||||||
elif stat.status == Conf.STOPPING:
|
elif stat.status == Conf.STOPPING:
|
||||||
@@ -105,6 +107,8 @@ def monitor(run_once=False, broker=None):
|
|||||||
status = term.red(str(Conf.STOPPED))
|
status = term.red(str(Conf.STOPPED))
|
||||||
elif stat.status == Conf.IDLE:
|
elif stat.status == Conf.IDLE:
|
||||||
status = str(Conf.IDLE)
|
status = str(Conf.IDLE)
|
||||||
|
else:
|
||||||
|
status = _("Unknown")
|
||||||
# color q's
|
# color q's
|
||||||
tasks = str(stat.task_q_size)
|
tasks = str(stat.task_q_size)
|
||||||
if stat.task_q_size > 0:
|
if stat.task_q_size > 0:
|
||||||
@@ -138,7 +142,7 @@ def monitor(run_once=False, broker=None):
|
|||||||
)
|
)
|
||||||
print(
|
print(
|
||||||
term.move(i, 3 * col_width)
|
term.move(i, 3 * col_width)
|
||||||
+ term.center(workers, width=col_width - 1)
|
+ term.center(str(workers), width=col_width - 1)
|
||||||
)
|
)
|
||||||
print(
|
print(
|
||||||
term.move(i, 4 * col_width)
|
term.move(i, 4 * col_width)
|
||||||
@@ -146,11 +150,11 @@ def monitor(run_once=False, broker=None):
|
|||||||
)
|
)
|
||||||
print(
|
print(
|
||||||
term.move(i, 5 * col_width)
|
term.move(i, 5 * col_width)
|
||||||
+ term.center(results, width=col_width - 1)
|
+ term.center(str(results), width=col_width - 1)
|
||||||
)
|
)
|
||||||
print(
|
print(
|
||||||
term.move(i, 6 * col_width)
|
term.move(i, 6 * col_width)
|
||||||
+ term.center(stat.reincarnations, width=col_width - 1)
|
+ term.center(str(stat.reincarnations), width=col_width - 1)
|
||||||
)
|
)
|
||||||
print(
|
print(
|
||||||
term.move(i, 7 * col_width)
|
term.move(i, 7 * col_width)
|
||||||
@@ -173,7 +177,7 @@ def monitor(run_once=False, broker=None):
|
|||||||
)
|
)
|
||||||
print(
|
print(
|
||||||
term.move(i, 3 * col_width)
|
term.move(i, 3 * col_width)
|
||||||
+ term.white_on_cyan(term.center(queue_size, width=col_width))
|
+ term.white_on_cyan(term.center(str(queue_size), width=col_width))
|
||||||
)
|
)
|
||||||
print(
|
print(
|
||||||
term.move(i, 4 * col_width)
|
term.move(i, 4 * col_width)
|
||||||
@@ -182,7 +186,7 @@ def monitor(run_once=False, broker=None):
|
|||||||
print(
|
print(
|
||||||
term.move(i, 5 * col_width)
|
term.move(i, 5 * col_width)
|
||||||
+ term.white_on_cyan(
|
+ term.white_on_cyan(
|
||||||
term.center(models.Success.objects.count(), width=col_width)
|
term.center(str(models.Success.objects.count()), width=col_width)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
print(
|
print(
|
||||||
@@ -192,7 +196,7 @@ def monitor(run_once=False, broker=None):
|
|||||||
print(
|
print(
|
||||||
term.move(i, 7 * col_width)
|
term.move(i, 7 * col_width)
|
||||||
+ term.white_on_cyan(
|
+ term.white_on_cyan(
|
||||||
term.center(models.Failure.objects.count(), width=col_width)
|
term.center(str(models.Failure.objects.count()), width=col_width)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
# for testing
|
# for testing
|
||||||
@@ -411,27 +415,27 @@ def memory(run_once=False, workers=False, broker=None):
|
|||||||
)
|
)
|
||||||
print(
|
print(
|
||||||
term.move(row, 2 * col_width)
|
term.move(row, 2 * col_width)
|
||||||
+ term.center(memory_available_percentage, width=col_width - 1)
|
+ term.center(str(memory_available_percentage), width=col_width - 1)
|
||||||
)
|
)
|
||||||
print(
|
print(
|
||||||
term.move(row, 3 * col_width)
|
term.move(row, 3 * col_width)
|
||||||
+ term.center(memory_available, width=col_width - 1)
|
+ term.center(str(memory_available), width=col_width - 1)
|
||||||
)
|
)
|
||||||
print(
|
print(
|
||||||
term.move(row, 4 * col_width)
|
term.move(row, 4 * col_width)
|
||||||
+ term.center(
|
+ term.center(
|
||||||
round(psutil.virtual_memory().total / 1024**2, 2),
|
str(round(psutil.virtual_memory().total / 1024**2, 2)),
|
||||||
width=col_width - 1,
|
width=col_width - 1,
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
print(
|
print(
|
||||||
term.move(row, 5 * col_width)
|
term.move(row, 5 * col_width)
|
||||||
+ term.center(get_process_mb(stat.sentinel), width=col_width - 1)
|
+ term.center(str(get_process_mb(stat.sentinel)), width=col_width - 1)
|
||||||
)
|
)
|
||||||
print(
|
print(
|
||||||
term.move(row, 6 * col_width)
|
term.move(row, 6 * col_width)
|
||||||
+ term.center(
|
+ term.center(
|
||||||
get_process_mb(getattr(stat, "monitor", None)),
|
str(get_process_mb(getattr(stat, "monitor", None))),
|
||||||
width=col_width - 1,
|
width=col_width - 1,
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
@@ -444,7 +448,7 @@ def memory(run_once=False, workers=False, broker=None):
|
|||||||
print(
|
print(
|
||||||
term.move(row, 7 * col_width)
|
term.move(row, 7 * col_width)
|
||||||
+ term.center(
|
+ term.center(
|
||||||
workers_mb or "NO_PROCESSES_FOUND", width=col_width - 1
|
str(workers_mb) or "NO_PROCESSES_FOUND", width=col_width - 1
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
row += 1
|
row += 1
|
||||||
@@ -476,7 +480,7 @@ def memory(run_once=False, workers=False, broker=None):
|
|||||||
mb_used = get_process_mb(worker_pid)
|
mb_used = get_process_mb(worker_pid)
|
||||||
print(
|
print(
|
||||||
term.move(row, (idx + 1) * col_width)
|
term.move(row, (idx + 1) * col_width)
|
||||||
+ term.center(mb_used, width=col_width - 1)
|
+ term.center(str(mb_used), width=col_width - 1)
|
||||||
)
|
)
|
||||||
row += 1
|
row += 1
|
||||||
row += 1
|
row += 1
|
||||||
|
|||||||
@@ -65,7 +65,7 @@ def scheduler(broker: Broker = None):
|
|||||||
if s.args:
|
if s.args:
|
||||||
args = ast.literal_eval(s.args)
|
args = ast.literal_eval(s.args)
|
||||||
# single value won't eval to tuple, so:
|
# single value won't eval to tuple, so:
|
||||||
if type(args) != tuple:
|
if type(args) is not tuple:
|
||||||
args = (args,)
|
args = (args,)
|
||||||
q_options = kwargs.get("q_options", {})
|
q_options = kwargs.get("q_options", {})
|
||||||
if s.intended_date_kwarg:
|
if s.intended_date_kwarg:
|
||||||
|
|||||||
@@ -43,3 +43,6 @@ pre_execute = Signal()
|
|||||||
|
|
||||||
# args: task
|
# args: task
|
||||||
post_execute = Signal()
|
post_execute = Signal()
|
||||||
|
|
||||||
|
# args: func, task
|
||||||
|
post_execute_in_worker = Signal()
|
||||||
|
|||||||
+3
-1
@@ -461,7 +461,9 @@ def async_iter(func, args_iter, **kwargs):
|
|||||||
# save the original arguments
|
# save the original arguments
|
||||||
broker = options["broker"]
|
broker = options["broker"]
|
||||||
broker.cache.set(
|
broker.cache.set(
|
||||||
f"{broker.list_key}:{iter_group}:args", SignedPackage.dumps(args_iter)
|
f"{broker.list_key}:{iter_group}:args",
|
||||||
|
SignedPackage.dumps(args_iter),
|
||||||
|
timeout=None,
|
||||||
)
|
)
|
||||||
for args in args_iter:
|
for args in args_iter:
|
||||||
if not isinstance(args, tuple):
|
if not isinstance(args, tuple):
|
||||||
|
|||||||
@@ -116,7 +116,7 @@ CACHES = {
|
|||||||
"LOCATION": f"redis://{REDIS_HOST}:6379/0",
|
"LOCATION": f"redis://{REDIS_HOST}:6379/0",
|
||||||
"OPTIONS": {
|
"OPTIONS": {
|
||||||
"CLIENT_CLASS": "django_redis.client.DefaultClient",
|
"CLIENT_CLASS": "django_redis.client.DefaultClient",
|
||||||
"PARSER_CLASS": "redis.connection.HiredisParser",
|
"PARSER_CLASS": "redis.connection.DefaultParser",
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -35,6 +35,57 @@ def test_broker(monkeypatch):
|
|||||||
assert broker.get_stats("test:*") is None
|
assert broker.get_stats("test:*") is None
|
||||||
|
|
||||||
|
|
||||||
|
def test_broker_set_stat_prunes_stale_master_list():
|
||||||
|
# regression: set_stat should prune stale master-list entries on register
|
||||||
|
broker = Broker()
|
||||||
|
a_key = f"{Conf.Q_STAT}:A"
|
||||||
|
b_key = f"{Conf.Q_STAT}:B"
|
||||||
|
broker.cache.delete(Conf.Q_STAT)
|
||||||
|
|
||||||
|
broker.set_stat(a_key, "state_a", 3)
|
||||||
|
assert a_key in broker.cache.get(Conf.Q_STAT)
|
||||||
|
|
||||||
|
# Drop A's per-stat value to simulate a dead cluster whose TTL expired,
|
||||||
|
# leaving the master-list entry as a stale reference.
|
||||||
|
broker.cache.delete(a_key)
|
||||||
|
assert broker.get_stat(a_key) is None
|
||||||
|
assert a_key in broker.cache.get(Conf.Q_STAT)
|
||||||
|
|
||||||
|
# Registering B should prune stale A from the master list.
|
||||||
|
broker.set_stat(b_key, "state_b", 3)
|
||||||
|
key_list = broker.cache.get(Conf.Q_STAT)
|
||||||
|
assert a_key not in key_list
|
||||||
|
assert b_key in key_list
|
||||||
|
assert broker.get_stat(b_key) == "state_b"
|
||||||
|
|
||||||
|
|
||||||
|
def test_broker_set_stat_skips_master_list_write_on_repeat(monkeypatch):
|
||||||
|
# set_stat should only write the master list when membership changes
|
||||||
|
broker = Broker()
|
||||||
|
a_key = f"{Conf.Q_STAT}:A"
|
||||||
|
broker.cache.delete(Conf.Q_STAT)
|
||||||
|
|
||||||
|
writes = []
|
||||||
|
orig_set = broker.cache.set
|
||||||
|
|
||||||
|
def counting_set(key, value, timeout=None, **kw):
|
||||||
|
if key == Conf.Q_STAT:
|
||||||
|
writes.append(key)
|
||||||
|
return orig_set(key, value, timeout, **kw)
|
||||||
|
|
||||||
|
monkeypatch.setattr(broker.cache, "set", counting_set)
|
||||||
|
|
||||||
|
# First call adds a new entry, one master-list write expected
|
||||||
|
broker.set_stat(a_key, "state_a", 3)
|
||||||
|
assert len(writes) == 1
|
||||||
|
|
||||||
|
# Subsequent calls for the same key must not rewrite the master list
|
||||||
|
broker.set_stat(a_key, "state_a", 3)
|
||||||
|
broker.set_stat(a_key, "state_a", 3)
|
||||||
|
broker.set_stat(a_key, "state_a", 3)
|
||||||
|
assert len(writes) == 1
|
||||||
|
|
||||||
|
|
||||||
def test_redis(monkeypatch):
|
def test_redis(monkeypatch):
|
||||||
monkeypatch.setattr(Conf, "DJANGO_REDIS", None)
|
monkeypatch.setattr(Conf, "DJANGO_REDIS", None)
|
||||||
broker = get_broker()
|
broker = get_broker()
|
||||||
@@ -51,7 +102,7 @@ def test_redis(monkeypatch):
|
|||||||
|
|
||||||
|
|
||||||
def test_custom(monkeypatch):
|
def test_custom(monkeypatch):
|
||||||
monkeypatch.setattr(Conf, "BROKER_CLASS", "brokers.redis_broker.Redis")
|
monkeypatch.setattr(Conf, "BROKER_CLASS", "django_q.brokers.redis_broker.Redis")
|
||||||
broker = get_broker()
|
broker = get_broker()
|
||||||
assert broker.ping() is True
|
assert broker.ping() is True
|
||||||
assert broker.info() is not None
|
assert broker.info() is not None
|
||||||
@@ -124,7 +175,7 @@ def test_ironmq(monkeypatch):
|
|||||||
@pytest.mark.skipif(
|
@pytest.mark.skipif(
|
||||||
not os.getenv("AWS_ACCESS_KEY_ID"), reason="requires AWS credentials"
|
not os.getenv("AWS_ACCESS_KEY_ID"), reason="requires AWS credentials"
|
||||||
)
|
)
|
||||||
def canceled_sqs(monkeypatch):
|
def test_sqs(monkeypatch):
|
||||||
monkeypatch.setattr(
|
monkeypatch.setattr(
|
||||||
Conf,
|
Conf,
|
||||||
"SQS",
|
"SQS",
|
||||||
@@ -132,11 +183,13 @@ def canceled_sqs(monkeypatch):
|
|||||||
"aws_region": os.getenv("AWS_REGION"),
|
"aws_region": os.getenv("AWS_REGION"),
|
||||||
"aws_access_key_id": os.getenv("AWS_ACCESS_KEY_ID"),
|
"aws_access_key_id": os.getenv("AWS_ACCESS_KEY_ID"),
|
||||||
"aws_secret_access_key": os.getenv("AWS_SECRET_ACCESS_KEY"),
|
"aws_secret_access_key": os.getenv("AWS_SECRET_ACCESS_KEY"),
|
||||||
"receive_message_wait_time_seconds": 20,
|
"receive_message_wait_time_seconds": 5,
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
# check broker
|
# check broker
|
||||||
broker = get_broker(list_key=uuid()[0])
|
broker = get_broker(list_key="testing")
|
||||||
|
assert "receive_message_wait_time_seconds" in Conf.SQS
|
||||||
|
assert "aws_region" in Conf.SQS
|
||||||
assert broker.ping() is True
|
assert broker.ping() is True
|
||||||
assert broker.info() is not None
|
assert broker.info() is not None
|
||||||
assert broker.queue_size() == 0
|
assert broker.queue_size() == 0
|
||||||
@@ -173,7 +226,7 @@ def canceled_sqs(monkeypatch):
|
|||||||
broker.enqueue("test")
|
broker.enqueue("test")
|
||||||
while task is None:
|
while task is None:
|
||||||
task = broker.dequeue()[0]
|
task = broker.dequeue()[0]
|
||||||
broker.fail(task[0])
|
broker.fail(task[0][0])
|
||||||
# bulk test
|
# bulk test
|
||||||
for _ in range(10):
|
for _ in range(10):
|
||||||
broker.enqueue("test")
|
broker.enqueue("test")
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
import time
|
||||||
|
from copy import deepcopy
|
||||||
from multiprocessing import Event, Value
|
from multiprocessing import Event, Value
|
||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
@@ -128,6 +130,27 @@ def test_iter(broker):
|
|||||||
assert len(i.result()) == 5
|
assert len(i.result()) == 5
|
||||||
|
|
||||||
|
|
||||||
|
def _sleeping_func(_):
|
||||||
|
time.sleep(1)
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.django_db
|
||||||
|
def test_iter_default_cache_timeout(broker, settings):
|
||||||
|
"""
|
||||||
|
Test async_iter when it completes after the default Django
|
||||||
|
cache timeout expires.
|
||||||
|
"""
|
||||||
|
cache_settings = deepcopy(settings.CACHES)
|
||||||
|
cache_settings["default"]["TIMEOUT"] = 1
|
||||||
|
settings.CACHES = cache_settings
|
||||||
|
broker.purge_queue()
|
||||||
|
broker.cache.clear()
|
||||||
|
it = [i for i in range(2)]
|
||||||
|
t = async_iter(_sleeping_func, it, sync=True)
|
||||||
|
result_t = result(t)
|
||||||
|
assert result_t is not None
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.django_db
|
@pytest.mark.django_db
|
||||||
def test_chain(broker):
|
def test_chain(broker):
|
||||||
broker.purge_queue()
|
broker.purge_queue()
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
import os
|
import os
|
||||||
|
import signal
|
||||||
import sys
|
import sys
|
||||||
import threading
|
import threading
|
||||||
import uuid as uuidlib
|
import uuid as uuidlib
|
||||||
@@ -19,7 +20,12 @@ from django_q.models import Success, Task
|
|||||||
from django_q.monitor import monitor, save_task
|
from django_q.monitor import monitor, save_task
|
||||||
from django_q.pusher import pusher
|
from django_q.pusher import pusher
|
||||||
from django_q.queues import Queue
|
from django_q.queues import Queue
|
||||||
from django_q.signals import post_execute, pre_enqueue, pre_execute
|
from django_q.signals import (
|
||||||
|
post_execute,
|
||||||
|
post_execute_in_worker,
|
||||||
|
pre_enqueue,
|
||||||
|
pre_execute,
|
||||||
|
)
|
||||||
from django_q.status import Stat
|
from django_q.status import Stat
|
||||||
from django_q.tasks import (
|
from django_q.tasks import (
|
||||||
async_task,
|
async_task,
|
||||||
@@ -93,6 +99,116 @@ def test_cluster_initial(broker):
|
|||||||
broker.delete_queue()
|
broker.delete_queue()
|
||||||
|
|
||||||
|
|
||||||
|
class TestEarlyClusterStop:
|
||||||
|
sentinel_event = Event()
|
||||||
|
test_event = Event()
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def _fake_ping_for_test_cluster_early_stop():
|
||||||
|
"""
|
||||||
|
Fake broker ping() method for test_cluster_early_stop()
|
||||||
|
|
||||||
|
This is called in the sentinel process's start() method and overriding it allows
|
||||||
|
us to synchronize the sentinel process with the main process to provide a
|
||||||
|
deterministic ordering of operations for the test.
|
||||||
|
|
||||||
|
This is implemented as a static method so the patched broker remains pickleable
|
||||||
|
for passing to the sentinel process, in case anyone ever runs the test on
|
||||||
|
platforms like MacOS that use spawn Process start method.
|
||||||
|
"""
|
||||||
|
# let the main process know the sentinel is waiting
|
||||||
|
TestEarlyClusterStop.sentinel_event.set()
|
||||||
|
# wait for the main process to let the sentinel proceed. The timeout prevents
|
||||||
|
# the test from hanging if the main process terminates unexpectedly before
|
||||||
|
# setting the event.
|
||||||
|
assert TestEarlyClusterStop.test_event.wait(10)
|
||||||
|
|
||||||
|
@pytest.mark.django_db
|
||||||
|
def test_cluster_early_stop(self, broker, monkeypatch):
|
||||||
|
"""
|
||||||
|
Test stopping the cluster before the sentinel has set the cluster's start_event
|
||||||
|
"""
|
||||||
|
|
||||||
|
def raise_sigterm():
|
||||||
|
# wait for the sentinel to be blocked in fake_ping(). Periodically check
|
||||||
|
# that the sentinel is alive in case the sentinel dies unexpectedly before
|
||||||
|
# setting the sentinel_event -- prevents the test from hanging if sentinel
|
||||||
|
# dies unexpectedly.
|
||||||
|
while True:
|
||||||
|
if self.sentinel_event.wait(0.5):
|
||||||
|
break
|
||||||
|
if not c.sentinel.is_alive():
|
||||||
|
break
|
||||||
|
# stop the cluster via SIGTERM
|
||||||
|
os.kill(os.getpid(), signal.SIGTERM)
|
||||||
|
# unblock the sentinel
|
||||||
|
self.test_event.set()
|
||||||
|
|
||||||
|
monkeypatch.setattr(
|
||||||
|
broker,
|
||||||
|
"ping",
|
||||||
|
self._fake_ping_for_test_cluster_early_stop,
|
||||||
|
)
|
||||||
|
|
||||||
|
broker.list_key = "initial_test:q"
|
||||||
|
broker.delete_queue()
|
||||||
|
c = Cluster(broker=broker)
|
||||||
|
assert c.sentinel is None
|
||||||
|
assert c.stat.status == Conf.STOPPED
|
||||||
|
|
||||||
|
# Use a timer to stop the cluster while it is still starting up. The timer function
|
||||||
|
# is guaranteed to run before c.start() returns, as start() must wait for the
|
||||||
|
# sentinel to set the cluster's start_event, and the sentinel will block on
|
||||||
|
# test_event before setting start_event.
|
||||||
|
threading.Timer(0.5, raise_sigterm).start()
|
||||||
|
|
||||||
|
c.start()
|
||||||
|
stat = c.stat
|
||||||
|
assert stat.status == Conf.STOPPED
|
||||||
|
assert c.sentinel.is_alive() is False
|
||||||
|
assert c.has_stopped
|
||||||
|
broker.delete_queue()
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.django_db
|
||||||
|
def test_cluster_stop_responsive(broker, monkeypatch):
|
||||||
|
"""
|
||||||
|
Ensure that stopping the cluster is responsive and does not wait for a full
|
||||||
|
GUARD_CYCLE.
|
||||||
|
"""
|
||||||
|
timeout_seconds = 5
|
||||||
|
|
||||||
|
def timeout(signal, frame):
|
||||||
|
assert 0, f"cluster did not stop after {timeout_seconds}s"
|
||||||
|
|
||||||
|
broker.list_key = "initial_test:q"
|
||||||
|
broker.delete_queue()
|
||||||
|
# set a long GUARD_CYCLE -- greater than timeout_seconds
|
||||||
|
monkeypatch.setattr(Conf, "GUARD_CYCLE", timeout_seconds * 2)
|
||||||
|
c = Cluster(broker=broker)
|
||||||
|
assert c.sentinel is None
|
||||||
|
assert c.stat.status == Conf.STOPPED
|
||||||
|
assert c.start() > 0
|
||||||
|
assert c.sentinel.is_alive() is True
|
||||||
|
assert c.is_running
|
||||||
|
assert c.is_stopping is False
|
||||||
|
assert c.is_starting is False
|
||||||
|
sleep(0.5)
|
||||||
|
stat = c.stat
|
||||||
|
assert stat.status == Conf.IDLE
|
||||||
|
prev_handler = signal.signal(signal.SIGALRM, timeout)
|
||||||
|
try:
|
||||||
|
signal.alarm(timeout_seconds)
|
||||||
|
assert c.stop() is True
|
||||||
|
finally:
|
||||||
|
signal.alarm(0) # cancel the alarm
|
||||||
|
signal.signal(signal.SIGALRM, prev_handler)
|
||||||
|
assert c.sentinel.is_alive() is False
|
||||||
|
assert c.has_stopped
|
||||||
|
assert c.stop() is False
|
||||||
|
broker.delete_queue()
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.django_db
|
@pytest.mark.django_db
|
||||||
def test_sentinel():
|
def test_sentinel():
|
||||||
start_event = Event()
|
start_event = Event()
|
||||||
@@ -399,7 +515,7 @@ def test_timeout_task_finishes(broker, cluster_config_timeout, async_task_kwargs
|
|||||||
|
|
||||||
|
|
||||||
@pytest.mark.django_db
|
@pytest.mark.django_db
|
||||||
def test_recycle(broker, monkeypatch):
|
def test_recycle(broker, monkeypatch, django_assert_num_queries):
|
||||||
# set up the Sentinel
|
# set up the Sentinel
|
||||||
broker.list_key = "test_recycle_test:q"
|
broker.list_key = "test_recycle_test:q"
|
||||||
async_task("django_q.tests.tasks.multiply", 2, 2, broker=broker)
|
async_task("django_q.tests.tasks.multiply", 2, 2, broker=broker)
|
||||||
@@ -432,7 +548,8 @@ def test_recycle(broker, monkeypatch):
|
|||||||
monkeypatch.setattr(Conf, "SAVE_LIMIT", 1)
|
monkeypatch.setattr(Conf, "SAVE_LIMIT", 1)
|
||||||
result_queue.put("STOP")
|
result_queue.put("STOP")
|
||||||
# run monitor
|
# run monitor
|
||||||
monitor(result_queue)
|
with django_assert_num_queries(12):
|
||||||
|
monitor(result_queue)
|
||||||
assert Success.objects.count() == Conf.SAVE_LIMIT
|
assert Success.objects.count() == Conf.SAVE_LIMIT
|
||||||
broker.delete_queue()
|
broker.delete_queue()
|
||||||
|
|
||||||
@@ -487,7 +604,7 @@ def test_max_rss(broker, monkeypatch):
|
|||||||
stop_event = Event()
|
stop_event = Event()
|
||||||
cluster_id = uuidlib.uuid4()
|
cluster_id = uuidlib.uuid4()
|
||||||
# override settings
|
# override settings
|
||||||
monkeypatch.setattr(Conf, "MAX_RSS", 40000)
|
monkeypatch.setattr(Conf, "MAX_RSS", 20000)
|
||||||
monkeypatch.setattr(Conf, "WORKERS", 1)
|
monkeypatch.setattr(Conf, "WORKERS", 1)
|
||||||
# set a timer to stop the Sentinel
|
# set a timer to stop the Sentinel
|
||||||
threading.Timer(3, stop_event.set).start()
|
threading.Timer(3, stop_event.set).start()
|
||||||
@@ -759,6 +876,35 @@ class TestSignals:
|
|||||||
assert self.task.get("result") == -1
|
assert self.task.get("result") == -1
|
||||||
post_execute.disconnect(handler)
|
post_execute.disconnect(handler)
|
||||||
|
|
||||||
|
@pytest.mark.django_db
|
||||||
|
def test_post_execute_in_worker_signal(self, broker):
|
||||||
|
broker.list_key = "post_execute_in_worker_test:q"
|
||||||
|
broker.delete_queue()
|
||||||
|
self.signal_was_called: bool = False
|
||||||
|
self.task: Optional[dict] = None
|
||||||
|
self.func = None
|
||||||
|
|
||||||
|
def handler(sender, task, **kwargs):
|
||||||
|
self.signal_was_called = True
|
||||||
|
self.task = task
|
||||||
|
|
||||||
|
post_execute_in_worker.connect(handler)
|
||||||
|
task_id = async_task("math.copysign", 1, -1, broker=broker)
|
||||||
|
task_queue = Queue()
|
||||||
|
result_queue = Queue()
|
||||||
|
event = Event()
|
||||||
|
event.set()
|
||||||
|
pusher(task_queue, event, broker=broker)
|
||||||
|
task_queue.put("STOP")
|
||||||
|
worker(task_queue, result_queue, Value("f", -1))
|
||||||
|
result_queue.put("STOP")
|
||||||
|
monitor(result_queue, broker)
|
||||||
|
broker.delete_queue()
|
||||||
|
assert self.signal_was_called is True
|
||||||
|
assert self.task.get("id") == task_id
|
||||||
|
assert self.task.get("result") == -1
|
||||||
|
post_execute_in_worker.disconnect(handler)
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.django_db
|
@pytest.mark.django_db
|
||||||
def assert_result(task):
|
def assert_result(task):
|
||||||
|
|||||||
@@ -473,6 +473,47 @@ def test_scheduler_atomic_must_specify_the_database_based_on_router_redirection(
|
|||||||
mocked_db.atomic.assert_called_with(using="default")
|
mocked_db.atomic.assert_called_with(using="default")
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.django_db
|
||||||
|
def test_schedule_save_sets_next_run_for_cron():
|
||||||
|
"""Ensure Schedule.save() sets next_run correctly for CRON schedules."""
|
||||||
|
cron_expression = "0 12 * * *" # Executes dialy at 12pm
|
||||||
|
schedule = Schedule(
|
||||||
|
func="math.sqrt",
|
||||||
|
schedule_type=Schedule.CRON,
|
||||||
|
cron=cron_expression,
|
||||||
|
)
|
||||||
|
|
||||||
|
assert schedule.next_run is not None
|
||||||
|
assert schedule.pk is None
|
||||||
|
|
||||||
|
initial_next_run = schedule.next_run
|
||||||
|
schedule.save()
|
||||||
|
|
||||||
|
# After save, next_run must be recalculated based on the CRON expression
|
||||||
|
assert schedule.next_run > initial_next_run
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.django_db
|
||||||
|
def test_schedule_save_direct_db(broker):
|
||||||
|
"""Ensure Schedule.save() updates next_run correctly when created directly in DB."""
|
||||||
|
cron_expression = "0 12 * * *" # Executes dialy at 12pm
|
||||||
|
|
||||||
|
# Creating schedule directly in database
|
||||||
|
schedule = Schedule.objects.create(
|
||||||
|
func="math.sqrt",
|
||||||
|
schedule_type=Schedule.CRON,
|
||||||
|
cron=cron_expression,
|
||||||
|
)
|
||||||
|
|
||||||
|
# Next run must be defined after execution time
|
||||||
|
assert schedule.next_run is not None
|
||||||
|
assert schedule.next_run > timezone.now()
|
||||||
|
|
||||||
|
scheduler(broker)
|
||||||
|
|
||||||
|
assert broker.queue_size() == 0
|
||||||
|
|
||||||
|
|
||||||
def test_localtime():
|
def test_localtime():
|
||||||
assert not is_naive(localtime())
|
assert not is_naive(localtime())
|
||||||
|
|
||||||
|
|||||||
+9
-4
@@ -22,11 +22,13 @@ class TimeoutHandler:
|
|||||||
return
|
return
|
||||||
try:
|
try:
|
||||||
signal.signal(signal.SIGALRM, self.raise_timeout_exception)
|
signal.signal(signal.SIGALRM, self.raise_timeout_exception)
|
||||||
except ValueError: # ValueError is raised for Windows users
|
signal.alarm(self._timeout)
|
||||||
|
except (
|
||||||
|
ValueError,
|
||||||
|
AttributeError,
|
||||||
|
): # AttributeError or ValueError might be raised for Windows users
|
||||||
logger.debug(_("SIGALARM is not available on your platform"))
|
logger.debug(_("SIGALARM is not available on your platform"))
|
||||||
|
|
||||||
signal.alarm(self._timeout)
|
|
||||||
|
|
||||||
def __exit__(self, exc_type, exc_value, traceback):
|
def __exit__(self, exc_type, exc_value, traceback):
|
||||||
if self._timeout == -1:
|
if self._timeout == -1:
|
||||||
return
|
return
|
||||||
@@ -34,5 +36,8 @@ class TimeoutHandler:
|
|||||||
try:
|
try:
|
||||||
signal.alarm(0)
|
signal.alarm(0)
|
||||||
signal.signal(signal.SIGALRM, signal.SIG_DFL)
|
signal.signal(signal.SIGALRM, signal.SIG_DFL)
|
||||||
except ValueError: # ValueError is raised for Windows users
|
except (
|
||||||
|
ValueError,
|
||||||
|
AttributeError,
|
||||||
|
): # AttributeError or ValueError might be raised for Windows users
|
||||||
logger.debug(_("SIGALARM is not available on your platform"))
|
logger.debug(_("SIGALARM is not available on your platform"))
|
||||||
|
|||||||
+1
-3
@@ -50,9 +50,7 @@ def get_func_repr(func):
|
|||||||
if inspect.isfunction(func):
|
if inspect.isfunction(func):
|
||||||
return f"{func.__module__}.{func.__name__}"
|
return f"{func.__module__}.{func.__name__}"
|
||||||
elif inspect.ismethod(func) and hasattr(func.__self__, "__name__"):
|
elif inspect.ismethod(func) and hasattr(func.__self__, "__name__"):
|
||||||
return (
|
return f"{func.__self__.__module__}.{func.__self__.__name__}.{func.__name__}"
|
||||||
f"{func.__self__.__module__}." f"{func.__self__.__name__}.{func.__name__}"
|
|
||||||
)
|
|
||||||
else:
|
else:
|
||||||
return str(func) if func else None
|
return str(func) if func else None
|
||||||
|
|
||||||
|
|||||||
+5
-2
@@ -18,7 +18,7 @@ except core.exceptions.AppRegistryNotReady:
|
|||||||
|
|
||||||
from django_q.conf import Conf, error_reporter, logger, resource, setproctitle
|
from django_q.conf import Conf, error_reporter, logger, resource, setproctitle
|
||||||
from django_q.exceptions import TimeoutException
|
from django_q.exceptions import TimeoutException
|
||||||
from django_q.signals import post_spawn, pre_execute
|
from django_q.signals import post_execute_in_worker, post_spawn, pre_execute
|
||||||
from django_q.timeout import TimeoutHandler
|
from django_q.timeout import TimeoutHandler
|
||||||
from django_q.utils import close_old_django_connections, get_func_repr
|
from django_q.utils import close_old_django_connections, get_func_repr
|
||||||
|
|
||||||
@@ -85,7 +85,8 @@ def worker(
|
|||||||
if not callable(f):
|
if not callable(f):
|
||||||
# locate() returns None if f cannot be loaded
|
# locate() returns None if f cannot be loaded
|
||||||
f = pydoc.locate(f)
|
f = pydoc.locate(f)
|
||||||
close_old_django_connections()
|
if not task.get("sync", False):
|
||||||
|
close_old_django_connections()
|
||||||
timer_value = task.pop("timeout", timeout)
|
timer_value = task.pop("timeout", timeout)
|
||||||
# signal execution
|
# signal execution
|
||||||
pre_execute.send(sender="django_q", func=f, task=task)
|
pre_execute.send(sender="django_q", func=f, task=task)
|
||||||
@@ -109,6 +110,7 @@ def worker(
|
|||||||
if error_reporter:
|
if error_reporter:
|
||||||
error_reporter.report()
|
error_reporter.report()
|
||||||
if task.get("sync", False):
|
if task.get("sync", False):
|
||||||
|
post_execute_in_worker.send(sender="django_q", func=f, task=task)
|
||||||
raise
|
raise
|
||||||
|
|
||||||
with timer.get_lock():
|
with timer.get_lock():
|
||||||
@@ -116,6 +118,7 @@ def worker(
|
|||||||
task["result"] = result[0]
|
task["result"] = result[0]
|
||||||
task["success"] = result[1]
|
task["success"] = result[1]
|
||||||
task["stopped"] = timezone.now()
|
task["stopped"] = timezone.now()
|
||||||
|
post_execute_in_worker.send(sender="django_q", func=f, task=task)
|
||||||
result_queue.put(task)
|
result_queue.put(task)
|
||||||
if timeout_error:
|
if timeout_error:
|
||||||
# force destroy process due to timeout
|
# force destroy process due to timeout
|
||||||
|
|||||||
+2
-2
@@ -73,9 +73,9 @@ author = "Ilan Steemers, Stan Triepels"
|
|||||||
# built documents.
|
# built documents.
|
||||||
#
|
#
|
||||||
# The short X.Y version.
|
# The short X.Y version.
|
||||||
version = "1.7"
|
version = "1.10"
|
||||||
# The full version, including alpha/beta/rc tags.
|
# The full version, including alpha/beta/rc tags.
|
||||||
release = "1.7.2"
|
release = "1.10.0"
|
||||||
|
|
||||||
# The language for content autogenerated by Sphinx. Refer to documentation
|
# The language for content autogenerated by Sphinx. Refer to documentation
|
||||||
# for a list of supported languages.
|
# for a list of supported languages.
|
||||||
|
|||||||
+1
-1
@@ -27,7 +27,7 @@ Features
|
|||||||
- Rollbar and Sentry support
|
- Rollbar and Sentry support
|
||||||
|
|
||||||
|
|
||||||
Django Q2 is tested with: Python 3.8, 3.9, 3.10, 3.11 and 3.12. Works with Django 4.2.x and 5.0.x
|
Django Q2 is tested with: Python 3.8, 3.9, 3.10, 3.11 and 3.12. Works with Django 4.2.x, 5.x and 6.0.x
|
||||||
|
|
||||||
Currently available in English, German and French.
|
Currently available in English, German and French.
|
||||||
|
|
||||||
|
|||||||
+12
-2
@@ -32,8 +32,14 @@ executed by a worker. This signal provides two arguments:
|
|||||||
|
|
||||||
After executing a task
|
After executing a task
|
||||||
""""""""""""""""""""""
|
""""""""""""""""""""""
|
||||||
The ``django_q.signals.post_execute`` signal is emitted after a task is
|
- The ``django_q.signals.post_execute_in_worker`` signal is emitted after a task
|
||||||
executed by a worker and processed by the monitor. It included the ``task`` dictionary with the result.
|
is executed by a worker and processed by the **worker**. It included the ``task``
|
||||||
|
dictionary with the result. Note that this signal is **emitted from, and handled
|
||||||
|
by, the worker process itself**, not the monitor, unlike the ``post_execute``
|
||||||
|
signal below.
|
||||||
|
- The ``django_q.signals.post_execute`` signal is emitted after a task is
|
||||||
|
executed by a worker and processed by the **monitor**. It included the ``task``
|
||||||
|
dictionary with the result.
|
||||||
|
|
||||||
|
|
||||||
Subscribing to a signal
|
Subscribing to a signal
|
||||||
@@ -56,6 +62,10 @@ signal::
|
|||||||
@receiver(post_execute)
|
@receiver(post_execute)
|
||||||
def my_post_execute_callback(sender, task, **kwargs):
|
def my_post_execute_callback(sender, task, **kwargs):
|
||||||
print(f"Task {task['name']} was executed with result {task['result']}")
|
print(f"Task {task['name']} was executed with result {task['result']}")
|
||||||
|
|
||||||
|
@receiver(post_execute_in_worker)
|
||||||
|
def my_post_execute_in_worker_callback(sender, func, task, **kwargs):
|
||||||
|
print(f"Task {task['name']} was executed with result {task['result']}")
|
||||||
|
|
||||||
@receiver(post_spawn)
|
@receiver(post_spawn)
|
||||||
def my_post_spawn_callback(sender, proc_name, **kwargs):
|
def my_post_spawn_callback(sender, proc_name, **kwargs):
|
||||||
|
|||||||
Generated
+853
-794
File diff suppressed because it is too large
Load Diff
+8
-5
@@ -4,7 +4,7 @@ build-backend = "poetry.core.masonry.api"
|
|||||||
|
|
||||||
[tool.poetry]
|
[tool.poetry]
|
||||||
name = "django-q2"
|
name = "django-q2"
|
||||||
version = "1.7.2"
|
version = "1.10.0"
|
||||||
packages = [
|
packages = [
|
||||||
{ include = "django_q" },
|
{ include = "django_q" },
|
||||||
]
|
]
|
||||||
@@ -30,16 +30,19 @@ classifiers = [
|
|||||||
'Operating System :: MacOS',
|
'Operating System :: MacOS',
|
||||||
'Programming Language :: Python',
|
'Programming Language :: Python',
|
||||||
'Programming Language :: Python :: 3',
|
'Programming Language :: Python :: 3',
|
||||||
'Programming Language :: Python :: 3.8',
|
|
||||||
'Programming Language :: Python :: 3.9',
|
'Programming Language :: Python :: 3.9',
|
||||||
'Programming Language :: Python :: 3.10',
|
'Programming Language :: Python :: 3.10',
|
||||||
'Programming Language :: Python :: 3.11',
|
'Programming Language :: Python :: 3.11',
|
||||||
'Programming Language :: Python :: 3.12',
|
'Programming Language :: Python :: 3.12',
|
||||||
|
'Programming Language :: Python :: 3.13',
|
||||||
'Topic :: Internet :: WWW/HTTP',
|
'Topic :: Internet :: WWW/HTTP',
|
||||||
'Topic :: System :: Distributed Computing',
|
'Topic :: System :: Distributed Computing',
|
||||||
'Topic :: Software Development :: Libraries :: Python Modules',
|
'Topic :: Software Development :: Libraries :: Python Modules',
|
||||||
]
|
]
|
||||||
include = ['CHANGELOG.md']
|
|
||||||
|
include = [
|
||||||
|
{ path = "CHANGELOG.md", format = "sdist" },
|
||||||
|
]
|
||||||
|
|
||||||
[tool.poetry.plugins] # Optional super table
|
[tool.poetry.plugins] # Optional super table
|
||||||
|
|
||||||
@@ -49,8 +52,8 @@ include = ['CHANGELOG.md']
|
|||||||
|
|
||||||
|
|
||||||
[tool.poetry.dependencies]
|
[tool.poetry.dependencies]
|
||||||
python = ">=3.8,<4"
|
python = ">=3.10,<4"
|
||||||
django = ">=4.2, <6"
|
django = ">=5.2"
|
||||||
django-picklefield = "^3.1"
|
django-picklefield = "^3.1"
|
||||||
|
|
||||||
blessed = { version = "^1.19.1", optional = true }
|
blessed = { version = "^1.19.1", optional = true }
|
||||||
|
|||||||
@@ -13,15 +13,41 @@ services:
|
|||||||
networks:
|
networks:
|
||||||
- main
|
- main
|
||||||
|
|
||||||
|
aws:
|
||||||
|
container_name: aws
|
||||||
|
image: localstack/localstack:3.4.0
|
||||||
|
ports:
|
||||||
|
- "127.0.0.1:4566:4566" # LocalStack Gateway
|
||||||
|
- "127.0.0.1:4510-4559:4510-4559" # External services port range
|
||||||
|
environment:
|
||||||
|
AWS_DEFAULT_REGION: ${AWS_DEFAULT_REGION:-us-west-2}
|
||||||
|
DEFAULT_REGION: ${AWS_DEFAULT_REGION:-us-west-2}
|
||||||
|
SQS_ENDPOINT_STRATEGY: path
|
||||||
|
SERVICES: sqs
|
||||||
|
LOCALSTACK_HOST: aws
|
||||||
|
DEBUG: 1
|
||||||
|
LS_LOG: trace
|
||||||
|
volumes:
|
||||||
|
- ./containers/localstack:/etc/localstack/init/ready.d
|
||||||
|
networks:
|
||||||
|
- main
|
||||||
|
|
||||||
django-q2:
|
django-q2:
|
||||||
build:
|
build:
|
||||||
dockerfile: ./Dockerfile.dev
|
dockerfile: ./Dockerfile.dev
|
||||||
context: .
|
context: .
|
||||||
|
environment:
|
||||||
|
AWS_ENDPOINT_URL: http://aws:4566
|
||||||
|
AWS_REGION: ${AWS_REGION:-us-west-2}
|
||||||
|
AWS_ACCESS_KEY_ID: ${AWS_ACCESS_KEY_ID:-test}
|
||||||
|
AWS_SECRET_ACCESS_KEY: ${AWS_SECRET_ACCESS_KEY:-test}
|
||||||
|
AWS_DEFAULT_REGION: ${AWS_DEFAULT_REGION:-us-west-2}
|
||||||
volumes:
|
volumes:
|
||||||
- .:/app
|
- .:/app
|
||||||
depends_on:
|
depends_on:
|
||||||
- redis
|
- redis
|
||||||
- mongo
|
- mongo
|
||||||
|
- aws
|
||||||
networks:
|
networks:
|
||||||
- main
|
- main
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user