미소를뿌리는감자의 코딩

[CatchLounge] 특정 시간에 작동하는 코드 - apscheduler 본문

프로젝트

[CatchLounge] 특정 시간에 작동하는 코드 - apscheduler

미뿌감 2024. 9. 5. 12:27
728x90

1. 개요

자리 예약을 하는 프로젝트를 진행하면서,

  1. 2시간이 지나면 자동으로 퇴실
  2. 새벽 2시가 지나면 모든 자리 퇴실

하는 기능 구현을 필요로 했다.

 

이를 apscheduler를 이용해서 적용해 보았다.

 

2. 코드

우선 2시간이 지나면 자동으로 퇴실되는 코드를 살펴보자.

from apscheduler.schedulers.background import BackgroundScheduler
scheduler = BackgroundScheduler()
scheduler.start()

@app.route("/reserve", methods=["POST"])
@token_required
def reserve_table(current_user):

    is_reserved = int(current_user.get("is_reserved", "0"))
    if is_reserved > 0:
        return jsonify({"result": "fail", "message": "이미 예약하셨습니다."}), 400

    tableNum_receive = request.form["tableNum_give"]
    time = datetime.now() + timedelta(seconds=15)
    tableNum = int(tableNum_receive)
    collection_table.update_one(
        {"tableNum": int(tableNum_receive)},
        {
            "$set": {
                "occupied": True,
                "user_name": current_user["username"],
                "time": time,
            }
        },
    )

    collection_user.update_one(
        {"_id": current_user["_id"]}, {"$set": {"is_reserved": tableNum_receive}}
    )
    scheduler.add_job(auto_checkout, "date", run_date=time, args=[tableNum])
    emit_db_update()
    return jsonify({"result": "success", "message": "예약이 완료되었습니다."})

 

위에는 좌석을 예약하는 코드이다. 

 

    scheduler.add_job(auto_checkout, "date", run_date=time, args=[tableNum])
    emit_db_update()
    return jsonify({"result": "success", "message": "예약이 완료되었습니다."})

 

그 중, 위 코드가 scheduler와 관련된 코드이다. 

"date" 는 지정된 날짜 및 시간에 한 번만 실행되는 작업을 나타내는 표현이다.

(추후에 사용 될, 새벽 2시마다 퇴실되도록 하는 것은 "cron"을 사용한다.)

run_date는 auto_checkout이라는 함수가 실행되게 될 시간을 명시해 준다. 인자로 tableNum 또한 넘겨주었다.

(emit_db_update()는 다음 포스팅에 다룰 예정이다)

 

이제 auto_checkout 코드를 확인해 보자

 

def auto_checkout(table_num):
    table = collection_table.find_one({"tableNum": table_num})
    userName = table.get("user_name")

    collection_table.update_one(
        {"tableNum": table_num},
        {"$set": {"user_name": None, "occupied": False, "time": None}},
    )

    collection_user.update_one({"username": userName}, {"$set": {"is_reserved": 0}})
    emit_db_update()

 

table collection에서 인자로 받았던 table_num을 이용해서 찾아주었다.

또한 해당 자리에 예약 되어 있는 userName 또한 가져와서, user collection에서 해당 user의 is_reserved 상태를 0으로 변경해 주었다.

 

이렇게 실행할 코드를 예약해 놓을 수 있다.

 

다음으로, 특정 시간대마다 모든 자리를 퇴실시키는 코드를 확인해 보자.

def logout_all_users():
    collection_user.update_many({}, {"$set": {"is_reserved": 0}})
    collection_table.update_many(
        {}, {"$set": {"user_name": None, "occupied": False, "time": None}}
    )
    emit_db_update()

scheduler.add_job(logout_all_users, "cron", hour=2, minute=0)

 

"cron"으로 새벽 2시마다 실행되는 코드를 작성하였다.

이는 모든 자리에 대해서 처리를 진행시켜야 하기 때문에, logout_all_users라는 함수를 작성해 주었다.

 

*** 주의 : 특정 시간에 작동하도록 하는 것은, 서버 시간과 application 시간을 명시해주어야 한다.

date // terminal 에서 서버 시간 확인하는 명령어
sudo timedatectl set-timezone Asia/Seoul // 서버 시간대를 Asia/Seoul로 바꾸도록 하는 명령어

 

이것만 해서는 안된다!

 

.python 파일에서도 시간대를 설정해 주어야 한다.

scheduler = BackgroundScheduler(timezone=timezone('Asia/Seoul'))

 

이를 통해, 서버에도 application에서도 Asia/Seoul로 명시해 주었다.

728x90