[CatchLounge] 특정 시간에 작동하는 코드 - apscheduler
1. 개요
자리 예약을 하는 프로젝트를 진행하면서,
- 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로 명시해 주었다.