# Buggy code
def housekeeping(self, expired_threshold, info_threshold):
    # delete 'closed' or 'expired' alerts older than "expired_threshold" hours
    # and 'informational' alerts older than "info_threshold" hours
    expired_hours_ago = datetime.utcnow() - timedelta(hours=expired_threshold)
    g.db.alerts.remove(
        {
            "status": {"$in": ["closed", "expired"]},
            "lastReceiveTime": {"$lt": expired_hours_ago},
        }
    )

    info_hours_ago = datetime.utcnow() - timedelta(hours=info_threshold)
    g.db.alerts.remove(
        {"severity": "informational", "lastReceiveTime": {"$lt": info_hours_ago}}
    )

    # get list of alerts to be newly expired
    pipeline = [
        {
            "$project": {
                "event": 1,
                "status": 1,
                "lastReceiveId": 1,
                "timeout": 1,
                "expireTime": {
                    "$add": ["$lastReceiveTime", {"$multiply": ["$timeout", 1000]}]
                },
            }
        },
        {
            "$match": {
                "status": {"$nin": ["expired", "shelved"]},
                "expireTime": {"$lt": datetime.utcnow()},
                "timeout": {"$ne": 0},
            }
        },
    ]
    expired = [
        (r["_id"], r["event"], r["lastReceiveId"])
        for r in g.db.alerts.aggregate(pipeline)
    ]

    # get list of alerts to be unshelved
    pipeline = [
        {
            "$project": {
                "event": 1,
                "status": 1,
                "lastReceiveId": 1,
                "timeout": 1,
                "expireTime": {
                    "$add": ["$lastReceiveTime", {"$multiply": ["$timeout", 1000]}]
                },
            }
        },
        {
            "$match": {
                "status": "shelved",
                "expireTime": {"$lt": datetime.utcnow()},
                "timeout": {"$ne": 0},
            }
        },
    ]
    unshelved = [
        (r["_id"], r["event"], r["lastReceiveId"])
        for r in g.db.alerts.aggregate(pipeline)
    ]

    return (expired, unshelved)


# Traceback (ApiError)
2018-04-28 00:06:43,862 - alerta[18702]: ERROR - HOUSEKEEPING FAILED: Type names and field names can only contain alphanumeric characters and underscores: '?column?' [in /usr/lib/python2.7/site-packages/alerta_server-5.2.0_-py2.7.egg/alerta/exceptions.py:67]
Traceback (most recent call last):
File "/usr/lib/python2.7/site-packages/flask/app.py", line 1612, in full_dispatch_request
rv = self.dispatch_request()
File "/usr/lib/python2.7/site-packages/flask/app.py", line 1598, in dispatch_request
return self.view_functions[rule.endpoint](**req.view_args)
File "/usr/lib/python2.7/site-packages/flask_cors/decorator.py", line 128, in wrapped_function
resp = make_response(f(*args, **kwargs))
File "/usr/lib/python2.7/site-packages/alerta_server-5.2.0_-py2.7.egg/alerta/auth/utils.py", line 95, in wrapped
return f(*args, **kwargs)
File "/usr/lib/python2.7/site-packages/alerta_server-5.2.0_-py2.7.egg/alerta/management/views.py", line 148, in housekeeping
raise ApiError('HOUSEKEEPING FAILED: %s' % e, 503)
ApiError: HOUSEKEEPING FAILED: Type names and field names can only contain alphanumeric characters and underscores: '?column?'

# Fixed code
def housekeeping(self, expired_threshold, info_threshold):
    # delete 'closed' or 'expired' alerts older than "expired_threshold" hours
    # and 'informational' alerts older than "info_threshold" hours
    expired_hours_ago = datetime.utcnow() - timedelta(hours=expired_threshold)
    g.db.alerts.remove(
        {
            "status": {"$in": ["closed", "expired"]},
            "lastReceiveTime": {"$lt": expired_hours_ago},
        }
    )

    info_hours_ago = datetime.utcnow() - timedelta(hours=info_threshold)
    g.db.alerts.remove(
        {"severity": "informational", "lastReceiveTime": {"$lt": info_hours_ago}}
    )

    # get list of alerts to be newly expired
    pipeline = [
        {
            "$project": {
                "event": 1,
                "status": 1,
                "lastReceiveId": 1,
                "timeout": 1,
                "expireTime": {
                    "$add": ["$lastReceiveTime", {"$multiply": ["$timeout", 1000]}]
                },
            }
        },
        {
            "$match": {
                "status": {"$nin": ["expired", "shelved"]},
                "expireTime": {"$lt": datetime.utcnow()},
                "timeout": {"$ne": 0},
            }
        },
    ]
    expired = [
        (r["_id"], r["event"], r["lastReceiveId"])
        for r in g.db.alerts.aggregate(pipeline)
    ]

    # get list of alerts to be unshelved
    pipeline = [
        {"$match": {"status": "shelved"}},
        {"$unwind": "$history"},
        {"$match": {"history.type": "action", "history.status": "shelved"}},
        {"$sort": {"history.updateTime": -1}},
        {
            "$group": {
                "_id": "$_id",
                "event": {"$first": "$event"},
                "lastReceiveId": {"$first": "$lastReceiveId"},
                "updateTime": {"$first": "$history.updateTime"},
                "timeout": {"$first": "$timeout"},
            }
        },
        {
            "$project": {
                "event": 1,
                "lastReceiveId": 1,
                "expireTime": {
                    "$add": ["$updateTime", {"$multiply": ["$timeout", 1000]}]
                },
            }
        },
        {"$match": {"expireTime": {"$lt": datetime.utcnow()}, "timeout": {"$ne": 0}}},
    ]
    unshelved = [
        (r["_id"], r["event"], r["lastReceiveId"])
        for r in g.db.alerts.aggregate(pipeline)
    ]

    return (expired, unshelved)