# Buggy code
def ws_connect(message):
    if not message.user.is_authenticated():
        logger.error("Request user is not authenticated to use websocket.")
        message.reply_channel.send({"close": True})
        return
    else:
        message.reply_channel.send({"accept": True})

    data = urlparse.parse_qs(message.content["query_string"])
    inventory_id = parse_inventory_id(data)
    topology_ids = list(
        TopologyInventory.objects.filter(inventory_id=inventory_id).values_list(
            "pk", flat=True
        )
    )
    topology_id = None
    if len(topology_ids) > 0:
        topology_id = topology_ids[0]
    if topology_id is not None:
        topology = Topology.objects.get(pk=topology_id)
    else:
        topology = Topology(name="topology", scale=1.0, panX=0, panY=0)
        topology.save()
        TopologyInventory(inventory_id=inventory_id, topology_id=topology.pk).save()
    topology_id = topology.pk
    message.channel_session["topology_id"] = topology_id
    Group("topology-%s" % topology_id).add(message.reply_channel)
    client = Client()
    client.save()
    message.channel_session["client_id"] = client.pk
    Group("client-%s" % client.pk).add(message.reply_channel)
    message.reply_channel.send({"text": json.dumps(["id", client.pk])})
    message.reply_channel.send({"text": json.dumps(["topology_id", topology_id])})
    topology_data = transform_dict(
        dict(
            id="topology_id",
            name="name",
            panX="panX",
            panY="panY",
            scale="scale",
            link_id_seq="link_id_seq",
            device_id_seq="device_id_seq",
        ),
        topology.__dict__,
    )

    message.reply_channel.send({"text": json.dumps(["Topology", topology_data])})
    send_snapshot(message.reply_channel, topology_id)


# 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 ws_connect(message):
    if not message.user.is_authenticated():
        logger.error("Request user is not authenticated to use websocket.")
        message.reply_channel.send({"close": True})
        return
    else:
        message.reply_channel.send({"accept": True})

    data = urlparse.parse_qs(message.content["query_string"])
    inventory_id = parse_inventory_id(data)
    topology_ids = list(
        TopologyInventory.objects.filter(inventory_id=inventory_id).values_list(
            "pk", flat=True
        )
    )
    topology_id = None
    if len(topology_ids) > 0:
        topology_id = topology_ids[0]
    if topology_id is not None:
        topology = Topology.objects.get(pk=topology_id)
    else:
        topology = Topology(name="topology", scale=1.0, panX=0, panY=0)
        topology.save()
        TopologyInventory(inventory_id=inventory_id, topology_id=topology.pk).save()
    topology_id = topology.pk
    message.channel_session["topology_id"] = topology_id
    channels.Group("topology-%s" % topology_id).add(message.reply_channel)
    client = Client()
    client.save()
    message.channel_session["client_id"] = client.pk
    channels.Group("client-%s" % client.pk).add(message.reply_channel)
    message.reply_channel.send({"text": json.dumps(["id", client.pk])})
    message.reply_channel.send({"text": json.dumps(["topology_id", topology_id])})
    topology_data = transform_dict(
        dict(
            id="topology_id",
            name="name",
            panX="panX",
            panY="panY",
            scale="scale",
            link_id_seq="link_id_seq",
            device_id_seq="device_id_seq",
        ),
        topology.__dict__,
    )

    message.reply_channel.send({"text": json.dumps(["Topology", topology_data])})
    send_snapshot(message.reply_channel, topology_id)