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 10, 2023
1 parent 46ae367 commit 5b0bba9
Showing 1 changed file with 41 additions and 2 deletions.
43 changes: 41 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,13 +126,51 @@ def delete_expired_projects(cls):
print(e)
print("project {} postponed".format(copr.full_name))

@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()

for _ in range(3600): # if project is in deleting for a day it's bad, right?
for action_to_refresh in actions_to_wait:
db.session.refresh(action_to_refresh)

if all([action.result != BackendResultEnum("waiting") for action in actions_to_wait]):
app.logger.info(
f"No blocking actions for project {ownername}/{dirname} so far. Forking..."
)
break
else:
blocking_actions = list(
filter(
lambda action: action.result == BackendResultEnum("waiting"),
actions_to_wait
)
)
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):
cls.raise_if_cant_fork(user, copr)
forking = ProjectForking(user, dstgroup)
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 5b0bba9

Please sign in to comment.