Skip to content

Commit edaefa6

Browse files
committed
Refactor some code
1 parent b199d7c commit edaefa6

File tree

10 files changed

+83
-220
lines changed

10 files changed

+83
-220
lines changed

cdk.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -198,7 +198,7 @@ def __init__(
198198

199199

200200
if __name__ == "__main__":
201-
config = config_module.get_config()
201+
config = config_module.config
202202
app = aws_cdk.App()
203203
notico_queue = NoticoQueue(scope=app, id="notico-queue", config=config)
204204
notico_ecr = NotiCoEcr(scope=app, id="notico-ecr", config=config)

runtime/app.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
import typing
44

55
import chalice.app
6-
import chalicelib.config
6+
import chalicelib.config as config_module
77
import chalicelib.logger.slack as slack_logger
88
import chalicelib.route
99
import chalicelib.worker
@@ -16,7 +16,7 @@
1616
SQSEventType = dict[str, typing.Any]
1717

1818

19-
config = chalicelib.config.get_config()
19+
config = config_module.config
2020
app = chalice.app.Chalice(app_name="notico")
2121
app.log.setLevel(logging.INFO)
2222

@@ -38,7 +38,7 @@ def sqs_handler(event: chalice.app.SQSEvent) -> list[dict[str, typing.Any]]:
3838
for record in parsed_event["Records"]:
3939
try:
4040
worker_name = json.loads(record["body"])["worker"]
41-
result = chalicelib.worker.workers[worker_name](app=app, config=config, record=record)
41+
result = chalicelib.worker.workers[worker_name](app=app, record=record)
4242
results.append(result)
4343
except Exception as e:
4444
app.log.error(f"Failed to handle event: {record}", exc_info=e)

runtime/chalicelib/aws_resource.py

Lines changed: 35 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
1+
import dataclasses
12
import enum
3+
import functools
24
import typing
35

46
import boto3
5-
import chalicelib.config
7+
import chalicelib.config as config_module
68

79
if typing.TYPE_CHECKING:
810
import mypy_boto3_s3.client
@@ -15,11 +17,37 @@
1517
s3_client: "mypy_boto3_s3.client.S3Client" = boto3.client(service_name="s3")
1618

1719

18-
class S3ResourcePath(enum.StrEnum):
19-
email_template = "email/template/{filename}.html"
20+
@dataclasses.dataclass
21+
class S3ResourceInfo:
22+
prefix: str
23+
extension: str
2024

21-
def as_path(self, filename: str) -> str:
22-
return self.value.format(filename=filename)
25+
def as_path(self, code: str) -> str:
26+
return self.prefix + f"{code}.{self.extension}"
2327

24-
def download(self, conf: chalicelib.config.Config, filename: str) -> bytes:
25-
return s3_client.get_object(Bucket=conf.infra.s3_bucket_name, Key=self.as_path(filename))["Body"].read()
28+
29+
class S3ResourcePath(enum.Enum):
30+
email_template = S3ResourceInfo(prefix="email/template/", extension="json")
31+
telegram_template = S3ResourceInfo(prefix="telegram/template/", extension="json")
32+
firebase_template = S3ResourceInfo(prefix="firebase/template/", extension="json")
33+
34+
@functools.cached_property
35+
def s3_bucket_name(self) -> config_module.InfraConfig:
36+
return config_module.config.infra.s3_bucket_name
37+
38+
def download(self, code: str) -> bytes:
39+
return s3_client.get_object(Bucket=self.s3_bucket_name, Key=self.value.as_path(code))["Body"].read()
40+
41+
def upload(self, code: str, content: str) -> None:
42+
s3_client.put_object(Bucket=self.s3_bucket_name, Key=self.value.as_path(code), Body=content)
43+
44+
def delete(self, code: str) -> None:
45+
s3_client.delete_object(Bucket=self.s3_bucket_name, Key=self.value.as_path(code))
46+
47+
def list_objects(self, filter_by_extension: bool = False) -> list[str]:
48+
return [
49+
key
50+
for obj in s3_client.list_objects(Bucket=self.s3_bucket_name, Prefix=self.value.prefix)["Contents"]
51+
if (key := obj["Key"].replace(self.value.prefix, ""))
52+
and (not filter_by_extension or key.split(".")[-1] == self.value.extension)
53+
]

runtime/chalicelib/config.py

Lines changed: 22 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import functools
1+
import logging
22
import typing
33
import urllib.parse
44

@@ -7,6 +7,16 @@
77
import pydantic_settings
88

99
AllowedToastServices = typing.Literal["alimtalk"]
10+
logger = logging.getLogger(__name__)
11+
12+
13+
def log_request(req: httpx.Request) -> None:
14+
logger.debug(f"REQ [{req.method}]{req.url}")
15+
16+
17+
def log_response(resp: httpx.Response) -> None:
18+
req = resp.request
19+
logger.debug(f"RES [{req.method}]{req.url}<{resp.status_code}> {resp.content.decode(errors='ignore')=}")
1020

1121

1222
class InfraConfig(pydantic_settings.BaseSettings):
@@ -46,6 +56,7 @@ def get_session(self, service: AllowedToastServices) -> httpx.Client:
4656
"Content-Type": "application/json;charset=UTF-8",
4757
},
4858
timeout=self.timeout,
59+
event_hooks={"request": [log_request], "response": [log_response]},
4960
)
5061

