Skip to content

Commit db5700a

Browse files
committed
fix(coderd): mark sub agent deletion via boolean instead of delete
Fixes coder/internal#685
1 parent b9ac16c commit db5700a

File tree

9 files changed

+174
-21
lines changed

9 files changed

+174
-21
lines changed

coderd/database/dump.sql

Lines changed: 5 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
ALTER TABLE workspace_agents
2+
DROP COLUMN deleted;
3+
4+
-- Restore trigger without deleted check.
5+
DROP TRIGGER IF EXISTS workspace_agent_name_unique_trigger ON workspace_agents;
6+
DROP FUNCTION IF EXISTS check_workspace_agent_name_unique();
7+
8+
CREATE OR REPLACE FUNCTION check_workspace_agent_name_unique()
9+
RETURNS TRIGGER AS $$
10+
DECLARE
11+
workspace_build_id uuid;
12+
agents_with_name int;
13+
BEGIN
14+
-- Find the workspace build the workspace agent is being inserted into.
15+
SELECT workspace_builds.id INTO workspace_build_id
16+
FROM workspace_resources
17+
JOIN workspace_builds ON workspace_builds.job_id = workspace_resources.job_id
18+
WHERE workspace_resources.id = NEW.resource_id;
19+
20+
-- If the agent doesn't have a workspace build, we'll allow the insert.
21+
IF workspace_build_id IS NULL THEN
22+
RETURN NEW;
23+
END IF;
24+
25+
-- Count how many agents in this workspace build already have the given agent name.
26+
SELECT COUNT(*) INTO agents_with_name
27+
FROM workspace_agents
28+
JOIN workspace_resources ON workspace_resources.id = workspace_agents.resource_id
29+
JOIN workspace_builds ON workspace_builds.job_id = workspace_resources.job_id
30+
WHERE workspace_builds.id = workspace_build_id
31+
AND workspace_agents.name = NEW.name
32+
AND workspace_agents.id != NEW.id;
33+
34+
-- If there's already an agent with this name, raise an error
35+
IF agents_with_name > 0 THEN
36+
RAISE EXCEPTION 'workspace agent name "%" already exists in this workspace build', NEW.name
37+
USING ERRCODE = 'unique_violation';
38+
END IF;
39+
40+
RETURN NEW;
41+
END;
42+
$$ LANGUAGE plpgsql;
43+
44+
CREATE TRIGGER workspace_agent_name_unique_trigger
45+
BEFORE INSERT OR UPDATE OF name, resource_id ON workspace_agents
46+
FOR EACH ROW
47+
EXECUTE FUNCTION check_workspace_agent_name_unique();
48+
49+
COMMENT ON TRIGGER workspace_agent_name_unique_trigger ON workspace_agents IS
50+
'Use a trigger instead of a unique constraint because existing data may violate
51+
the uniqueness requirement. A trigger allows us to enforce uniqueness going
52+
forward without requiring a migration to clean up historical data.';
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
ALTER TABLE workspace_agents
2+
ADD COLUMN deleted BOOLEAN NOT NULL DEFAULT FALSE;
3+
4+
COMMENT ON COLUMN workspace_agents.deleted IS 'Indicates whether or not the agent has been deleted. This is currently only applicable to sub agents.';
5+
6+
-- Recreate the trigger with deleted check.
7+
DROP TRIGGER IF EXISTS workspace_agent_name_unique_trigger ON workspace_agents;
8+
DROP FUNCTION IF EXISTS check_workspace_agent_name_unique();
9+
10+
CREATE OR REPLACE FUNCTION check_workspace_agent_name_unique()
11+
RETURNS TRIGGER AS $$
12+
DECLARE
13+
workspace_build_id uuid;
14+
agents_with_name int;
15+
BEGIN
16+
-- Find the workspace build the workspace agent is being inserted into.
17+
SELECT workspace_builds.id INTO workspace_build_id
18+
FROM workspace_resources
19+
JOIN workspace_builds ON workspace_builds.job_id = workspace_resources.job_id
20+
WHERE workspace_resources.id = NEW.resource_id;
21+
22+
-- If the agent doesn't have a workspace build, we'll allow the insert.
23+
IF workspace_build_id IS NULL THEN
24+
RETURN NEW;
25+
END IF;
26+
27+
-- Count how many agents in this workspace build already have the given agent name.
28+
SELECT COUNT(*) INTO agents_with_name
29+
FROM workspace_agents
30+
JOIN workspace_resources ON workspace_resources.id = workspace_agents.resource_id
31+
JOIN workspace_builds ON workspace_builds.job_id = workspace_resources.job_id
32+
WHERE workspace_builds.id = workspace_build_id
33+
AND workspace_agents.name = NEW.name
34+
AND workspace_agents.id != NEW.id
35+
AND workspace_agents.deleted = FALSE; -- Ensure we only count non-deleted agents.
36+
37+
-- If there's already an agent with this name, raise an error
38+
IF agents_with_name > 0 THEN
39+
RAISE EXCEPTION 'workspace agent name "%" already exists in this workspace build', NEW.name
40+
USING ERRCODE = 'unique_violation';
41+
END IF;
42+
43+
RETURN NEW;
44+
END;
45+
$$ LANGUAGE plpgsql;
46+
47+
CREATE TRIGGER workspace_agent_name_unique_trigger
48+
BEFORE INSERT OR UPDATE OF name, resource_id ON workspace_agents
49+
FOR EACH ROW
50+
EXECUTE FUNCTION check_workspace_agent_name_unique();
51+
52+
COMMENT ON TRIGGER workspace_agent_name_unique_trigger ON workspace_agents IS
53+
'Use a trigger instead of a unique constraint because existing data may violate
54+
the uniqueness requirement. A trigger allows us to enforce uniqueness going
55+
forward without requiring a migration to clean up historical data.';

coderd/database/models.go

Lines changed: 2 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy