Skip to content

Commit 9d55322

Browse files
committed
perf: cache timezone objects at module level for better performance
Cache frequently instantiated timezone objects (UTC and available timezones) at module level to avoid repeated overhead: - Cache available_timezones() set in trigger_models.py to prevent repeated filesystem queries during timezone validation - Cache ZoneInfo("UTC") constant in trigger_cron.py and verify_graph.py to avoid repeated ZoneInfo instantiation in hot paths These optimizations reduce unnecessary overhead in functions that are called frequently, particularly in cron trigger scheduling operations. Signed-off-by: Sparsh <sparsh.raj30@gmail.com>
1 parent 4b065e4 commit 9d55322

3 files changed

Lines changed: 15 additions & 6 deletions

File tree

state-manager/app/models/trigger_models.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,9 @@
44
from typing import Self, Optional
55
from zoneinfo import available_timezones
66

7+
# Cache available timezones at module level to avoid repeated filesystem queries
8+
_AVAILABLE_TIMEZONES = available_timezones()
9+
710
class TriggerTypeEnum(str, Enum):
811
CRON = "CRON"
912

@@ -30,7 +33,7 @@ def validate_expression(cls, v: str) -> str:
3033
def validate_timezone(cls, v: Optional[str]) -> str:
3134
if v is None:
3235
return "UTC"
33-
if v not in available_timezones():
36+
if v not in _AVAILABLE_TIMEZONES:
3437
raise ValueError(f"Invalid timezone: {v}. Must be a valid IANA timezone (e.g., 'America/New_York', 'Europe/London', 'UTC')")
3538
return v
3639

state-manager/app/tasks/trigger_cron.py

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,9 @@
1212
import croniter
1313
import asyncio
1414

15+
# Cache UTC timezone at module level to avoid repeated instantiation
16+
UTC = ZoneInfo("UTC")
17+
1518
logger = LogsManager().get_logger()
1619

1720
async def get_due_triggers(cron_time: datetime) -> DatabaseTriggers | None:
@@ -48,15 +51,15 @@ async def create_next_triggers(trigger: DatabaseTriggers, cron_time: datetime):
4851
tz = ZoneInfo(trigger.timezone or "UTC")
4952

5053
# Convert trigger_time to the specified timezone for croniter
51-
trigger_time_tz = trigger.trigger_time.replace(tzinfo=ZoneInfo("UTC")).astimezone(tz)
54+
trigger_time_tz = trigger.trigger_time.replace(tzinfo=UTC).astimezone(tz)
5255
iter = croniter.croniter(trigger.expression, trigger_time_tz)
5356

5457
while True:
5558
# Get next trigger time in the specified timezone
5659
next_trigger_time_tz = iter.get_next(datetime)
5760

5861
# Convert back to UTC for storage
59-
next_trigger_time = next_trigger_time_tz.astimezone(ZoneInfo("UTC")).replace(tzinfo=None)
62+
next_trigger_time = next_trigger_time_tz.astimezone(UTC).replace(tzinfo=None)
6063

6164
try:
6265
await DatabaseTriggers(

state-manager/app/tasks/verify_graph.py

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,9 @@
1212
from app.models.trigger_models import TriggerStatusEnum, TriggerTypeEnum
1313
from app.models.db.trigger import DatabaseTriggers
1414

15+
# Cache UTC timezone at module level to avoid repeated instantiation
16+
UTC = ZoneInfo("UTC")
17+
1518
logger = LogsManager().get_logger()
1619

1720
async def verify_node_exists(graph_template: GraphTemplate, registered_nodes: list[RegisteredNode]) -> list[str]:
@@ -111,22 +114,22 @@ async def create_crons(graph_template: GraphTemplate):
111114
cron_trigger = CronTrigger.model_validate(trigger.value)
112115
triggers_to_create[(cron_trigger.expression, cron_trigger.timezone)] = cron_trigger
113116

114-
current_time = datetime.now(ZoneInfo("UTC")).replace(tzinfo=None)
117+
current_time = datetime.now(UTC).replace(tzinfo=None)
115118

116119
new_db_triggers = []
117120
for (expression, timezone), cron_trigger in triggers_to_create.items():
118121
# Use the validated timezone (guaranteed to be valid IANA timezone, never None)
119122
tz = ZoneInfo(timezone)
120123

121124
# Get current time in the specified timezone
122-
current_time_tz = current_time.replace(tzinfo=ZoneInfo("UTC")).astimezone(tz)
125+
current_time_tz = current_time.replace(tzinfo=UTC).astimezone(tz)
123126
iter = croniter.croniter(expression, current_time_tz)
124127

125128
# Get next trigger time in the specified timezone
126129
next_trigger_time_tz = iter.get_next(datetime)
127130

128131
# Convert back to UTC for storage (remove timezone info for storage)
129-
next_trigger_time = next_trigger_time_tz.astimezone(ZoneInfo("UTC")).replace(tzinfo=None)
132+
next_trigger_time = next_trigger_time_tz.astimezone(UTC).replace(tzinfo=None)
130133

131134
new_db_triggers.append(
132135
DatabaseTriggers(

0 commit comments

Comments
 (0)