Skip to content
New issue

Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? # to your account

Add timeout to locks #421

Open
wants to merge 5 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .env.example
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
MARKLOGIC_API_CLIENT_HOST=
MARKLOGIC_USER=fake_user
MARKLOGIC_PASSWORD=fake_password
DEBUG=True
4 changes: 3 additions & 1 deletion .pre-commit-config.yaml
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
default_language_version:
python: "3.12"
repos:
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v5.0.0
Expand Down Expand Up @@ -29,7 +31,7 @@ repos:
[
"types-requests",
"types-ujson",
"ds-caselaw-marklogic-api-client==17.2.0",
"ds-caselaw-marklogic-api-client==27.3.0",
]
files: ^src/

Expand Down
2 changes: 1 addition & 1 deletion Dockerfile
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
FROM python:3.12 as service
FROM python:3.12 AS service

RUN pip install poetry==1.6.1

Expand Down
1 change: 0 additions & 1 deletion docker-compose.yaml
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
version: "3.6"
services:
service:
build:
Expand Down
6 changes: 6 additions & 0 deletions openapi.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -159,6 +159,12 @@ paths:
schema:
type: string
style: simple
- name: timeout
schema:
type: int
required: false
in: query
description: After this many seconds, the judgment will be unlocked. Defaults to 900 (15 minutes).
responses:
"201":
description: "A single judgment document, in Akoma Ntoso XML"
Expand Down
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ requires-python = ">=3.12, <4"

[tool.poetry]
name = "ds-caselaw-privileged-api"
version = "0.3.0"
version = "0.4.0"
description = ""
authors = ["David McKee <david.mckee@dxw.com>"]
license = "MIT"
Expand Down
2 changes: 1 addition & 1 deletion setup.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
where = src

[mypy]
python_version = 3.9
python_version = 3.12
check_untyped_defs = True
ignore_missing_imports = True
warn_unused_ignores = True
Expand Down
13 changes: 7 additions & 6 deletions src/openapi_server/apis/writing_api.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import datetime

from caselawclient.client_helpers import VersionAnnotation, VersionType
from caselawclient.models.documents import DocumentURIString
from fastapi import ( # noqa: F401
Expand Down Expand Up @@ -84,20 +86,19 @@ async def judgment_uri_lock_put(
response: Response,
judgmentUri: DocumentURIString,
token_basic: TokenModel = SECURITY_TOKEN_MODEL,
expires="0",
timeout: str = "900", # noqa: ASYNC109
):
"""Locks edit access for a document for the current client. Returns the latest
version of the locked document, along with the new lock state."""
client = client_for_basic_auth(token_basic)
annotation = f"Judgment locked for editing by {token_basic.username}"
expires = bool(
int(expires),
) # If expires is True then the lock will expire at midnight, otherwise the lock is permanent
now = datetime.datetime.now(tz=datetime.UTC).isoformat()
timeout_seconds = int(timeout)
annotation = f"Judgment locked for editing by {token_basic.username} at {now} for {timeout_seconds} seconds"
with error_handling():
_ml_response = client.checkout_judgment(
judgmentUri,
annotation,
expires,
timeout_seconds=timeout_seconds,
)
judgment = client.get_judgment_xml(judgmentUri, show_unpublished=True)
return Response(status_code=201, content=judgment, media_type="application/xml")
Expand Down
10 changes: 5 additions & 5 deletions tests/test_writing_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -82,27 +82,27 @@ def test_put_lock_success(mocked_client):
mocked_client.return_value.checkout_judgment.assert_called_with(
"judgment/uri",
"Judgment locked for editing by user",
False,
timeout_seconds=900,
)
assert response.status_code == 201
assert "<judgment>" in response.text


@patch("openapi_server.apis.writing_api.client_for_basic_auth")
def test_put_lock_success_temporary(mocked_client):
"""If expires is passed, the lock will expire"""
"""If timeout is passed, the lock will expire"""
mocked_client.return_value.checkout_judgment.return_value = None
mocked_client.return_value.get_judgment_xml.return_value = b"<judgment></judgment>"
response = TestClient(app).request(
"PUT",
"/lock/judgment/uri",
auth=("user", "pass"),
params={"expires": "1"},
params={"timeout": "123"},
)
mocked_client.return_value.checkout_judgment.assert_called_with(
"judgment/uri",
"Judgment locked for editing by user",
True,
timeout_seconds=123,
)
assert response.status_code == 201
assert "<judgment>" in response.text
Expand All @@ -123,7 +123,7 @@ def test_put_lock_failure(mocked_client):
mocked_client.return_value.checkout_judgment.assert_called_with(
"judgment/uri",
"Judgment locked for editing by user",
False,
timeout_seconds=900,
)
assert response.status_code == 409
assert "resource is locked by another user" in response.text
Expand Down
Loading