1
1
import logging
2
2
import os
3
3
import uuid
4
+ import time
4
5
from datetime import datetime
5
6
from typing import List , Dict , Optional
6
7
@@ -65,32 +66,52 @@ async def create_todo(todo: TodoItem):
65
66
logging .error (f"Unexpected error creating todo: { e } " )
66
67
raise HTTPException (status_code = 500 , detail = "Error creating todo" )
67
68
69
+ # Define a Pydantic model for the update request body
70
+ class UpdateTodoRequest (BaseModel ):
71
+ text : str
72
+ completed : Optional [bool ] = None # Include the `completed` field
73
+ timestamp : Optional [int ] = None # Make `timestamp` optional
74
+
68
75
# PUT endpoint to update a todo item
69
76
@app .put ("/todos/{id}" , response_model = TodoItem )
70
- async def update_todo (id : str , timestamp : int , todo : TodoItem ):
77
+ async def update_todo (id : str , request : UpdateTodoRequest ):
78
+ # Use the current timestamp if one is not provided
79
+ timestamp = request .timestamp or int (time .time ())
80
+
81
+ if not request .text :
82
+ raise HTTPException (status_code = 400 , detail = "Missing 'text' in request body" )
83
+
84
+ # Prepare the update expressions
85
+ update_expressions = ["#t = :t" ]
86
+ expression_attribute_names = {"#t" : "text" }
87
+ expression_attribute_values = {":t" : request .text }
88
+
89
+ # Add the `completed` field to the update if it's provided
90
+ if request .completed is not None :
91
+ update_expressions .append ("#c = :c" )
92
+ expression_attribute_names ["#c" ] = "completed"
93
+ expression_attribute_values [":c" ] = request .completed
94
+
95
+ # Construct the UpdateExpression string
96
+ update_expression = "SET " + ", " .join (update_expressions )
97
+
71
98
try :
72
- # Update the item in DynamoDB using both the id and timestamp as keys
99
+ # Update the item in the DynamoDB table
73
100
response = table .update_item (
74
101
Key = {"id" : id , "timestamp" : timestamp },
75
- UpdateExpression = "SET #t = :t, #c = :c" ,
76
- ExpressionAttributeNames = {
77
- "#t" : "text" ,
78
- "#c" : "completed"
79
- },
80
- ExpressionAttributeValues = {
81
- ":t" : todo .text ,
82
- ":c" : todo .completed
83
- },
102
+ UpdateExpression = update_expression ,
103
+ ExpressionAttributeNames = expression_attribute_names ,
104
+ ExpressionAttributeValues = expression_attribute_values ,
84
105
ReturnValues = "ALL_NEW"
85
106
)
86
-
107
+
87
108
updated_todo = response .get ("Attributes" )
88
109
if not updated_todo :
89
110
raise HTTPException (status_code = 404 , detail = "Todo not found" )
90
-
111
+
91
112
logging .debug (f"Updated item: { updated_todo } " )
92
113
return updated_todo
93
-
114
+
94
115
except ClientError as e :
95
116
logging .error (f"ClientError updating todo: { e } " )
96
117
raise HTTPException (status_code = 500 , detail = "Error updating todo" )
@@ -100,15 +121,18 @@ async def update_todo(id: str, timestamp: int, todo: TodoItem):
100
121
101
122
# Delete a todo item in the DynamoDB table
102
123
@app .delete ("/todos/{id}" , status_code = 204 )
103
- async def delete_todo (id : str , timestamp : int ):
124
+ async def delete_todo (id : str , timestamp : Optional [int ] = None ):
125
+ # Use the current timestamp if one is not provided
126
+ timestamp = timestamp or int (time .time ())
127
+
104
128
try :
105
129
# Attempt to delete the item using both the partition key (id) and sort key (timestamp)
106
130
response = table .delete_item (Key = {"id" : id , "timestamp" : timestamp })
107
131
108
132
# Check if the HTTP status code indicates a successful deletion
109
133
status_code = response .get ("ResponseMetadata" , {}).get ("HTTPStatusCode" )
110
134
if status_code != 200 :
111
- logging .warning (f"Delete operation failed for id { id } : { response } " )
135
+ logging .warning (f"Delete operation failed for id { id } and timestamp { timestamp } : { response } " )
112
136
raise HTTPException (status_code = 404 , detail = "Todo not found" )
113
137
114
138
logging .debug (f"Deleted item with id: { id } and timestamp: { timestamp } " )
@@ -123,7 +147,6 @@ async def delete_todo(id: str, timestamp: int):
123
147
logging .error (f"Unexpected error deleting todo with id { id } : { e } " )
124
148
raise HTTPException (status_code = 500 , detail = "Error deleting todo" )
125
149
126
-
127
150
@app .get ("/health" )
128
151
async def health ():
129
152
try :
0 commit comments