✨ introduce max search horizon config
Adds `MAX_SEARCH_HORIZON` environment variable to control the maximum range of days for search operations. Splits longer search periods into multiple requests, preventing potential performance issues or timeouts with large datasets.
This commit is contained in:
parent
13dc40302c
commit
46e62a94ed
|
|
@ -16,6 +16,7 @@ services:
|
||||||
- SMTP_SERVER=your.smtp.server # adjust this
|
- SMTP_SERVER=your.smtp.server # adjust this
|
||||||
- SMTP_PORT=587 # adjust this if necessary
|
- SMTP_PORT=587 # adjust this if necessary
|
||||||
- SMTP_SENDER_NAME=Room Booking System # adjust this if you want
|
- SMTP_SENDER_NAME=Room Booking System # adjust this if you want
|
||||||
|
- MAX_SEARCH_HORIZON=14 # adjust maximal range of days (longer search periods will get split into multiple requests)
|
||||||
|
|
||||||
volumes:
|
volumes:
|
||||||
app-data:
|
app-data:
|
||||||
|
|
@ -12,10 +12,12 @@ from pprint import pprint
|
||||||
|
|
||||||
import caldav
|
import caldav
|
||||||
import pytz
|
import pytz
|
||||||
from caldav import CalendarObjectResource, Principal, Calendar
|
from caldav import CalendarObjectResource, Principal, Calendar, DAVObject
|
||||||
from jinja2 import Template
|
from jinja2 import Template
|
||||||
|
from django.core.exceptions import ObjectDoesNotExist
|
||||||
|
|
||||||
tz = pytz.timezone(os.getenv("TIME_ZONE", "Europe/Berlin"))
|
tz = pytz.timezone(os.getenv("TIME_ZONE", "Europe/Berlin"))
|
||||||
|
MAX_SEARCH_HORIZON = int(os.getenv("MAX_SEARCH_HORIZON", 14))
|
||||||
|
|
||||||
class DavEvent:
|
class DavEvent:
|
||||||
"""
|
"""
|
||||||
|
|
@ -29,7 +31,7 @@ class DavEvent:
|
||||||
created: datetime
|
created: datetime
|
||||||
status: str
|
status: str
|
||||||
organizer: str
|
organizer: str
|
||||||
calendar: Calendar
|
calendar: DAVObject
|
||||||
obj: CalendarObjectResource
|
obj: CalendarObjectResource
|
||||||
missing_required_fields: list
|
missing_required_fields: list
|
||||||
|
|
||||||
|
|
@ -119,11 +121,10 @@ class DavEvent:
|
||||||
if match:
|
if match:
|
||||||
token = match.group()
|
token = match.group()
|
||||||
print(f"Priority token found in event description: {token}")
|
print(f"Priority token found in event description: {token}")
|
||||||
token_obj = PriorityEventToken.objects.get(token=token)
|
try:
|
||||||
|
token_obj = PriorityEventToken.objects.get(token=token)
|
||||||
# Check if the token object exists in the database
|
except ObjectDoesNotExist:
|
||||||
if not token_obj:
|
print(f"Priority token could not be found in database: {token}")
|
||||||
print(f"Priority token '{token}' not found in database.")
|
|
||||||
return False
|
return False
|
||||||
|
|
||||||
# If token is already used, verify signature
|
# If token is already used, verify signature
|
||||||
|
|
@ -138,7 +139,7 @@ class DavEvent:
|
||||||
# TODO: Notify about invalid token usage
|
# TODO: Notify about invalid token usage
|
||||||
return False
|
return False
|
||||||
|
|
||||||
# If the token hasn't been used yet, redeem it
|
# If the token hasn't been used yet, redeem it
|
||||||
else:
|
else:
|
||||||
print(f"Redeeming priority token '{token}' for event '{uid}'.")
|
print(f"Redeeming priority token '{token}' for event '{uid}'.")
|
||||||
token_obj.redeem(uid)
|
token_obj.redeem(uid)
|
||||||
|
|
@ -263,17 +264,34 @@ def clear(target_calendars: list, is_test: bool=False) -> dict:
|
||||||
print(f"--- Clearing cancelled bookings and overlaps in calendar: {calendar.id}")
|
print(f"--- Clearing cancelled bookings and overlaps in calendar: {calendar.id}")
|
||||||
horizon = tcal_by_name[calendar.id].auto_clear_overlap_horizon_days
|
horizon = tcal_by_name[calendar.id].auto_clear_overlap_horizon_days
|
||||||
|
|
||||||
try:
|
# Split horizon search into multiple requests if horizon is bigger
|
||||||
events_fetched = calendar.search(
|
# than MAX_SEARCH_HORIZON
|
||||||
start=datetime.now(),
|
horizons = []
|
||||||
end=date.today() + timedelta(days=horizon),
|
while horizon > 0:
|
||||||
event=True,
|
if horizon >= MAX_SEARCH_HORIZON:
|
||||||
expand=True,
|
horizons.append(MAX_SEARCH_HORIZON)
|
||||||
split_expanded=True,
|
else:
|
||||||
)
|
horizons.append(horizon)
|
||||||
except Exception as e:
|
horizon -= MAX_SEARCH_HORIZON
|
||||||
print(f"--- Failed to fetch events for calendar: {calendar.id}: {e}")
|
|
||||||
continue
|
events_fetched = []
|
||||||
|
start_delta = 0
|
||||||
|
end_delta = 0
|
||||||
|
today = datetime.now(tz=tz).date()
|
||||||
|
for h in horizons:
|
||||||
|
end_delta += h
|
||||||
|
try:
|
||||||
|
events_fetched.extend(calendar.search(
|
||||||
|
start=today + timedelta(days=start_delta),
|
||||||
|
end=today + timedelta(days=end_delta),
|
||||||
|
event=True,
|
||||||
|
expand=True,
|
||||||
|
split_expanded=True,
|
||||||
|
))
|
||||||
|
except Exception as e:
|
||||||
|
print(f"--- Failed to fetch events for calendar: {calendar.id}: {e}")
|
||||||
|
continue
|
||||||
|
start_delta += h
|
||||||
|
|
||||||
# Create DavEvent objects from fetched events
|
# Create DavEvent objects from fetched events
|
||||||
events = []
|
events = []
|
||||||
|
|
@ -348,7 +366,6 @@ def clear(target_calendars: list, is_test: bool=False) -> dict:
|
||||||
elif not event.is_cancelled:
|
elif not event.is_cancelled:
|
||||||
if not is_test:
|
if not is_test:
|
||||||
event.cancel()
|
event.cancel()
|
||||||
is_cancelled = True
|
|
||||||
result["cancellation_type"] = "cancelled"
|
result["cancellation_type"] = "cancelled"
|
||||||
results["cancelled_overlapping_recurring_events"].append(result)
|
results["cancelled_overlapping_recurring_events"].append(result)
|
||||||
print("Cancelled overlapping recurring event:")
|
print("Cancelled overlapping recurring event:")
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue