# Buggy code
def onLinkDestroy(self, link, topology_id, client_id):
    logger.debug("Link deleted %s", link)
    device_map = dict(
        Device.objects.filter(
            topology_id=topology_id,
            cid__in=[link["from_device_id"], link["to_device_id"]],
        ).values_list("cid", "pk")
    )
    if link["from_device_id"] not in device_map:
        return
    if link["to_device_id"] not in device_map:
        return
    Link.objects.filter(
        cid=link["id"],
        from_device_id=device_map[link["from_device_id"]],
        to_device_id=device_map[link["to_device_id"]],
        from_interface_id=Interface.objects.get(
            device_id=device_map[link["from_device_id"]], cid=link["from_interface_id"]
        ).pk,
        to_interface_id=Interface.objects.get(
            device_id=device_map[link["to_device_id"]], cid=link["to_interface_id"]
        ).pk,
    ).delete()


# Traceback (AttributeError)
[2018-02-15 10:31:51,202: DEBUG/MainProcess] TaskPool: Apply <function _fast_trace_task at 0x1d71c80> (args:('awx.main.tasks.run_project_update', '69545664-1752-4c48-a46c-41b7976d5bd3', {'origin': 'gen280@awx', 'lang': 'py', 'task': 'awx.main.tasks.run_project_update', 'group': None, 'root_id': 'e22c4be1-8d1a-4193-a5e8-03b8c6b25f3a', u'delivery_info': {u'priority': None, u'redelivered': False, u'routing_key': u'tower', u'exchange': u''}, 'expires': None, u'correlation_id': '69545664-1752-4c48-a46c-41b7976d5bd3', 'retries': 0, 'timelimit': [None, None], 'argsrepr': '[18]', 'eta': None, 'parent_id': 'e22c4be1-8d1a-4193-a5e8-03b8c6b25f3a', u'reply_to': 'aef45ebd-7309-34e3-8669-7f378d04708f', 'id': '69545664-1752-4c48-a46c-41b7976d5bd3', 'kwargsrepr': '{}'}, u'[[18], {}, {"chord": null, "callbacks": [{"chord_size": null, "task": "awx.main.tasks.handle_work_success", "subtask_type": null, "kwargs": {"task_actual": {"type": "project_update", "id": 18}}, "args": [], "options": {}, "immutable": false}], "errbacks": [{"chord_size": null, "task": "awx.main.tasks.handle_work_error", "subtask_type": null, "kwargs":... kwargs:{})
[2018-02-15 10:31:51,205: DEBUG/MainProcess] Task accepted: awx.main.tasks.run_project_update[69545664-1752-4c48-a46c-41b7976d5bd3] pid:279
[2018-02-15 10:31:51,221: INFO/ForkPoolWorker-50] Task awx.main.scheduler.tasks.run_job_launch[e22c4be1-8d1a-4193-a5e8-03b8c6b25f3a] succeeded in 0.280421956s: None
2018-02-15 10:31:52,001 ERROR    awx.main.tasks project_update 18 (running) Post run hook errored.
Traceback (most recent call last):
File "/usr/lib/python2.7/site-packages/awx/main/tasks.py", line 997, in run
self.post_run_hook(instance, status, **kwargs)
File "/usr/lib/python2.7/site-packages/awx/main/tasks.py", line 1647, in post_run_hook
fd = open(self.revision_path, 'r')
AttributeError: 'RunProjectUpdate' object has no attribute 'revision_path'
2018-02-15 10:31:52,089 DEBUG    awx.main.tasks Executing error task id <Context: {'origin': 'gen280@awx', u'args': [18], u'chain': None, 'root_id': 'e22c4be1-8d1a-4193-a5e8-03b8c6b25f3a', 'expires': None, u'is_eager': False, u'correlation_id': '69545664-1752-4c48-a46c-41b7976d5bd3', u'chord': None, u'reply_to': 'aef45ebd-7309-34e3-8669-7f378d04708f', '_children': [], 'id': '69545664-1752-4c48-a46c-41b7976d5bd3', 'kwargsrepr': '{}', 'lang': 'py', 'retries': 0, 'task': 'awx.main.tasks.run_project_update', 'group': None, 'timelimit': [None, None], u'delivery_info': {u'priority': None, u'redelivered': False, u'routing_key': u'tower', u'exchange': u''}, u'hostname': u'celery@awx', 'called_directly': False, 'parent_id': 'e22c4be1-8d1a-4193-a5e8-03b8c6b25f3a', 'argsrepr': '[18]', u'errbacks': [{u'chord_size': None, u'task': u'awx.main.tasks.handle_work_error', u'args': [], u'immutable': False, u'subtask_type': None, u'kwargs': {u'subtasks': [{u'type': u'project_update', u'id': 18}]}, u'options': {}}], u'callbacks': [{u'chord_size': None, u'task': u'awx.main.tasks.handle_work_success', u'args': [], u'immutable': False, u'subtask_type': None, u'kwargs': {u'task_actual': {u'type': u'project_update', u'id': 18}}, u'options': {}}], u'kwargs': {}, 'eta': None, '_protected': 1}>, subtasks: [{u'type': u'project_update', u'id': 18}]
2018-02-15 10:31:52,180 WARNING  awx.main.tasks project_update 18 (error) encountered an error (rc=None), please see task stdout for details.
[2018-02-15 10:31:52,181: ERROR/ForkPoolWorker-49] Task awx.main.tasks.run_project_update[69545664-1752-4c48-a46c-41b7976d5bd3] raised unexpected: Exception('project_update 18 (error) encountered an error (rc=None), please see task stdout for details.',)

# Fixed code
def onLinkDestroy(self, link, topology_id, client_id):
    logger.debug("Link deleted %s", link)
    device_map = dict(
        Device.objects.filter(
            topology_id=topology_id,
            cid__in=[link["from_device_id"], link["to_device_id"]],
        ).values_list("cid", "pk")
    )
    if link["from_device_id"] not in device_map:
        logger.warning("Device not found")
        return
    if link["to_device_id"] not in device_map:
        logger.warning("Device not found")
        return
    Link.objects.filter(
        cid=link["id"],
        from_device_id=device_map[link["from_device_id"]],
        to_device_id=device_map[link["to_device_id"]],
        from_interface_id=Interface.objects.get(
            device_id=device_map[link["from_device_id"]], cid=link["from_interface_id"]
        ).pk,
        to_interface_id=Interface.objects.get(
            device_id=device_map[link["to_device_id"]], cid=link["to_interface_id"]
        ).pk,
    ).delete()