Skip to content

Commit

Permalink
Partial proof of concept for splitting up business logic layer from d…
Browse files Browse the repository at this point in the history
…ata access layer
  • Loading branch information
inglesp committed Feb 29, 2024
1 parent 1666d4d commit d7870e5
Show file tree
Hide file tree
Showing 2 changed files with 34 additions and 29 deletions.
42 changes: 23 additions & 19 deletions airlock/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -284,12 +284,12 @@ def check_status(
there's not transaction protection.
"""
# validate state logic
valid_transitions = self.VALID_STATE_TRANSITIONS.get(release_request.status, [])
# valid_transitions = self.VALID_STATE_TRANSITIONS.get(release_request.status, [])

if to_status not in valid_transitions:
raise self.InvalidStateTransition(
f"from {release_request.status.name} to {to_status.name}"
)
# if to_status not in valid_transitions:
# raise self.InvalidStateTransition(
# f"from {release_request.status.name} to {to_status.name}"
# )

# check permissions
# author transitions
Expand All @@ -314,22 +314,26 @@ def check_status(
def set_status(
self, release_request: ReleaseRequest, to_status: Status, user: User
):
"""Set the status of the request.
This will validate the transition, and then mutate the request object.
As calling set_status will mutate the passed ReleaseRequest, in cases
where we may want to call to external services (e.g. job-server) to
mutate external state, and these calls might fail, we provide
a look-before-you-leap API. That is, when changing status and related
state, an implementer should call `check_status(...)` first to validate
the desired state transition and permissions are valid, then mutate
their own state, and then call `set_status(...)` if successful to
mutate the passed ReleaseRequest object.
"""
"""Set the status of the request."""

# validate first
# We're using this only to validate that the user has permission to move
# release_request into to_status.
self.check_status(release_request, to_status, user)

valid_from_statuses = [
status
for status in self.VALID_STATE_TRANSITIONS
if to_status in self.VALID_STATE_TRANSITIONS[status]
]

num_updates = self.update_status(
release_request, to_status, valid_from_statuses
)
if num_updates == 0:
raise self.InvalidStateTransition(
f"from {release_request.status.name} to {to_status.name}"
)

release_request.status = to_status

def add_file_to_request(
Expand Down
21 changes: 11 additions & 10 deletions local_db/api.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
from dataclasses import dataclass
from pathlib import Path
from typing import Optional
from typing import List, Optional

from django.db import transaction

Expand Down Expand Up @@ -119,15 +119,16 @@ def get_outstanding_requests_for_review(self, user: User):

return requests

def set_status(self, request: ReleaseRequest, status: Status, user: User):
with transaction.atomic():
# validate transition/permissions ahead of time
self.check_status(request, status, user)
# persist state change
metadata = self._find_metadata(request.id)
metadata.status = status
metadata.save()
super().set_status(request, status, user)
def update_status(
self,
request: ReleaseRequest,
to_status: Status,
valid_from_statuses: List[Status],
):
return RequestMetadata.objects.filter(
id=request.id,
status__in=valid_from_statuses,
).update(status=to_status)

def add_file_to_request(
self,
Expand Down

0 comments on commit d7870e5

Please sign in to comment.