-
Notifications
You must be signed in to change notification settings - Fork 46
Add waitForExit() method to Process interface #299
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
🦋 Changeset detectedLatest commit: 4df089d The changes in this PR will be included in the next version bump. This PR includes changesets to release 1 package
Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
commit: |
🐳 Docker Images PublishedDefault: FROM cloudflare/sandbox:0.0.0-pr-299-09e6d55With Python: FROM cloudflare/sandbox:0.0.0-pr-299-09e6d55-pythonWith OpenCode: FROM cloudflare/sandbox:0.0.0-pr-299-09e6d55-opencodeVersion: Use the 📦 Standalone BinaryFor arbitrary Dockerfiles: COPY --from=cloudflare/sandbox:0.0.0-pr-299-09e6d55 /container-server/sandbox /sandbox
ENTRYPOINT ["/sandbox"]Download via GitHub CLI: gh run download 20169928424 -n sandbox-binaryExtract from Docker: docker run --rm cloudflare/sandbox:0.0.0-pr-299-09e6d55 cat /container-server/sandbox > sandbox && chmod +x sandbox |
| { | ||
| method: 'POST', | ||
| headers, | ||
| body: JSON.stringify({ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Tests call custom endpoint that doesn't exist in production container. Should use SDK directly:
// Instead of HTTP call to custom endpoint
const result = await startData.waitForExit(30000);Current approach tests test worker implementation, not actual SDK.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Still seeing the same pattern in the new tests. Lines 363-373 in process-readiness-workflow.test.ts use HTTP fetch calls to custom endpoints. The E2E tests should use the SDK directly to validate the actual API users will consume.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Still relevant - custom endpoint added but no E2E tests using it. Added this to my main review.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The custom endpoint was added but no E2E tests were created that actually call the SDK. The test suite needs tests that verify process.waitForExit() works end-to-end in a real Worker environment.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The custom endpoint was added but no E2E tests were created that actually call the SDK. The test suite needs tests that verify process.waitForExit() works end-to-end in a real Worker environment.
ghostwriternr
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks good overall - but there's a lot of work being done to fetch logs, but I think we can separate concerns and keep waitForExit focused and leave fetching logs to the existing methods.
packages/shared/src/types.ts
Outdated
| /** Accumulated stdout output */ | ||
| stdout: string; | ||
| /** Accumulated stderr output */ | ||
| stderr: string; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Similar to the other waitFor methods, I think we can leave out accumulated logs from being returned in the response. If users need it, they anyway have access to the various log fetching utils right now. This method has a simple purpose that already gets solved without these.
packages/sandbox/src/sandbox.ts
Outdated
| const existingLogs = await this.getProcessLogs(processId); | ||
| collectedStdout = existingLogs.stdout; | ||
| collectedStderr = existingLogs.stderr; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If we remove the logs from output, we can perhaps completely get rid of all log-related logic from here.
packages/sandbox/src/sandbox.ts
Outdated
| // Stream logs and wait for exit event | ||
| const stream = await this.streamProcessLogs(processId); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same as above
| }); | ||
| }); | ||
|
|
||
| describe('waitForExit() method', () => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Tests can be more concise. Lots of overlap with current setup.
| ); | ||
| }, 60000); | ||
|
|
||
| test('should wait for process to exit and return exit code with output', async () => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
no-op: v nice e2e tests
|
Minor import order merge conflicts too, sorry about that |
Remove stdout/stderr accumulation from waitForExit() per review feedback. Users can fetch logs separately via getProcessLogs() or streamProcessLogs() if needed. This keeps the method focused on its single responsibility.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Claude Code Review
The waitForExit() implementation is clean and follows established patterns. The exit code fallback logic is correct - I verified that 'killed' and 'error' statuses don't set exitCode in the container runtime.
Issues to address:
-
Missing E2E tests - Custom test endpoint exists but no tests use it. Other readiness methods (waitForLog, waitForPort) have comprehensive E2E coverage in process-readiness-workflow.test.ts. This needs equivalent tests.
-
Generic Error instead of typed error - Line 1559 throws plain
Errorfor process not found. Should useProcessNotFoundErrorfor consistency with other process methods.
Minor improvements:
-
Add clarifying comment at line 1556 explaining why status is checked every iteration (unlike waitForPort which checks every 3rd to reduce latency - here the status IS what we're waiting for).
-
Consider enhancing JSDoc with
@param,@returns, and@throwstags for consistency.
The unit tests are comprehensive and the implementation is architecturally sound. Just needs E2E coverage and the error type fix before merge.
| const processInfo = await this.getProcess(processId); | ||
|
|
||
| if (!processInfo) { | ||
| throw new Error( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Use ProcessNotFoundError instead of generic Error for consistency with other process methods.
if (!processInfo) {
throw new ProcessNotFoundError({
code: ErrorCode.PROCESS_NOT_FOUND,
message: `Process ${processId} not found. It may have been cleaned up or never existed.`,
context: { processId },
httpStatus: 404,
timestamp: new Date().toISOString()
});
}Streaming is more efficient - single request to container instead of repeated polling. streamProcessLogs handles already-exited processes gracefully by sending the exit event immediately.
Documents the new Process.waitForExit() method that allows waiting for background processes to complete and retrieving their exit codes. Related to cloudflare/sandbox-sdk#299
packages/sandbox/src/sandbox.ts
Outdated
| for await (const event of parseSSEStream<LogEvent>(stream)) { | ||
| if (event.type === 'exit') { | ||
| return { | ||
| exitCode: event.exitCode ?? 0 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: should the fallback be 0 or 1? Assuming failure when we don't have a clean exit code might be better no?
ghostwriternr
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
lessgooo
Implemented waitForExit(timeout?) method to Process objects
also replaced the arbitrary setTimeout(resolve, 3000) workaround with waitForExit():
fixes #297