Considérez l'extrait suivant ci-dessous et deux nœuds de calcul en cours d'exécution :
r = Redis(
host="localhost",
port=6379,
db=0
)
q = Queue(connection=r)
id_1 = str(uuid4())
q.enqueue(func_1, job_id=id_1)
q.enqueue(func_2, depends_on=id_1)
Dans cet extrait, tout fonctionne comme prévu ; les deux travaux sont mis en file d'attente (un sur chaque travailleur) mais func_2 ne s'exécute pas avant que func_1 ne soit terminé.
Considérons maintenant l'extrait suivant, toujours avec deux nœuds de calcul :
r = Redis(
host="localhost",
port=6379,
db=0
)
q = Queue(connection=r)
id_1 = str(uuid4())
id_2 = str(uuid4())
job_1 = Job.create(func_1, id=id_1, connection=r)
job_2 = Job.create(func_2, id=id_2, depends_on=id_1, connection=r)
q.enqueue_job(job_1)
q.enqueue_job(job_2)
Lorsque j'exécute ce code, les deux tâches sont démarrées immédiatement, malgré la définition de l'argument depends_on
.
Pourquoi est-il nécessaire de mettre connection=
sur les jobs quand j'utilise Job.create
? L'instance Queue
sait-elle pas déjà quelle connexion Redis utiliser ? Le code échoue sans que je définisse connection
sur tous les travaux également.
Ce PR ajoute une fonction de multi-dépendance à RQ proprement dit. Vous devriez essayer ceci à la place.
Merci de répondre!
J'ai parcouru le PR, mais je ne vois pas comment ces changements résoudraient ce problème ? La seule façon dont j'ai réussi à résoudre ce problème était de créer une classe de file d'attente personnalisée et d'implémenter la fonction suivante en remplacement de l'appel initial enqueue_job
:
def enqueue_custom(
self, job: CustomJob, pipeline=None, at_front: bool = False
) -> CustomJob:
# If a _dependent_ job depends on any unfinished job, register all the
# _dependent_ job's dependencies instead of enqueueing it.
#
# `Job#fetch_dependencies` sets WATCH on all dependencies. If
# WatchError is raised in the when the pipeline is executed, that means
# something else has modified either the set of dependencies or the
# status of one of them. In this case, we simply retry.
job.set_status(FlowStatus.QUEUED)
if job._dependency_id:
with self.connection.pipeline() as pipe:
while True:
try:
pipe.watch(job.dependencies_key)
dependencies = job.fetch_dependencies(watch=True, pipeline=pipe)
pipe.multi()
for dependency in dependencies:
if (
dependency.get_status(refresh=False)
!= FlowStatus.FINISHED
):
job.set_status(FlowStatus.DEFERRED, pipeline=pipe)
job.register_dependency(pipeline=pipe)
job.save(pipeline=pipe)
job.cleanup(ttl=job.ttl, pipeline=pipe)
pipe.execute()
return job
break
except WatchError:
continue
return super().enqueue_job(job, pipeline, at_front=at_front)
Vous avez également ce bloc if dans enqueue_call
, et je ne pourrais pas faire fonctionner les dépendances sans lui.
Avec le PR fusionné, vous pouvez faire queue.enqueue(my_func, depends_on=[job_1, job_2])
Oui je comprends (et j'aime vraiment cette fonctionnalité !)
Mais, dans la doc, vous donnez cet exemple :
from rq.job import Job
job = Job.create(count_words_at_url, 'http://nvie.com')
print('Job id: %s' % job.id)
q.enqueue_job(job)
# create a job with a predetermined id
job = Job.create(count_words_at url, 'http://nvie.com', id='my_job_id')
Cette façon de faire correspond _très_ bien à mes besoins, mais si je fais ce travail, les dépendances ne fonctionnent pas. Si c'est par conception, bien sûr, je devrai utiliser q.enqueue( ... )
.
Éditer:
Mes fonctions ( ie count_words_at_url ) sont chargées dynamiquement à partir d'un fichier de configuration, et sont donc attachées à ma classe Job lors de l'exécution.
Je pense que ce problème devrait être rouvert car il semble toujours se produire (nouveau test échoué):
https://github.com/rq/rq/blob/9bef2aa5a49d894bd03bd772b670e207f8edd0ef/tests/test_queue.py#L530
Je suis d'accord avec @jtfidje qu'il ne s'agit pas de dépendances multiples liées, bien que quelques personnes l'aient documenté dans #1170.
Le nœud du problème est que enqueue_job
ne vérifie pas du tout les dépendances.
Commentaire le plus utile
Je pense que ce problème devrait être rouvert car il semble toujours se produire (nouveau test échoué):
https://github.com/rq/rq/blob/9bef2aa5a49d894bd03bd772b670e207f8edd0ef/tests/test_queue.py#L530
Je suis d'accord avec @jtfidje qu'il ne s'agit pas de dépendances multiples liées, bien que quelques personnes l'aient documenté dans #1170.
Le nœud du problème est que
enqueue_job
ne vérifie pas du tout les dépendances.