Skip to content

Commit

Permalink
frontend: don't send new create project task if project is deleting
Browse files Browse the repository at this point in the history
wait for the end of the deletion of project to avoid race condition when fork is called immidiatelly after delete
  • Loading branch information
nikromen committed Jul 18, 2023
1 parent 46ae367 commit 29705bb
Showing 1 changed file with 46 additions and 2 deletions.
48 changes: 46 additions & 2 deletions frontend/coprs_frontend/coprs/logic/complex_logic.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
# coding: utf-8

import os
import datetime
import time
import fnmatch
import flask
import sqlalchemy

from copr_common.enums import StatusEnum
from sqlalchemy import and_

from copr_common.enums import StatusEnum, ActionTypeEnum, BackendResultEnum, ActionObjectTypeEnum
from coprs import app
from coprs import db
from coprs import helpers
Expand Down Expand Up @@ -125,6 +126,47 @@ def delete_expired_projects(cls):
print(e)
print("project {} postponed".format(copr.full_name))

@staticmethod
def _refresh_waiting_actions(actions_to_refresh):
for action_to_refresh in actions_to_refresh:
db.session.refresh(action_to_refresh)

blocking_actions = []
for action in actions_to_refresh:
if action.result == BackendResultEnum("waiting"):
blocking_actions.append(action)

return blocking_actions

@classmethod
def _wait_for_copr_to_be_deleted(cls, ownername, dirname):
actions_to_wait = (
models.Action.query
.filter(models.Action.object_type == ActionObjectTypeEnum.copr)
.filter(models.Action.result == BackendResultEnum("waiting"))
.filter(models.Action.action_type == ActionTypeEnum("delete"))
.filter(
and_(
models.Action.data.contains(ownername),
models.Action.data.contains(dirname)
)
)
).all()

# if a project is in deleting state for a day, it's bad, right?
for _ in range(3600):
blocking_actions = cls._refresh_waiting_actions(actions_to_wait)
if not blocking_actions:
app.logger.info(
f"No blocking actions for project {ownername}/{dirname} so far. Forking..."
)
return

app.logger.info(
f"Blocking delete actions: {blocking_actions} to wait for project:"
f" {ownername}/{dirname}"
)
time.sleep(60)

@classmethod
def fork_copr(cls, copr, user, dstname, dstgroup=None):
Expand All @@ -133,6 +175,8 @@ def fork_copr(cls, copr, user, dstname, dstgroup=None):
created = (not bool(forking.get(copr, dstname)))
fcopr = forking.fork_copr(copr, dstname)

cls._wait_for_copr_to_be_deleted(fcopr.owner_name, fcopr.name)

if fcopr.full_name == copr.full_name:
raise exceptions.DuplicateException("Source project should not be same as destination")

Expand Down

0 comments on commit 29705bb

Please sign in to comment.