5162

@@ -55,6 +66,15 @@ class FirebaseConfig(_ServiceConfig, pydantic_settings.BaseSettings):
5566

5667
class TelegramConfig(_ServiceConfig, pydantic_settings.BaseSettings):
5768
bot_token: pydantic.SecretStr | None = None
69+
timeout: float = 3.0
70+
71+
def get_session(self) -> httpx.Client:
72+
return httpx.Client(
73+
base_url=f"https://api.telegram.org/bot{self.bot_token.get_secret_value()}/",
74+
headers={"Content-Type": "application/json;charset=UTF-8"},
75+
timeout=self.timeout,
76+
event_hooks={"request": [log_request], "response": [log_response]},
77+
)
5878

5979

6080
class SlackConfig(_ServiceConfig, pydantic_settings.BaseSettings):
@@ -72,6 +92,4 @@ class Config(pydantic_settings.BaseSettings):
7292
env_vars: dict[str, str] = pydantic.Field(default_factory=dict)
7393

7494

75-
@functools.lru_cache(maxsize=1)
76-
def get_config() -> Config:
77-
return Config(_env_nested_delimiter="__", _case_sensitive=False)
95+
config = Config(_env_nested_delimiter="__", _case_sensitive=False)

runtime/chalicelib/sender/__interface__.py

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
import chalicelib.config as config_module
21
import pydantic
32

43
ReceiverType = str
@@ -15,5 +14,3 @@ class NotificationSendRequest(pydantic.BaseModel):
1514
template_code: str
1615
shared_context: ContextType
1716
personalized_context: dict[ReceiverType, ContextType]
18-
19-
conf: config_module.Config

runtime/chalicelib/sender/aws_ses.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -61,8 +61,7 @@ def validate_shared_context(cls, v: sender_interface.ContextType) -> sender_inte
6161
def to_aws_ses_request(self) -> list[AWSSESRequest]:
6262
title_template = self.shared_context["title"]
6363
body_template = chalicelib.aws_resource.S3ResourcePath.email_template.download(
64-
conf=self.conf,
65-
filename=self.template_code,
64+
code=self.template_code,
6665
).decode("utf-8")
6766

6867
return [

runtime/chalicelib/sender/firebase_cloudmessaging.py

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
import logging
55
import typing
66

7-
import chalicelib.config
7+
import chalicelib.config as config_module
88
import firebase_admin
99
import firebase_admin.credentials
1010
import firebase_admin.messaging
@@ -51,8 +51,6 @@ class FirebaseCloudMessaging(pydantic.BaseModel):
5151
webpush: firebase_admin.messaging.WebpushConfig | None = None
5252
fcm_options: firebase_admin.messaging.FCMOptions | None = None
5353

54-
conf: chalicelib.config.FirebaseConfig
55-
5654
model_config = pydantic.ConfigDict(arbitrary_types_allowed=True)
5755

5856
@pydantic.field_validator("data", mode="before")
@@ -88,13 +86,13 @@ def message_payloads(self) -> list[firebase_admin.messaging.Message]:
8886
]
8987

9088
def send(self) -> str:
91-
if not self.conf.is_configured():
89+
if not config_module.config.firebase.is_configured():
9290
raise ValueError("Firebase configuration is not set up properly.")
9391

9492
with contextlib.suppress(ValueError):
9593
firebase_admin.initialize_app(
9694
credential=firebase_admin.credentials.Certificate(
97-
cert=self.conf.certificate.get_secret_value(),
95+
cert=config_module.config.firebase.certificate.get_secret_value(),
9896
)
9997
)
10098

0 commit comments

Comments
 (0)