mirror of
https://github.com/coder/coder.git
synced 2026-09-24 15:04:27 +08:00
perf: support fastpath in dbauthz GetLatestWorkspaceBuildByWorkspaceID (#21047)
This PR piggy backs on the agent API cached workspace added in earlier PRs to provide a fast path for avoiding `GetWorkspaceByID` calls in `GetLatestWorkspaceBuildByWorkspaceID` via injection of the workspaces RBAC object into the context. We can do this from the `agentConnectionMonitor` easily since we already cache the workspace. --------- Signed-off-by: Callum Styan <callumstyan@gmail.com>
This commit is contained in:
@@ -2455,6 +2455,18 @@ func (q *querier) GetLatestWorkspaceAppStatusesByWorkspaceIDs(ctx context.Contex
|
||||
}
|
||||
|
||||
func (q *querier) GetLatestWorkspaceBuildByWorkspaceID(ctx context.Context, workspaceID uuid.UUID) (database.WorkspaceBuild, error) {
|
||||
// Fast path: Check if we have a workspace RBAC object in context.
|
||||
if rbacObj, ok := WorkspaceRBACFromContext(ctx); ok {
|
||||
// Errors here will result in falling back to GetWorkspaceByAgentID,
|
||||
// in case the cached data is stale.
|
||||
if err := q.authorizeContext(ctx, policy.ActionRead, rbacObj); err == nil {
|
||||
return q.db.GetLatestWorkspaceBuildByWorkspaceID(ctx, workspaceID)
|
||||
}
|
||||
|
||||
q.log.Debug(ctx, "fast path authorization failed for GetLatestWorkspaceBuildByWorkspaceID, using slow path",
|
||||
slog.F("workspace_id", workspaceID))
|
||||
}
|
||||
|
||||
if _, err := q.GetWorkspaceByID(ctx, workspaceID); err != nil {
|
||||
return database.WorkspaceBuild{}, err
|
||||
}
|
||||
|
||||
@@ -4731,3 +4731,77 @@ func (s *MethodTestSuite) TestTelemetry() {
|
||||
check.Args(database.CalculateAIBridgeInterceptionsTelemetrySummaryParams{}).Asserts(rbac.ResourceAibridgeInterception, policy.ActionRead)
|
||||
}))
|
||||
}
|
||||
|
||||
func TestGetLatestWorkspaceBuildByWorkspaceID_FastPath(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
ownerID := uuid.New()
|
||||
wsID := uuid.New()
|
||||
orgID := uuid.New()
|
||||
|
||||
workspace := database.Workspace{
|
||||
ID: wsID,
|
||||
OwnerID: ownerID,
|
||||
OrganizationID: orgID,
|
||||
}
|
||||
|
||||
build := database.WorkspaceBuild{
|
||||
ID: uuid.New(),
|
||||
WorkspaceID: wsID,
|
||||
}
|
||||
|
||||
wsIdentity := database.WorkspaceIdentity{
|
||||
ID: wsID,
|
||||
OwnerID: ownerID,
|
||||
OrganizationID: orgID,
|
||||
}
|
||||
|
||||
actor := rbac.Subject{
|
||||
ID: ownerID.String(),
|
||||
Roles: rbac.RoleIdentifiers{rbac.RoleOwner()},
|
||||
Groups: []string{orgID.String()},
|
||||
Scope: rbac.ScopeAll,
|
||||
}
|
||||
|
||||
authorizer := &coderdtest.RecordingAuthorizer{
|
||||
Wrapped: (&coderdtest.FakeAuthorizer{}).AlwaysReturn(nil),
|
||||
}
|
||||
|
||||
t.Run("WithWorkspaceRBAC", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
ctx := dbauthz.As(context.Background(), actor)
|
||||
ctrl := gomock.NewController(t)
|
||||
dbm := dbmock.NewMockStore(ctrl)
|
||||
|
||||
rbacObj := wsIdentity.RBACObject()
|
||||
ctx, err := dbauthz.WithWorkspaceRBAC(ctx, rbacObj)
|
||||
require.NoError(t, err)
|
||||
|
||||
dbm.EXPECT().GetLatestWorkspaceBuildByWorkspaceID(gomock.Any(), workspace.ID).Return(build, nil).AnyTimes()
|
||||
dbm.EXPECT().Wrappers().Return([]string{})
|
||||
|
||||
q := dbauthz.New(dbm, authorizer, slogtest.Make(t, nil), coderdtest.AccessControlStorePointer())
|
||||
|
||||
result, err := q.GetLatestWorkspaceBuildByWorkspaceID(ctx, workspace.ID)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, build, result)
|
||||
})
|
||||
t.Run("WithoutWorkspaceRBAC", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
ctx := dbauthz.As(context.Background(), actor)
|
||||
ctrl := gomock.NewController(t)
|
||||
dbm := dbmock.NewMockStore(ctrl)
|
||||
|
||||
dbm.EXPECT().GetWorkspaceByID(gomock.Any(), wsID).Return(workspace, nil).AnyTimes()
|
||||
dbm.EXPECT().GetLatestWorkspaceBuildByWorkspaceID(gomock.Any(), workspace.ID).Return(build, nil).AnyTimes()
|
||||
dbm.EXPECT().Wrappers().Return([]string{})
|
||||
|
||||
q := dbauthz.New(dbm, authorizer, slogtest.Make(t, nil), coderdtest.AccessControlStorePointer())
|
||||
|
||||
result, err := q.GetLatestWorkspaceBuildByWorkspaceID(ctx, workspace.ID)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, build, result)
|
||||
})
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user