Skip to content

feat: replace sandboxes-api with editor-service sessions API#88

Merged
odinuv merged 4 commits into
mainfrom
odin/AJDA-1942
May 12, 2026
Merged

feat: replace sandboxes-api with editor-service sessions API#88
odinuv merged 4 commits into
mainfrom
odin/AJDA-1942

Conversation

@odinuv
Copy link
Copy Markdown
Member

@odinuv odinuv commented Mar 31, 2026

https://linear.app/keboola/issue/AJDA-1942

Description

Replaces all usages of the sandboxes-api PHP client with the editor-service sessions API (SQL workspaces) and the sandboxes-service-api-client (Python/R sandboxes), as the sandboxes API is being turned off. Introduces a lightweight EditorServiceClient with list and delete endpoints, adds Python/R sandbox deletion via Job Queue jobs, and removes the now-obsolete DeleteProjectSandboxes command.

Ownership model

The two resource types use different identity anchors:

  • Editor sessions are bound to userId, which is stable for the entire lifetime of the user in the system. A session is ownerless when userId is no longer present among any active project token's admin.id.
  • Python/R sandbox configs are bound to creatorToken.id, which is re-issued every time a user leaves and re-enters a project (the old token is deleted, a new one issued). A config is ownerless when its creatorToken.id no longer exists in listTokens(). A user who rejoins the project keeps their editor sessions but loses their old sandbox configs — this is intentional and matches the previous sandboxes-api behavior.

Job-queue deletion fallback

The normal deletion path enqueues a keboola.sandboxes job with task=delete; the job deletes the app on success. If job creation fails, the app may already be in a partially-deleted state, so the catch block calls deleteApp() + double-deleteConfiguration() to finish cleanup directly rather than leaving things inconsistent.

Release Notes

Change Type
Refactoring / internal improvement — migrates from sandboxes-api to editor-service and sandbox-service APIs; adds Python/R sandbox handling to ownerless workspace cleanup commands.

Justification
The sandboxes API is being turned off. SQL workspace sessions are now listed via the editor-service and deleted by removing the associated storage configuration (double-call pattern to purge from trash). Python/R sandboxes are listed via the sandbox-service API and deleted via a Job Queue job of keboola.sandboxes.

Plans for Customer Communication
No customer-facing changes; these are internal maintenance CLI commands.

Impact Analysis
Low risk. Affects three commands (DeleteOwnerlessWorkspaces, DeleteOrganizationOwnerlessWorkspaces, MassDeleteProjectWorkspaces) and removes one (DeleteProjectSandboxes). No breaking changes to command interfaces. Adds dependency on keboola/sandboxes-service-api-client and keboola/service-client.

⚠️ Blocker: composer.json currently references keboola/sandboxes-service-api-client: dev-odin/AJDA-1942 (the upstream branch that adds the types filter to AppsApiClient::listApps()). This must be replaced with a stable tagged release (^1.8.0) before merging. Tracked in keboola/sandboxes-service-api-php-client.

Deployment Plan
Standard CI/CD continuous deployment across all stacks.

Rollback Plan
Standard git revert if issues detected post-deployment.

Post-Release Support Plan
No follow-up actions needed.

@linear
Copy link
Copy Markdown

linear Bot commented Mar 31, 2026

@odinuv odinuv requested a review from ondrajodas April 1, 2026 13:40
@ondrajodas
Copy link
Copy Markdown
Contributor

Code review

Found 2 issues:

  1. deleteConfiguration() is called twice consecutively with identical arguments in all three modified command files. If this is intentional (e.g. soft-delete then purge from trash), a comment should explain it — the previous implementation in PR add cmd 'manage:mass-delete-project-workspaces' #69 included such a comment. If unintentional, the second call will hit a 404 since the configuration was already deleted, crashing the loop mid-execution.

$components = new Components($branchClient);
$components->deleteConfiguration($session['componentId'], $session['configurationId']);
$components->deleteConfiguration($session['componentId'], $session['configurationId']);
}

Same pattern in:

  1. EditorServiceClient queries /sql/sessions only. The endpoint name suggests SQL-scoped sessions, whereas the old sandboxes-api client covered all workspace types (Python, Jupyter, RStudio, database workspaces). If editor-service has separate endpoints for non-SQL session types, this PR would silently stop cleaning up those sessions without any error or log output.

public function listSessions(): array
{
$response = $this->httpClient->request('GET', '/sql/sessions', [
'query' => ['listAll' => '1'],
]);

🤖 Generated with Claude Code

- If this code review was useful, please react with 👍. Otherwise, react with 👎.

Copy link
Copy Markdown
Contributor

@ondrajodas ondrajodas left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

1 - je to pokaždé jiný use-case, takže v pohodě
2 - to je pravda no, že tímto budeme mazat jen SQL worksapces

@odinuv
Copy link
Copy Markdown
Member Author

odinuv commented Apr 7, 2026

ad 2. no to není pravda ne? tam byly podmínky

       if (!in_array($sandbox->getType(), Sandbox::CONTAINER_TYPES)) {
            // it is a database workspace
            if (empty($sandbox->getPhysicalId())) {
                $output->writeln('No underlying storage workspace found for sandboxId ' . $sandbox->getId());

Takže to mazalo jen DB workspaces, ne?

@ondrajodas
Copy link
Copy Markdown
Contributor

ondrajodas commented Apr 7, 2026

no ale když vezmeš celý kus kódu:
https://github.com/keboola/cli-utils/blob/main/src/Keboola/Console/Command/DeleteOwnerlessWorkspaces.php#L95C13-L117C14

tak je to mazalo... konkrétně na řádku 116

@odinuv
Copy link
Copy Markdown
Member Author

odinuv commented Apr 7, 2026

A kuš, tak to jsem přehlídl!

Tak zpátky do výroby

@odinuv odinuv marked this pull request as draft April 7, 2026 10:18
@odinuv odinuv marked this pull request as ready for review April 27, 2026 15:12
@odinuv odinuv requested a review from ondrajodas April 27, 2026 15:13
@odinuv
Copy link
Copy Markdown
Member Author

odinuv commented Apr 27, 2026

@ondrajodas Je to nakonec celkem dost předělaný - snažil jsem se to spíš udělat tak, aby to dávalo nějakej smysl než nutně přesně tak jak to bylo předtím :D

Copy link
Copy Markdown
Contributor

@ondrajodas ondrajodas left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

asi to bude v pohodě, jen drobnosti

Comment thread composer.json Outdated
Comment on lines +204 to +206
// First call moves the configuration to trash, second call permanently purges it.
$storageComponents->deleteConfiguration('keboola.sandboxes', $app->getConfigId());
$storageComponents->deleteConfiguration('keboola.sandboxes', $app->getConfigId());
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

:trollface:

));
continue;
}
if ($exception->getCode() !== 404) {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

dřív tu byl check jestli existuje token a teď se kontroluje jestli je uživatel v projektu?

asi ok, ale zůstanou tu WSs které mají neplatný token

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

platí pro oba commandy

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Upravil jsem popis a doplnil tam comment aby to bylo jasnější, editor je vázáný na uživatele (a jinak není v UI vidět), sandbox na token

@odinuv odinuv merged commit 8dc27ad into main May 12, 2026
1 check passed
@odinuv odinuv deleted the odin/AJDA-1942 branch May 12, 2026 14:17
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants