feat(auth): send a request again when its token lapsed in the queue
A request can wait to be served for longer than the access token it was sent with lives, and comes back refused for a token that was valid when it left. Uploads that take minutes make that wait ordinary. - tell an expired token apart from any other refusal by the code the API returns, and retry only that one, once - prefer a token another process left behind over minting a second: it saves a round trip, and a rotating provider would retire one that is still in use. Assign it rather than read it, since the setter is what rewrites the session header the retry will carry - settle the token before the request so the one compared afterwards is the one that was actually sent - report an overloaded server when the second attempt is refused too, and let API errors out of the upload path with their own type
This commit is contained in:
@@ -5,7 +5,7 @@ from pydantic import TypeAdapter
|
||||
from pydantic.dataclasses import dataclass
|
||||
|
||||
from mdrsclient.api.base import BaseApi
|
||||
from mdrsclient.api.utils import token_check
|
||||
from mdrsclient.api.utils import retry_on_expired_token, token_check
|
||||
from mdrsclient.exceptions import UnauthorizedException
|
||||
from mdrsclient.models import Folder, FolderSimple
|
||||
|
||||
@@ -18,6 +18,7 @@ class FoldersApiCreateResponse:
|
||||
class FoldersApi(BaseApi):
|
||||
ENTRYPOINT: Final[str] = "v3/folders/"
|
||||
|
||||
@retry_on_expired_token
|
||||
def list(self, laboratory_id: int, path: str) -> list[FolderSimple]:
|
||||
# print(self.__class__.__name__ + "::" + sys._getframe().f_code.co_name)
|
||||
url = self.ENTRYPOINT
|
||||
@@ -30,6 +31,7 @@ class FoldersApi(BaseApi):
|
||||
ret.append(TypeAdapter(FolderSimple).validate_python(data))
|
||||
return ret
|
||||
|
||||
@retry_on_expired_token
|
||||
def retrieve(self, id: str) -> Folder:
|
||||
# print(self.__class__.__name__ + "::" + sys._getframe().f_code.co_name)
|
||||
url = self.ENTRYPOINT + id + "/"
|
||||
@@ -39,6 +41,7 @@ class FoldersApi(BaseApi):
|
||||
ret = TypeAdapter(Folder).validate_python(response.json())
|
||||
return ret
|
||||
|
||||
@retry_on_expired_token
|
||||
def create(self, name: str, parent_id: str) -> str:
|
||||
# print(self.__class__.__name__ + "::" + sys._getframe().f_code.co_name)
|
||||
url = self.ENTRYPOINT
|
||||
@@ -49,6 +52,7 @@ class FoldersApi(BaseApi):
|
||||
ret = TypeAdapter(FoldersApiCreateResponse).validate_python(response.json())
|
||||
return ret.id
|
||||
|
||||
@retry_on_expired_token
|
||||
def update(self, folder: FolderSimple) -> bool:
|
||||
# print(self.__class__.__name__ + "::" + sys._getframe().f_code.co_name)
|
||||
url = self.ENTRYPOINT + folder.id + "/"
|
||||
@@ -61,6 +65,7 @@ class FoldersApi(BaseApi):
|
||||
self._raise_response_error(response)
|
||||
return True
|
||||
|
||||
@retry_on_expired_token
|
||||
def destroy(self, id: str, recursive: bool) -> bool:
|
||||
# print(self.__class__.__name__ + "::" + sys._getframe().f_code.co_name)
|
||||
url = self.ENTRYPOINT + id + "/"
|
||||
@@ -70,6 +75,7 @@ class FoldersApi(BaseApi):
|
||||
self._raise_response_error(response)
|
||||
return True
|
||||
|
||||
@retry_on_expired_token
|
||||
def auth(self, id: str, password: str) -> bool:
|
||||
# print(self.__class__.__name__ + "::" + sys._getframe().f_code.co_name)
|
||||
url = self.ENTRYPOINT + id + "/auth/"
|
||||
@@ -81,6 +87,7 @@ class FoldersApi(BaseApi):
|
||||
self._raise_response_error(response)
|
||||
return True
|
||||
|
||||
@retry_on_expired_token
|
||||
def acl(self, id: str, access_level: int, recursive: bool, password: str | None) -> bool:
|
||||
# print(self.__class__.__name__ + "::" + sys._getframe().f_code.co_name)
|
||||
url = self.ENTRYPOINT + id + "/acl/"
|
||||
@@ -94,6 +101,7 @@ class FoldersApi(BaseApi):
|
||||
self._raise_response_error(response)
|
||||
return True
|
||||
|
||||
@retry_on_expired_token
|
||||
def move(self, folder: FolderSimple, folder_id: str, name: str) -> bool:
|
||||
# print(self.__class__.__name__ + "::" + sys._getframe().f_code.co_name)
|
||||
url = self.ENTRYPOINT + folder.id + "/move/"
|
||||
@@ -103,6 +111,7 @@ class FoldersApi(BaseApi):
|
||||
self._raise_response_error(response)
|
||||
return True
|
||||
|
||||
@retry_on_expired_token
|
||||
def copy(self, folder: FolderSimple, folder_id: str, name: str) -> bool:
|
||||
# print(self.__class__.__name__ + "::" + sys._getframe().f_code.co_name)
|
||||
url = self.ENTRYPOINT + folder.id + "/copy/"
|
||||
@@ -112,6 +121,7 @@ class FoldersApi(BaseApi):
|
||||
self._raise_response_error(response)
|
||||
return True
|
||||
|
||||
@retry_on_expired_token
|
||||
def metadata(self, id: str) -> dict[str, Any]:
|
||||
# print(self.__class__.__name__ + "::" + sys._getframe().f_code.co_name)
|
||||
url = self.ENTRYPOINT + id + "/metadata/"
|
||||
|
||||
Reference in New Issue
Block a user