Skip to content

Commit

Permalink
fix: Retain group_id when tasks get re-frozen
Browse files Browse the repository at this point in the history
When a group task which is part of a chain was to be delayed by
`trace_task()`, it would be reconstructed from the serialized request.
Normally, this sets the `group_id` of encapsulated tasks to the ID of
the group being instantiated. However, in the specific situation of a
group that is the last task in a chain which contributes to the
completion of a chord, it is essential that the group ID of the top-most
group is used instead. This top-most group ID is used by the redis
backend to track the completions of "final elements" of a chord in the
`on_chord_part_return()` implementation. By overwriting the group ID
which was already set in the `options` dictionaries of the child tasks
being deserialized, the chord accounting done by the redis backend would
be made inaccurate and chords would never complete.

This change alters how options are overridden for signatures to ensure
that if a `group_id` has already been set, it cannot be overridden.
Since group ID should be generally opaque to users, this should not be
disruptive.
  • Loading branch information
maybe-sybr committed Sep 28, 2020
1 parent ea37db1 commit 7178c07
Showing 1 changed file with 2 additions and 3 deletions.
5 changes: 2 additions & 3 deletions celery/canvas.py
Expand Up @@ -227,8 +227,7 @@ def _merge(self, args=None, kwargs=None, options=None, force=False):
options = options if options else {}
if self.immutable and not force:
return (self.args, self.kwargs,
dict(self.options,
**options) if options else self.options)
dict(options, **self.options) if options else self.options)
return (tuple(args) + tuple(self.args) if args else self.args,
dict(self.kwargs, **kwargs) if kwargs else self.kwargs,
dict(self.options, **options) if options else self.options)
Expand Down Expand Up @@ -286,7 +285,7 @@ def freeze(self, _id=None, group_id=None, chord=None,
opts['parent_id'] = parent_id
if 'reply_to' not in opts:
opts['reply_to'] = self.app.oid
if group_id:
if group_id and "group_id" not in opts:
opts['group_id'] = group_id
if chord:
opts['chord'] = chord
Expand Down

0 comments on commit 7178c07

Please sign in to comment.