Skip to content

Commit 3425938

Browse files
committed
[server] WorkspaceService.sendHeartBeat
1 parent b55df37 commit 3425938

File tree

3 files changed

+55
-32
lines changed

3 files changed

+55
-32
lines changed

components/server/src/workspace/gitpod-server-impl.ts

Lines changed: 4 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,6 @@ import { WorkspaceManagerClientProvider } from "@gitpod/ws-manager/lib/client-pr
9696
import {
9797
AdmissionLevel,
9898
ControlAdmissionRequest,
99-
MarkActiveRequest,
10099
StopWorkspacePolicy,
101100
TakeSnapshotRequest,
102101
} from "@gitpod/ws-manager/lib/core_pb";
@@ -173,7 +172,7 @@ import { RedisSubscriber } from "../messaging/redis-subscriber";
173172
import { UsageService } from "../orgs/usage-service";
174173
import { UserService } from "../user/user-service";
175174
import { SSHKeyService } from "../user/sshkey-service";
176-
import { StartWorkspaceOptions, WorkspaceService, mapGrpcError } from "./workspace-service";
175+
import { StartWorkspaceOptions, WorkspaceService } from "./workspace-service";
177176
import { GitpodTokenService } from "../user/gitpod-token-service";
178177
import { EnvVarService } from "../user/env-var-service";
179178

@@ -1098,36 +1097,9 @@ export class GitpodServerImpl implements GitpodServerWithTracing, Disposable {
10981097

10991098
const user = await this.checkAndBlockUser("sendHeartBeat", undefined, { instanceId });
11001099

1101-
try {
1102-
const wsi = await this.workspaceDb.trace(ctx).findInstanceById(instanceId);
1103-
if (!wsi) {
1104-
throw new ApplicationError(ErrorCodes.NOT_FOUND, "workspace does not exist");
1105-
}
1106-
1107-
const ws = await this.workspaceDb.trace(ctx).findById(wsi.workspaceId);
1108-
if (!ws) {
1109-
throw new ApplicationError(ErrorCodes.NOT_FOUND, "workspace does not exist");
1110-
}
1111-
await this.guardAccess({ kind: "workspaceInstance", subject: wsi, workspace: ws }, "update");
1112-
1113-
const wasClosed = !!(options && options.wasClosed);
1114-
await this.workspaceDb.trace(ctx).updateLastHeartbeat(instanceId, user.id, new Date(), wasClosed);
1115-
1116-
const req = new MarkActiveRequest();
1117-
req.setId(instanceId);
1118-
req.setClosed(wasClosed);
1119-
1120-
const client = await this.workspaceManagerClientProvider.get(wsi.region);
1121-
await client.markActive(ctx, req);
1122-
} catch (e) {
1123-
if (e.message && typeof e.message === "string" && (e.message as String).endsWith("does not exist")) {
1124-
// This is an old tab with open workspace: drop silently
1125-
return;
1126-
} else {
1127-
e = mapGrpcError(e);
1128-
throw e;
1129-
}
1130-
}
1100+
await this.workspaceService.sendHeartBeat(user.id, options, (instance, workspace) =>
1101+
this.guardAccess({ kind: "workspaceInstance", subject: instance, workspace }, "update"),
1102+
);
11311103
}
11321104

11331105
async getWorkspaceOwner(ctx: TraceContext, workspaceId: string): Promise<UserInfo | undefined> {

components/server/src/workspace/workspace-service.spec.db.ts

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -365,6 +365,19 @@ describe("WorkspaceService", async () => {
365365
) => {},
366366
}); // returns without error in case of non-running workspace
367367
});
368+
369+
it("should sendHeartBeat", async () => {
370+
const svc = container.get(WorkspaceService);
371+
await createTestWorkspace(svc, org, owner, project);
372+
373+
await expectError(
374+
ErrorCodes.NOT_FOUND,
375+
svc.sendHeartBeat(owner.id, {
376+
instanceId: "non-existing-instanceId",
377+
}),
378+
"should fail on non-running workspace",
379+
);
380+
});
368381
});
369382

370383
async function createTestWorkspace(svc: WorkspaceService, org: Organization, owner: User, project: Project) {

components/server/src/workspace/workspace-service.ts

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ import {
4040
PortSpec,
4141
ControlPortRequest,
4242
SetTimeoutRequest,
43+
MarkActiveRequest,
4344
} from "@gitpod/ws-manager/lib";
4445
import { WorkspaceStarter } from "./workspace-starter";
4546
import { LogContext, log } from "@gitpod/gitpod-protocol/lib/util/logging";
@@ -775,6 +776,43 @@ export class WorkspaceService {
775776
aborted.resolve(false);
776777
}
777778
}
779+
780+
public async sendHeartBeat(
781+
userId: string,
782+
options: GitpodServer.SendHeartBeatOptions,
783+
check: (instance: WorkspaceInstance, workspace: Workspace) => Promise<void> = async () => {},
784+
): Promise<void> {
785+
const instanceId = options.instanceId;
786+
const instance = await this.db.findInstanceById(instanceId);
787+
if (!instance) {
788+
throw new ApplicationError(ErrorCodes.NOT_FOUND, "workspace does not exist");
789+
}
790+
const workspaceId = instance.workspaceId;
791+
await this.auth.checkPermissionOnWorkspace(userId, "access", workspaceId);
792+
793+
try {
794+
const workspace = await this.getWorkspace(userId, workspaceId);
795+
await check(instance, workspace);
796+
797+
const wasClosed = !!(options && options.wasClosed);
798+
await this.db.updateLastHeartbeat(instanceId, userId, new Date(), wasClosed);
799+
800+
const req = new MarkActiveRequest();
801+
req.setId(instanceId);
802+
req.setClosed(wasClosed);
803+
804+
const client = await this.clientProvider.get(instance.region);
805+
await client.markActive({}, req);
806+
} catch (e) {
807+
if (e.message && typeof e.message === "string" && (e.message as String).endsWith("does not exist")) {
808+
// This is an old tab with open workspace: drop silently
809+
return;
810+
} else {
811+
e = mapGrpcError(e);
812+
throw e;
813+
}
814+
}
815+
}
778816
}
779817

780818
// TODO(gpl) Make private after FGA rollout

0 commit comments

Comments
 (0)