add support to save executed scheduled

This commit is contained in:
2025-12-12 11:09:56 -03:00
parent 3954b148fe
commit 3895e953af
2 changed files with 61 additions and 22 deletions

View File

@@ -1,7 +1,7 @@
from datetime import date, datetime, time, timedelta from datetime import date, datetime, time, timedelta
from decimal import Decimal from decimal import Decimal
from http import HTTPStatus from http import HTTPStatus
from typing import Annotated from typing import Annotated, TypedDict
from uuid import uuid4 from uuid import uuid4
import pytz import pytz
@@ -18,7 +18,6 @@ from layercake.dynamodb import DynamoDBPersistenceLayer, KeyPair
from layercake.extra_types import CpfStr, NameStr from layercake.extra_types import CpfStr, NameStr
from layercake.strutils import md5_hash from layercake.strutils import md5_hash
from pydantic import UUID4, BaseModel, EmailStr, Field, FutureDate from pydantic import UUID4, BaseModel, EmailStr, Field, FutureDate
from typing_extensions import TypedDict
from boto3clients import dynamodb_client from boto3clients import dynamodb_client
from config import DEDUP_WINDOW_OFFSET_DAYS, ENROLLMENT_TABLE, TZ, USER_TABLE from config import DEDUP_WINDOW_OFFSET_DAYS, ENROLLMENT_TABLE, TZ, USER_TABLE
@@ -276,10 +275,13 @@ def enroll_later(enrollment: Enrollment, context: Context):
lock_hash = md5_hash(f'{user.id}{course.id}') lock_hash = md5_hash(f'{user.id}{course.id}')
with dyn.transact_writer() as transact: with dyn.transact_writer() as transact:
pk = f'SCHEDULED#ORG#{org.id}'
sk = f'{scheduled_for.isoformat()}#{lock_hash}'
transact.put( transact.put(
item={ item={
'id': f'SCHEDULED#ORG#{org.id}', 'id': pk,
'sk': f'{scheduled_for.isoformat()}#{lock_hash}', 'sk': sk,
'user': user.model_dump(), 'user': user.model_dump(),
'course': course.model_dump(), 'course': course.model_dump(),
'org_name': org.name, 'org_name': org.name,
@@ -301,6 +303,10 @@ def enroll_later(enrollment: Enrollment, context: Context):
item={ item={
'id': 'LOCK#SCHEDULED', 'id': 'LOCK#SCHEDULED',
'sk': lock_hash, 'sk': lock_hash,
'scheduled': {
'id': pk,
'sk': sk,
},
'created_at': now_, 'created_at': now_,
}, },
cond_expr='attribute_not_exists(sk)', cond_expr='attribute_not_exists(sk)',

View File

@@ -6,7 +6,9 @@ from aws_lambda_powertools.utilities.data_classes import (
event_source, event_source,
) )
from aws_lambda_powertools.utilities.typing import LambdaContext from aws_lambda_powertools.utilities.typing import LambdaContext
from layercake.dateutils import now
from layercake.dynamodb import DynamoDBPersistenceLayer from layercake.dynamodb import DynamoDBPersistenceLayer
from layercake.funcs import pick
from boto3clients import dynamodb_client from boto3clients import dynamodb_client
from config import ENROLLMENT_TABLE from config import ENROLLMENT_TABLE
@@ -20,6 +22,8 @@ dyn = DynamoDBPersistenceLayer(ENROLLMENT_TABLE, dynamodb_client)
@logger.inject_lambda_context @logger.inject_lambda_context
def lambda_handler(event: EventBridgeEvent, context: LambdaContext) -> bool: def lambda_handler(event: EventBridgeEvent, context: LambdaContext) -> bool:
old_image = event.detail['old_image'] old_image = event.detail['old_image']
sk = old_image['sk']
now_ = now()
# Key pattern `SCHEDULED#ORG#{org_id}` # Key pattern `SCHEDULED#ORG#{org_id}`
*_, org_id = old_image['id'].split('#') *_, org_id = old_image['id'].split('#')
offset_days = old_image.get('dedup_window_offset_days') offset_days = old_image.get('dedup_window_offset_days')
@@ -30,23 +34,52 @@ def lambda_handler(event: EventBridgeEvent, context: LambdaContext) -> bool:
user=old_image['user'], user=old_image['user'],
) )
return enroll( try:
enrollment, enroll(
org={ enrollment,
'org_id': org_id, org={
'name': old_image['org_name'],
},
subscription=(
{
'org_id': org_id, 'org_id': org_id,
'billing_day': int(billing_day), 'name': old_image['org_name'],
},
subscription=(
{
'org_id': org_id,
'billing_day': int(billing_day),
}
if billing_day
else None
),
created_by=created_by,
scheduled_at=datetime.fromisoformat(old_image['created_at']),
# Transfer the deduplication window if it exists
deduplication_window={'offset_days': offset_days} if offset_days else None,
persistence_layer=dyn,
)
keys = ('id', 'name')
dyn.put_item(
item={
'id': old_image['id'],
'sk': f'{sk}#EXECUTED',
'enrollment_id': enrollment.id,
'user': pick(keys, old_image['user']),
'course': pick(keys, old_image['course']),
'created_by': created_by,
'created_at': now_,
} }
if billing_day )
else None except Exception as exc:
), dyn.put_item(
created_by=created_by, item={
scheduled_at=datetime.fromisoformat(old_image['created_at']), 'id': old_image['id'],
# Transfer the deduplication window if it exists 'sk': f'{sk}#FAILED',
deduplication_window={'offset_days': offset_days} if offset_days else None, 'cause': {
persistence_layer=dyn, 'type': type(exc).__name__,
) 'message': str(exc),
},
'snapshot': old_image,
'created_at': now_,
}
)
return True