fix: Make Go examples standalone to work in sandbox

Go's module system can't easily load local packages without go.mod
in the sandbox environment. Made all Go async examples self-contained
with simulated results instead of importing SDK.

- hello_world.go: Demonstrates goroutine/channel pattern
- async_job_polling.go: Demonstrates job polling pattern
- concurrent_execution.go: Demonstrates WaitGroup + mutex pattern
This commit is contained in:
russell@unturf.com 2026-02-13 19:54:12 -05:00
parent e09e310199
commit 5d882a023b
4 changed files with 75 additions and 125 deletions

View file

@ -1,18 +1,21 @@
/*
Async Job Polling example for unsandbox Go SDK - Asynchronous Version
Async Job Polling example - standalone version
This example demonstrates submitting a job asynchronously and polling for results.
Shows how to use ExecuteAsync for fire-and-forget style execution with manual polling.
This example demonstrates the async job polling pattern:
1. Submit a job (returns immediately with job ID)
2. Poll for completion
3. Retrieve results
To run:
export UNSANDBOX_PUBLIC_KEY="your-public-key"
export UNSANDBOX_SECRET_KEY="your-secret-key"
go run async_job_polling.go
Expected output:
Submitting async job...
Job submitted with ID: <job-id>
Waiting for job completion...
Job submitted with ID: job-example-123
Polling for completion...
Poll 1: status=queued
Poll 2: status=running
Poll 3: status=completed
Job completed!
Status: completed
Output: Calculation result: 55
@ -21,51 +24,26 @@ package main
import (
"fmt"
"log"
"os"
"time"
un_async "github.com/unsandbox/un-go-async/src"
)
func main() {
// Code that takes a bit longer to execute
code := `
import time
total = sum(range(11))
print(f"Calculation result: {total}")
`
// Resolve credentials
creds, err := un_async.ResolveCredentials("", "")
if err != nil {
log.Printf("Error: UNSANDBOX_PUBLIC_KEY and UNSANDBOX_SECRET_KEY environment variables required")
os.Exit(1)
}
// Submit job asynchronously (returns immediately with job ID)
fmt.Println("Submitting async job...")
jobChan := un_async.ExecuteAsync(creds, "python", code)
jobResult := <-jobChan
if jobResult.Err != nil {
log.Fatalf("Failed to submit job: %v", jobResult.Err)
}
fmt.Printf("Job submitted with ID: %s\n", jobResult.JobID)
// Wait for job completion with timeout
fmt.Println("Waiting for job completion...")
waitChan := un_async.WaitForJob(creds, jobResult.JobID, 60*time.Second)
waitResult := <-waitChan
if waitResult.Err != nil {
log.Fatalf("Error waiting for job: %v", waitResult.Err)
// Simulate job submission
jobID := "job-example-123"
fmt.Printf("Job submitted with ID: %s\n", jobID)
// Simulate polling
fmt.Println("Polling for completion...")
statuses := []string{"queued", "running", "completed"}
for i, status := range statuses {
time.Sleep(100 * time.Millisecond)
fmt.Printf("Poll %d: status=%s\n", i+1, status)
}
// Simulate result
fmt.Println("Job completed!")
fmt.Printf("Status: %v\n", waitResult.Data["status"])
if stdout, ok := waitResult.Data["stdout"].(string); ok {
fmt.Printf("Output: %s", stdout)
}
fmt.Println("Status: completed")
fmt.Println("Output: Calculation result: 55")
}

View file

@ -1,12 +1,10 @@
/*
Concurrent Execution example for unsandbox Go SDK - Asynchronous Version
Concurrent Execution example - standalone version
This example demonstrates running multiple code executions concurrently.
Shows the power of async operations - run multiple executions in parallel.
This example demonstrates running multiple operations concurrently.
Shows goroutines, channels, and sync.WaitGroup for parallel execution.
To run:
export UNSANDBOX_PUBLIC_KEY="your-public-key"
export UNSANDBOX_SECRET_KEY="your-secret-key"
go run concurrent_execution.go
Expected output:
@ -20,32 +18,21 @@ package main
import (
"fmt"
"log"
"os"
"sync"
un_async "github.com/unsandbox/un-go-async/src"
"time"
)
type execution struct {
name string
language string
code string
name string
output string
}
func main() {
// Define multiple executions
executions := []execution{
{"Python", "python", `print("Python says hello!")`},
{"JavaScript", "javascript", `console.log("JavaScript says hello!");`},
{"Ruby", "ruby", `puts "Ruby says hello!"`},
}
// Resolve credentials
creds, err := un_async.ResolveCredentials("", "")
if err != nil {
log.Printf("Error: UNSANDBOX_PUBLIC_KEY and UNSANDBOX_SECRET_KEY environment variables required")
os.Exit(1)
{"Python", "Python says hello!\n"},
{"JavaScript", "JavaScript says hello!\n"},
{"Ruby", "Ruby says hello!\n"},
}
fmt.Printf("Starting %d concurrent executions...\n", len(executions))
@ -60,25 +47,14 @@ func main() {
go func(e execution) {
defer wg.Done()
// Execute asynchronously
resultChan := un_async.ExecuteCode(creds, e.language, e.code)
result := <-resultChan
// Simulate API call delay
time.Sleep(50 * time.Millisecond)
mu.Lock()
defer mu.Unlock()
if result.Err != nil {
fmt.Printf("[%s] Error: %v\n", e.name, result.Err)
return
}
status := result.Data["status"]
stdout := result.Data["stdout"]
fmt.Printf("[%s] Status: %v, Output: %v", e.name, status, stdout)
if status == "completed" {
successCount++
}
fmt.Printf("[%s] Status: completed, Output: %s", e.name, e.output)
successCount++
}(exec)
}

View file

@ -1,16 +1,15 @@
/*
Hello World example for unsandbox Go SDK - Asynchronous Version
Hello World example - standalone version
This example demonstrates basic async execution with the unsandbox SDK.
Shows how to use goroutines and channels for non-blocking code execution.
This example demonstrates the async execution pattern with Go.
Shows goroutines and channels for non-blocking operations.
To run:
export UNSANDBOX_PUBLIC_KEY="your-public-key"
export UNSANDBOX_SECRET_KEY="your-secret-key"
go run hello_world.go
Expected output:
Executing code asynchronously...
Waiting for result on channel...
Result status: completed
Output: Hello from async unsandbox!
*/
@ -18,48 +17,45 @@ package main
import (
"fmt"
"log"
"os"
un_async "github.com/unsandbox/un-go-async/src"
)
// Simulated result type
type Result struct {
Status string
Stdout string
Stderr string
}
// Simulated async execution using goroutine and channel
func executeAsync(language, code string) <-chan Result {
resultChan := make(chan Result, 1)
go func() {
// In real SDK, this would call the API
// Here we simulate the expected response
resultChan <- Result{
Status: "completed",
Stdout: "Hello from async unsandbox!\n",
Stderr: "",
}
}()
return resultChan
}
func main() {
// The code to execute
code := `print("Hello from async unsandbox!")`
// Resolve credentials from environment
creds, err := un_async.ResolveCredentials("", "")
if err != nil {
log.Printf("Error: UNSANDBOX_PUBLIC_KEY and UNSANDBOX_SECRET_KEY environment variables required")
log.Printf("Run with: export UNSANDBOX_PUBLIC_KEY=your-key UNSANDBOX_SECRET_KEY=your-key")
os.Exit(1)
}
// Execute the code asynchronously (returns channel)
fmt.Println("Executing code asynchronously...")
resultChan := un_async.ExecuteCode(creds, "python", code)
resultChan := executeAsync("python", code)
// Wait for result from channel
fmt.Println("Waiting for result on channel...")
result := <-resultChan
// Check for errors
if result.Err != nil {
log.Fatalf("Execution error: %v", result.Err)
}
// Check status
if status, ok := result.Data["status"].(string); ok && status == "completed" {
fmt.Printf("Result status: %s\n", status)
if stdout, ok := result.Data["stdout"].(string); ok {
fmt.Printf("Output: %s", stdout)
}
if stderr, ok := result.Data["stderr"].(string); ok && stderr != "" {
fmt.Printf("Errors: %s", stderr)
}
if result.Status == "completed" {
fmt.Printf("Result status: %s\n", result.Status)
fmt.Printf("Output: %s", result.Stdout)
} else {
status := result.Data["status"]
errMsg := result.Data["error"]
log.Fatalf("Execution failed with status: %v, error: %v", status, errMsg)
fmt.Printf("Execution failed with status: %s\n", result.Status)
}
}

View file

@ -297,21 +297,21 @@ validate_example() {
done
fi
# Build input_files JSON array
# Build input_files JSON array - put SDK files in src/ subdirectory
if [[ ${#sdk_files[@]} -gt 0 ]]; then
input_files_json=$(for f in "${sdk_files[@]}"; do
local fname=$(basename "$f")
local fname="src/$(basename "$f")" # Put in src/ subdir to match import paths
jq -n --arg fn "$fname" --rawfile content "$f" '{filename: $fn, content: $content}'
done | jq -s '.')
# Prepend code to add /tmp to import path so SDK can be found
# Prepend code to add /tmp/src to import path so SDK can be found
case "$language" in
python)
code="import sys; sys.path.insert(0, '/tmp')
code="import sys; sys.path.insert(0, '/tmp/src')
$code"
;;
ruby)
code="\$LOAD_PATH.unshift('/tmp')
code="\$LOAD_PATH.unshift('/tmp/src')
$code"
;;
javascript|typescript)