Repository: celery/celery

Issue:
EagerResult doesn't seem to poplate name
Sometimes I run my tasks with `CELERY_TASK_ALWAYS_EAGER` to aid debugging, it seems like the `name` property of EagerResult isn't populated, which makes this sort of investigation more tricky.

I have some code I use to list my tasks in a django app, and part of this is to grab the task name.

When running eagerly, the EagerResult task status is SUCCESS, so I would have expected `name` to be available at this point.


Discussion:
Hey @stuaxo :wave:,
Thank you for opening an issue. We will get back to you as soon as we can.
Also, check out our [Open Collective](https://opencollective.com/celery) and consider backing us - every little helps!

We also offer priority support for our sponsors.
If you require immediate assistance please consider sponsoring us.

do you have any failing test/implementation detail in mind to share?
I'll see what I can find, I'm no longer working at the organisation* I did that project for, but it is open source so I still have that work and can share it :)

*I'm a contractor and move from place to place.
BTW, I am a contractor too
I really wish that every contract had a budget to put towards open source projects they use - I did raise this @ the last place, but probably not in the right places.

The furthest I've got is submitting patches to projects used.

Resolving patch:
diff --git a/celery/app/task.py b/celery/app/task.py
--- a/celery/app/task.py
+++ b/celery/app/task.py
@@ -788,6 +788,7 @@ def apply(self, args=None, kwargs=None,
 
         request = {
             'id': task_id,
+            'task': self.name,
             'retries': retries,
             'is_eager': True,
             'logfile': logfile,
@@ -824,7 +825,7 @@ def apply(self, args=None, kwargs=None,
         if isinstance(retval, Retry) and retval.sig is not None:
             return retval.sig.apply(retries=retries + 1)
         state = states.SUCCESS if ret.info is None else ret.info.state
-        return EagerResult(task_id, retval, state, traceback=tb)
+        return EagerResult(task_id, self.name, retval, state, traceback=tb)
 
     def AsyncResult(self, task_id, **kwargs):
         """Get AsyncResult instance for the specified task.
diff --git a/celery/result.py b/celery/result.py
--- a/celery/result.py
+++ b/celery/result.py
@@ -983,10 +983,11 @@ def restore(cls, id, backend=None, app=None):
 class EagerResult(AsyncResult):
     """Result that we know has already been executed."""
 
-    def __init__(self, id, ret_value, state, traceback=None):
+    def __init__(self, id, name, ret_value, state, traceback=None):
         # pylint: disable=super-init-not-called
         # XXX should really not be inheriting from AsyncResult
         self.id = id
+        self._name = name
         self._result = ret_value
         self._state = state
         self._traceback = traceback
@@ -1038,6 +1039,7 @@ def __repr__(self):
     @property
     def _cache(self):
         return {
+            'name': self._name,
             'task_id': self.id,
             'result': self._result,
             'status': self._state,


Test patch:
diff --git a/t/unit/tasks/test_chord.py b/t/unit/tasks/test_chord.py
--- a/t/unit/tasks/test_chord.py
+++ b/t/unit/tasks/test_chord.py
@@ -46,7 +46,7 @@ def join(self, propagate=True, **kwargs):
     def _failed_join_report(self):
         for value in self.value:
             if isinstance(value, Exception):
-                yield EagerResult('some_id', value, 'FAILURE')
+                yield EagerResult('some_id', 'test-task', value, 'FAILURE')
 
 
 class TSRNoReport(TSR):
diff --git a/t/unit/tasks/test_result.py b/t/unit/tasks/test_result.py
--- a/t/unit/tasks/test_result.py
+++ b/t/unit/tasks/test_result.py
@@ -136,7 +136,7 @@ def test_reduce_direct(self):
 
     def test_children(self):
         x = self.app.AsyncResult('1')
-        children = [EagerResult(str(i), i, states.SUCCESS) for i in range(3)]
+        children = [EagerResult(str(i), 'test-task', i, states.SUCCESS) for i in range(3)]
         x._cache = {'children': children, 'status': states.SUCCESS}
         x.backend = Mock()
         assert x.children
@@ -147,12 +147,12 @@ def test_propagates_for_parent(self):
         x.backend = Mock(name='backend')
         x.backend.get_task_meta.return_value = {}
         x.backend.wait_for_pending.return_value = 84
-        x.parent = EagerResult(uuid(), KeyError('foo'), states.FAILURE)
+        x.parent = EagerResult(uuid(), 'test-task', KeyError('foo'), states.FAILURE)
         with pytest.raises(KeyError):
             x.get(propagate=True)
         x.backend.wait_for_pending.assert_not_called()
 
-        x.parent = EagerResult(uuid(), 42, states.SUCCESS)
+        x.parent = EagerResult(uuid(), 'test-task', 42, states.SUCCESS)
         assert x.get(propagate=True) == 84
         x.backend.wait_for_pending.assert_called()
 
@@ -172,7 +172,7 @@ def test_get_children(self):
     def test_build_graph_get_leaf_collect(self):
         x = self.app.AsyncResult('1')
         x.backend._cache['1'] = {'status': states.SUCCESS, 'result': None}
-        c = [EagerResult(str(i), i, states.SUCCESS) for i in range(3)]
+        c = [EagerResult(str(i), 'test-task', i, states.SUCCESS) for i in range(3)]
         x.iterdeps = Mock()
         x.iterdeps.return_value = (
             (None, x),
@@ -194,7 +194,7 @@ def test_build_graph_get_leaf_collect(self):
 
     def test_iterdeps(self):
         x = self.app.AsyncResult('1')
-        c = [EagerResult(str(i), i, states.SUCCESS) for i in range(3)]
+        c = [EagerResult(str(i), 'test-task', i, states.SUCCESS) for i in range(3)]
         x._cache = {'status': states.SUCCESS, 'result': None, 'children': c}
         for child in c:
             child.backend = Mock()
@@ -945,13 +945,13 @@ def test_wait_raises(self):
         assert res.wait(propagate=False)
 
     def test_wait(self):
-        res = EagerResult('x', 'x', states.RETRY)
+        res = EagerResult('x', 'test-task', 'x', states.RETRY)
         res.wait()
         assert res.state == states.RETRY
         assert res.status == states.RETRY
 
     def test_forget(self):
-        res = EagerResult('x', 'x', states.RETRY)
+        res = EagerResult('x', 'test-task', 'x', states.RETRY)
         res.forget()
 
     def test_revoke(self):
@@ -962,7 +962,7 @@ def test_revoke(self):
     def test_get_sync_subtask_option(self, task_join_will_block):
         task_join_will_block.return_value = True
         tid = uuid()
-        res_subtask_async = EagerResult(tid, 'x', 'x', states.SUCCESS)
+        res_subtask_async = EagerResult(tid, 'test-task', 'x', 'x', states.SUCCESS)
         with pytest.raises(RuntimeError):
             res_subtask_async.get()
         res_subtask_async.get(disable_sync_subtasks=False)