Skip to content

Commit

Permalink
Merge pull request #3 from gdsc-ssu/v2
Browse files Browse the repository at this point in the history
Merge with v2
  • Loading branch information
thinkjin99 authored Apr 25, 2024
2 parents 6b165eb + 3dcd062 commit cdec8de
Show file tree
Hide file tree
Showing 11 changed files with 8,319 additions and 205 deletions.
11 changes: 1 addition & 10 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -6,18 +6,9 @@ ENV TZ=Asia/Seoul
# Copy requirements.txt
COPY requirements.txt ${LAMBDA_TASK_ROOT}

#Set aws credentials
ARG AWS_REGION_NAME
ENV AWS_REGION_NAME=$AWS_REGION_NAME

ARG AWS_ACCESS_KEY_ID
ENV AWS_ACCESS_KEY_ID=$AWS_ACCESS_KEY_ID

ARG AWS_SECRET_ACCESS_KEY
ENV AWS_SECRET_ACCESS_KEY=$AWS_SECRET_ACCESS_KEY

#Copy code
COPY *.py ${LAMBDA_TASK_ROOT}
COPY .env ${LAMBDA_TASK_ROOT}

# Install the specified packages
RUN pip install -r requirements.txt
Expand Down
98 changes: 98 additions & 0 deletions api.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
from functools import wraps
import json
import typing


import aiohttp
from aiohttp_retry import RetryClient, ExponentialRetry

from env import *


def create_retry_client(func) -> typing.Callable:
"""
연결에 문제가 발생했을 경우 재시도를 시도할 수 있게 하는 기능을
세션에 추가합니다.
Args:
session (aiohttp.ClientSession): 세션
Returns:
RetryClient: 재시도가 가능한 세션 래핑 객체
"""

@wraps(func)
async def wrapper(*args, **kwargs) -> RetryClient:
session: aiohttp.ClientSession = await func(*args, **kwargs)
retry_options = ExponentialRetry(
attempts=3, statuses={400, 401, 403, 404, 408, 429}
) # 리퀘스트가 너무 많은 경우, 연결 시간이 너무 긴 경우
# 명확하게 해당 코드가 전달된 경우만 재시도
retry_client = RetryClient(
raise_for_status=True, retry_options=retry_options, client_session=session
)
return retry_client

return wrapper


async def read_response(response: aiohttp.ClientResponse) -> dict:
try:
data = await response.json()

except aiohttp.ContentTypeError:
data = json.loads(await response.text())

is_success = data.get("success") # 도서관 api의 자체 응답 코드
if is_success: # 예약 데이터가 존재하는 경우
return data
else:
raise AssertionError("Token expired")


@create_retry_client
async def create_logined_session(
student_id: str, usaint_secret: str, token: str
) -> aiohttp.ClientSession:
"""
로그인을 진행하고 인증 토큰을 발급합니다.
Returns:
str: 인증 토큰 값
"""

session = aiohttp.ClientSession(
base_url="https://oasis.ssu.ac.kr",
timeout=aiohttp.ClientTimeout(total=5),
raise_for_status=True,
)

login_url = "/pyxis-api/api/login" # 로그인 api
payload = {
"loginId": student_id,
"password": usaint_secret,
"isFamilyLogin": False,
"isMobile": False,
}

if not token:
async with session.post(login_url, json=payload) as response:
data = await read_response(response)
token = data["data"]["accessToken"]

headers = {
"Accept": "application/json",
"pyxis-auth-token": token,
}

session.headers.update(headers)
return session


async def call_reservation_api(
session: RetryClient, room_type_id: int, date: str
) -> dict:
url = f"/pyxis-api/1/api/rooms?roomTypeId={room_type_id}&smufMethodCode=PC&hopeDate={date}"
async with session.get(url) as response:
data = await read_response(response)
return data
39 changes: 39 additions & 0 deletions cache/cache_getter.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import json
import redis
import traceback


def create_response(status_code: str | int, cache: str | bytes) -> dict:
response = dict(
{
"isBase64Encoded": False,
"headers": {"Content-Type": "application/json"},
"statusCode": status_code,
"body": cache,
},
)
return response


def lambda_handler(event: dict, context: dict):
try:
rd = redis.Redis(
# host="ssudobi-cache-001.96ug1w.0001.apn2.cache.amazonaws.com",
host="localhost",
port=6379,
socket_timeout=3,
)
room_type_id = event["pathParameters"].get("room_type_id", "1")
cache = rd.get(room_type_id) # set data to redis
response = create_response(200, cache)

except Exception as e:
response = create_response(500, str(e))
print(traceback.format_exc())

finally:
return response


if __name__ == "__main__":
print(lambda_handler({"pathParameters": {"room_type_id": "1"}}, {}))
67 changes: 67 additions & 0 deletions cache/cache_refresher.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
import redis
import boto3
import json
import traceback


def invoke_function(function_name: str, payload: dict | str):
"""
Invokes the specified function and returns the result.
"""
client = boto3.client("lambda")
response = client.invoke(FunctionName=function_name, Payload=json.dumps(payload))
return response


def get_payload(response) -> dict | None:
try:
payload = json.loads(response["Payload"].read().decode("utf-8"))
status_code = payload.pop("statusCode")
assert status_code == 200
return payload

except AssertionError as e:
print("Error occured in request: ", str(e))
raise e


def create_response(status_code: str | int, msg: str) -> dict:
response = {
"isBase64Encoded": False,
"headers": {"Content-Type": "application/json"},
"statusCode": status_code,
"body": msg,
}
return response


def lambda_handler(event: dict, context: dict):
try:
rd = redis.Redis(
host="ssudobi-cache-001.96ug1w.0001.apn2.cache.amazonaws.com",
port=6379,
socket_timeout=3,
)

for room_type_id in (1, 5):
response = invoke_function("cache", {"room_type_id": room_type_id})
if payload := get_payload(response):
rd.set(
str(room_type_id), json.dumps(payload)
) # set data to redis, room_type_id is key

response = create_response(
200,
"Cache Success",
)

except Exception as e:
response = create_response(500, str(e))
print(traceback.format_exc())

finally:
return response


# if __name__ == "__main__":
# lambda_handler({}, {})
Loading

0 comments on commit cdec8de

Please sign in to comment.