Releases the already acquired lock. The token is only cleared after the Redis release operation completes successfully. This ensures that if the release is cancelled mid-operation, the lock state remains consistent and can be retried.
(self)
| 264 | return self.local.token is not None and stored_token == self.local.token |
| 265 | |
| 266 | async def release(self) -> None: |
| 267 | """Releases the already acquired lock. |
| 268 | |
| 269 | The token is only cleared after the Redis release operation completes |
| 270 | successfully. This ensures that if the release is cancelled mid-operation, |
| 271 | the lock state remains consistent and can be retried. |
| 272 | """ |
| 273 | expected_token = self.local.token |
| 274 | if expected_token is None: |
| 275 | raise LockError( |
| 276 | "Cannot release a lock that's not owned or is already unlocked.", |
| 277 | lock_name=self.name, |
| 278 | ) |
| 279 | try: |
| 280 | await self.do_release(expected_token) |
| 281 | except LockNotOwnedError: |
| 282 | # Lock doesn't exist in Redis, safe to clear token |
| 283 | self.local.token = None |
| 284 | raise |
| 285 | # Only clear token after successful release |
| 286 | self.local.token = None |
| 287 | |
| 288 | async def do_release(self, expected_token: bytes) -> None: |
| 289 | if not bool( |