@@ -71,26 +71,31 @@ class UpdateTodoRequest(BaseModel):
71
71
text : str
72
72
completed : bool = None # Optional field
73
73
74
- # PUT endpoint to update a todo item
75
- @app .put ("/todos/{id}" , response_model = TodoItem )
74
+ # PATCH endpoint to update a todo item
75
+ @app .patch ("/todos/{id}" , response_model = TodoItem )
76
76
async def update_todo (id : str , request : UpdateTodoRequest , timestamp : int = None ):
77
77
# Use the current timestamp if one is not provided
78
78
timestamp = timestamp or int (time .time ())
79
79
80
- if not request .text :
81
- raise HTTPException (status_code = 400 , detail = "Missing 'text' in request body" )
80
+ # Initialize the list of update expressions and expression attributes
81
+ update_expressions = []
82
+ expression_attribute_names = {}
83
+ expression_attribute_values = {}
82
84
83
- # Prepare the update expressions
84
- update_expressions = ["#t = :t" ]
85
- expression_attribute_names = {"#t" : "text" }
86
- expression_attribute_values = {":t" : request .text }
85
+ # Only include fields that are present in the request
86
+ if request .text :
87
+ update_expressions .append ("#t = :t" )
88
+ expression_attribute_names ["#t" ] = "text"
89
+ expression_attribute_values [":t" ] = request .text
87
90
88
- # Add the `completed` field to the update if it's provided
89
91
if request .completed is not None :
90
92
update_expressions .append ("#c = :c" )
91
93
expression_attribute_names ["#c" ] = "completed"
92
94
expression_attribute_values [":c" ] = request .completed
93
95
96
+ if not update_expressions :
97
+ raise HTTPException (status_code = 400 , detail = "No fields provided to update" )
98
+
94
99
# Construct the UpdateExpression string
95
100
update_expression = "SET " + ", " .join (update_expressions )
96
101
@@ -118,29 +123,32 @@ async def update_todo(id: str, request: UpdateTodoRequest, timestamp: int = None
118
123
logging .error (f"Error updating todo: { e } " )
119
124
raise HTTPException (status_code = 500 , detail = "Error updating todo" )
120
125
126
+
121
127
# Delete a todo item in the DynamoDB table (using only `id` as the partition key)
122
128
@app .delete ("/todos/{id}" , status_code = 204 )
123
- async def delete_todo (id : str ):
129
+ async def delete_todo (id : str , timestamp : int = None ):
124
130
try :
125
- # If the table uses only `id` as the partition key, we don't need a timestamp
126
- response = table .delete_item (Key = {"id" : id })
131
+ # If timestamp is not provided, use the current timestamp
132
+ timestamp = timestamp or int (time .time ())
133
+
134
+ # Attempt to delete the item using both the partition key (id) and sort key (timestamp)
135
+ response = table .delete_item (Key = {"id" : id , "timestamp" : timestamp })
127
136
128
- # Check if the deletion was successful by checking the response metadata
129
- if response . get ( "ResponseMetadata" , {}) .get ("HTTPStatusCode" ) != 200 :
130
- logging .warning (f"Delete operation failed for id { id } : { response } " )
137
+ # Check if the HTTP status code indicates a successful deletion
138
+ if "ResponseMetadata" not in response or response [ "ResponseMetadata" ] .get ("HTTPStatusCode" ) != 200 :
139
+ logging .warning (f"Delete operation failed for id { id } and timestamp { timestamp } : { response } " )
131
140
raise HTTPException (status_code = 404 , detail = "Todo not found" )
132
141
133
- logging .debug (f"Deleted item with id: { id } " )
134
-
142
+ logging .debug (f"Deleted item with id: { id } and timestamp: { timestamp } " )
135
143
# Return nothing (status code 204)
136
144
return {"detail" : "Todo deleted successfully" }
137
145
138
146
except ClientError as e :
139
- logging .error (f"ClientError deleting todo with id { id } : { e } " )
147
+ logging .error (f"ClientError deleting todo with id { id } and timestamp { timestamp } : { e } " )
140
148
raise HTTPException (status_code = 500 , detail = f"Error deleting todo: { str (e )} " )
141
149
142
150
except Exception as e :
143
- logging .error (f"Unexpected error deleting todo with id { id } : { e } " )
151
+ logging .error (f"Unexpected error deleting todo with id { id } and timestamp { timestamp } : { e } " )
144
152
raise HTTPException (status_code = 500 , detail = "Error deleting todo" )
145
153
146
154
0 commit comments