chore: fix concurrent CommitQuota transactions for unrelated users/orgs (#15261)

The failure condition being fixed is `w1` and `w2` could belong
to different users, organizations, and templates and still cause a
serializable failure if run concurrently. This is because the old query 
did a `seq scan` on the `workspace_builds` table. Since that is the 
table being updated, we really want to prevent that.

So before this would fail for any 2 workspaces. Now it only fails if
`w1` and `w2` are owned by the same user and organization.
This commit is contained in:
Steven Masley
2024-11-01 11:05:49 -04:00
committed by GitHub
parent 47f9a8aeb8
commit 854044e811
15 changed files with 982 additions and 23 deletions

View File

@ -6736,23 +6736,33 @@ const getQuotaConsumedForUser = `-- name: GetQuotaConsumedForUser :one
WITH latest_builds AS (
SELECT
DISTINCT ON
(workspace_id) id,
workspace_id,
daily_cost
(wb.workspace_id) wb.workspace_id,
wb.daily_cost
FROM
workspace_builds wb
-- This INNER JOIN prevents a seq scan of the workspace_builds table.
-- Limit the rows to the absolute minimum required, which is all workspaces
-- in a given organization for a given user.
INNER JOIN
workspaces on wb.workspace_id = workspaces.id
WHERE
workspaces.owner_id = $1 AND
workspaces.organization_id = $2
ORDER BY
workspace_id,
created_at DESC
wb.workspace_id,
wb.created_at DESC
)
SELECT
coalesce(SUM(daily_cost), 0)::BIGINT
FROM
workspaces
JOIN latest_builds ON
INNER JOIN latest_builds ON
latest_builds.workspace_id = workspaces.id
WHERE NOT
deleted AND
WHERE
NOT deleted AND
-- We can likely remove these conditions since we check above.
-- But it does not hurt to be defensive and make sure future query changes
-- do not break anything.
workspaces.owner_id = $1 AND
workspaces.organization_id = $2
`