mirror of
				https://github.com/zulip/zulip.git
				synced 2025-10-31 12:03:46 +00:00 
			
		
		
		
	access_message: Allow selecting message row FOR UPDATE.
This is a prep change to start using `SELECT FOR UPDATE` queries when there is a chance of race conditions.
This commit is contained in:
		
				
					committed by
					
						 Tim Abbott
						Tim Abbott
					
				
			
			
				
	
			
			
			
						parent
						
							51f5bbcd57
						
					
				
				
					commit
					1a9f385e17
				
			| @@ -655,7 +655,9 @@ class ReactionDict: | ||||
|  | ||||
|  | ||||
| def access_message( | ||||
|     user_profile: UserProfile, message_id: int | ||||
|     user_profile: UserProfile, | ||||
|     message_id: int, | ||||
|     lock_message: bool = False, | ||||
| ) -> Tuple[Message, Optional[UserMessage]]: | ||||
|     """You can access a message by ID in our APIs that either: | ||||
|     (1) You received or have previously accessed via starring | ||||
| @@ -664,9 +666,21 @@ def access_message( | ||||
|  | ||||
|     We produce consistent, boring error messages to avoid leaking any | ||||
|     information from a security perspective. | ||||
|  | ||||
|     The lock_message parameter should be passed by callers that are | ||||
|     planning to modify the Message object. This will use the SQL | ||||
|     `SELECT FOR UPDATE` feature to ensure that other processes cannot | ||||
|     delete the message during the current transaction, which is | ||||
|     important to prevent rare race conditions. Callers must only | ||||
|     pass lock_message when inside a @transaction.atomic block. | ||||
|     """ | ||||
|     try: | ||||
|         message = Message.objects.select_related().get(id=message_id) | ||||
|         base_query = Message.objects.select_related() | ||||
|         if lock_message:  # nocoverage | ||||
|             # We want to lock only the `Message` row, and not the related fields | ||||
|             # because the `Message` row only has a possibility of races. | ||||
|             base_query = base_query.select_for_update(of=("self",)) | ||||
|         message = base_query.get(id=message_id) | ||||
|     except Message.DoesNotExist: | ||||
|         raise JsonableError(_("Invalid message(s)")) | ||||
|  | ||||
|   | ||||
		Reference in New Issue
	
	Block a user