Skip to content

Commit

Permalink
Improve remove_project, add migration to cleanup condition.checks field
Browse files Browse the repository at this point in the history
  • Loading branch information
m.kindritskiy committed Dec 4, 2024
1 parent e87c6c3 commit 11d2ab1
Show file tree
Hide file tree
Showing 6 changed files with 96 additions and 43 deletions.
62 changes: 57 additions & 5 deletions featureflags/graph/actions.py
Original file line number Diff line number Diff line change
Expand Up @@ -504,28 +504,80 @@ async def delete_variable(
@auth_required
@track
async def delete_project(
project_id: str,
project_id: UUID,
*,
conn: SAConnection,
) -> None:
"""Physycally deletes project and its:
* flags
* variables
* conditions
* checks
"""
assert project_id, "Project id is required"

project_uuid = UUID(hex=project_id)
# Delete flag conditions
flags = await conn.execute(
select([Flag.id]).where(Flag.project == project_id)
)
flag_ids = [f.id for f in await flags.fetchall()]

await conn.execute(
Condition.__table__.delete().where(Condition.flag.in_(flag_ids))
)

# Delete flags changelog
await conn.execute(
Changelog.__table__.delete().where(Changelog.flag.in_(flag_ids))
)

# Delete project flags
await conn.execute(
Flag.__table__.delete().where(Flag.project == project_id)
)

# Delete value conditions
values = await conn.execute(
select([Value.id]).where(Value.project == project_id)
)
values_ids = [v.id for v in await values.fetchall()]

await conn.execute(
ValueCondition.__table__.delete().where(
ValueCondition.value.in_(values_ids)
)
)

# Delete value changelog
await conn.execute(
ValueChangelog.__table__.delete().where(
ValueChangelog.value.in_(values_ids)
)
)

# Delete project values
await conn.execute(
Flag.__table__.delete().where(Flag.project == project_id)
)

# Delete project variables
variables = await conn.execute(
select([Variable.id]).where(Project.id == project_uuid)
select([Variable.id]).where(Project.id == project_id)
)
variable_ids = [v.id for v in await variables.fetchall()]

# Delete variable checks
if variable_ids:
await conn.execute(
Check.__table__.delete().where(Check.variable.in_(variable_ids))
)

# Delete variables
await conn.execute(
Variable.__table__.delete().where(Variable.project == project_uuid)
Variable.__table__.delete().where(Variable.project == project_id)
)

# Finally delete project
await conn.execute(
Project.__table__.delete().where(Project.id == project_uuid)
Project.__table__.delete().where(Project.id == project_id)
)
16 changes: 1 addition & 15 deletions featureflags/graph/graph.py
Original file line number Diff line number Diff line change
Expand Up @@ -1187,23 +1187,9 @@ async def delete_project(ctx: dict, options: dict) -> DeleteProjectResult:
async with ctx[GraphContext.DB_ENGINE].acquire() as conn:
project_uuid = UUID(options["id"])

is_flags_exists = await exec_scalar(
ctx[GraphContext.DB_ENGINE],
(select([Flag.id]).where(Flag.project == project_uuid).limit(1)),
)
if is_flags_exists:
return DeleteProjectResult("You need delete all Flags firstly.")

is_values_exists = await exec_scalar(
ctx[GraphContext.DB_ENGINE],
(select([Value.id]).where(Value.project == project_uuid).limit(1)),
)
if is_values_exists:
return DeleteProjectResult("You need delete all Values firstly.")

try:
await actions.delete_project(
options["id"],
project_uuid,
conn=conn,
)
except Exception as e:
Expand Down
3 changes: 1 addition & 2 deletions featureflags/graph/proto_adapter.py
Original file line number Diff line number Diff line change
Expand Up @@ -85,8 +85,7 @@ def variable(self, obj, value):
obj.variable.Variable = value.ident.hex

def operator(self, obj, value):
if value is not None:
obj.operator = value.to_pb()
obj.operator = value.to_pb()

def value_string(self, obj, value):
if value is not None:
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
from alembic import op


revision = "2fa54f8b55c1"
down_revision = "a327a3ea7a5f"
branch_labels = None
depends_on = None


def upgrade():
conn = op.get_bind()

conditions = list(conn.execute("SELECT id, checks FROM condition"))
checks = list(conn.execute('SELECT id FROM "check"'))

print("Found conditions: {}".format(len(conditions)))
print("Found checks: {}".format(len(checks)))

check_ids = {check.id for check in checks}

for condition in conditions:
new_checks = {check for check in condition.checks if check in check_ids}
if set(condition.checks) != new_checks:
print(
"Updating condition {} with new checks: before={}, after={}".format(
condition.id, condition.checks, new_checks
)
)
conn.execute(
"UPDATE condition SET checks = :checks WHERE id = :id",
{"checks": new_checks, "id": condition.id},
)


def downgrade(): ...
21 changes: 1 addition & 20 deletions featureflags/rpc/servicer.py
Original file line number Diff line number Diff line change
Expand Up @@ -93,26 +93,7 @@ async def Exchange(self, stream: Stream) -> None: # noqa: N802
db_engine=self._db_engine,
session=user_session.get(),
)
try:
log.debug(
"Graph result: %r",
result.__idx__,
extra={
"project_name": request.project,
"request_verion": request.version,
"project_version": version,
},
)
populate_result_proto(result, exchange_reply.result)
except: # noqa
log.error(
"Failed to populate result proto",
extra={
"project_name": request.project,
"request_verion": request.version,
"project_version": version,
},
)
populate_result_proto(result, exchange_reply.result)

exchange_reply.version = version

Expand Down
2 changes: 1 addition & 1 deletion lets.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,7 @@ commands:
depends: [build-dev]
cmd: |
docker-compose run --rm backend \
pdm run python3 -m featureflags alembic -- revision --autogenerate -m
pdm run python3 -m featureflags alembic -- revision --autogenerate -m ${LETS_COMMAND_ARGS}
apply-seeds-dev:
description: Apply seeds to local postgres
Expand Down

0 comments on commit 11d2ab1

Please sign in to comment.