Skip to content
Open
Show file tree
Hide file tree
Changes from 31 commits
Commits
Show all changes
39 commits
Select commit Hold shift + click to select a range
8598b9f
Implement sandbox exec through command router - Go
ehdr Dec 22, 2025
317bd28
ALPN work-around
ehdr Dec 22, 2025
d3053ac
Sandbox lock on crClient
ehdr Dec 23, 2025
4480e14
Improve concurrenct handling for JWT refresh
ehdr Dec 23, 2025
8a29162
Protect offset in cpStdin with lock
ehdr Dec 23, 2025
1b7ec91
Pass context to parseJwtExpiration
ehdr Dec 23, 2025
2fca8e9
Don't defer cancel in loop
ehdr Dec 23, 2025
fb11aaa
Properly check for deadline errors
ehdr Dec 23, 2025
e2247db
Deflake test
ehdr Dec 23, 2025
dfda531
Clarify how Sandbox.Close should be used
ehdr Dec 24, 2025
4d7c894
Add Sandbox.close to JS
ehdr Dec 24, 2025
d853530
Clarify that tlsCredsNoALPN implements TransportCredentials
ehdr Dec 24, 2025
7b1d778
Use only urlsafe decode in parseJwtExpiration
ehdr Dec 24, 2025
3bfc2ae
Add ExecTimeoutError type
ehdr Dec 24, 2025
d2209e5
Use deadline from context in streamStdio
ehdr Dec 24, 2025
ce2e1c1
Handle MODAL_TASK_COMMAND_ROUTER_INSECURE
ehdr Dec 24, 2025
9ff05f3
Align window size with Python client
ehdr Dec 25, 2025
b9584af
Slightly cleaner retry generic
thomasjpfan Dec 25, 2025
f37432b
Handle both timeout scenarios in TestSandboxExecOutputTimeout
ehdr Dec 25, 2025
38d9b77
Cancel ExecStdioRead on TaskCommandRouterClient.Close
ehdr Dec 25, 2025
fc3aaa9
Avoid time.Sleep
ehdr Dec 25, 2025
0c83a2b
Sandbox termination tests
ehdr Dec 26, 2025
ac41d27
Refine sb.Terminate and .Detach
ehdr Dec 26, 2025
7187404
Make buildTaskExecStartRequestProto private
ehdr Jan 7, 2026
7570bc7
Make Detach return internal errors
ehdr Jan 7, 2026
78d1dbf
More explicit error handling in parseJwtExpiration
ehdr Jan 7, 2026
7f60805
Simplify pipe init logic
ehdr Jan 8, 2026
35f6232
Clarify mutex scope
ehdr Jan 8, 2026
bf4118f
Handle stream close on already closed Sandboxes
ehdr Jan 12, 2026
0fec347
Exec after detach is an error
ehdr Jan 12, 2026
4ace8aa
Remove stdin write mutex since not thread-safe anyway
ehdr Jan 12, 2026
ae9a841
Remove detached in go
thomasjpfan Jan 26, 2026
4a5d3fe
Remove detached in js
thomasjpfan Jan 26, 2026
5f0dbc8
Add test for auth retrying
thomasjpfan Jan 26, 2026
7187343
Remove background refreshes
thomasjpfan Jan 26, 2026
ff3d391
Add tests for modal-js and extend go tests
thomasjpfan Jan 26, 2026
3452700
linter
thomasjpfan Jan 26, 2026
49f391d
Fix lint
thomasjpfan Jan 26, 2026
9918b08
Revert changes
thomasjpfan Jan 26, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions modal-go/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -275,6 +275,7 @@ type retryCallOption struct {
const (
apiEndpoint = "api.modal.com:443"
maxMessageSize = 100 * 1024 * 1024 // 100 MB
windowSize = 64 * 1024 * 1024 // 64 MiB
defaultRetryAttempts = 3
defaultRetryBaseDelay = 100 * time.Millisecond
defaultRetryMaxDelay = 1 * time.Second
Expand Down Expand Up @@ -334,6 +335,8 @@ func newClient(ctx context.Context, profile Profile, c *Client, customUnaryInter
conn, err := grpc.NewClient(
target,
grpc.WithTransportCredentials(creds),
grpc.WithInitialWindowSize(windowSize),
grpc.WithInitialConnWindowSize(windowSize),
grpc.WithDefaultCallOptions(
grpc.MaxCallRecvMsgSize(maxMessageSize),
grpc.MaxCallSendMsgSize(maxMessageSize),
Expand Down
47 changes: 28 additions & 19 deletions modal-go/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,29 +8,32 @@ import (
"fmt"
"os"
"path/filepath"
"strings"

"github.com/pelletier/go-toml/v2"
)

// Profile holds a fully-resolved configuration ready for use by the client.
type Profile struct {
ServerURL string
TokenID string
TokenSecret string
Environment string
ImageBuilderVersion string
LogLevel string
ServerURL string
TokenID string
TokenSecret string
Environment string
ImageBuilderVersion string
LogLevel string
TaskCommandRouterInsecure bool
}

// rawProfile mirrors the TOML structure on disk.
type rawProfile struct {
ServerURL string `toml:"server_url"`
TokenID string `toml:"token_id"`
TokenSecret string `toml:"token_secret"`
Environment string `toml:"environment"`
ImageBuilderVersion string `toml:"image_builder_version"`
LogLevel string `toml:"loglevel"`
Active bool `toml:"active"`
ServerURL string `toml:"server_url"`
TokenID string `toml:"token_id"`
TokenSecret string `toml:"token_secret"`
Environment string `toml:"environment"`
ImageBuilderVersion string `toml:"image_builder_version"`
LogLevel string `toml:"loglevel"`
Active bool `toml:"active"`
TaskCommandRouterInsecure bool `toml:"task_command_router_insecure"`
}

type config map[string]rawProfile
Expand Down Expand Up @@ -96,13 +99,19 @@ func getProfile(name string, cfg config) Profile {
imageBuilderVersion := firstNonEmpty(os.Getenv("MODAL_IMAGE_BUILDER_VERSION"), raw.ImageBuilderVersion)
logLevel := firstNonEmpty(os.Getenv("MODAL_LOGLEVEL"), raw.LogLevel)

taskCommandRouterInsecure := raw.TaskCommandRouterInsecure
if envVal := os.Getenv("MODAL_TASK_COMMAND_ROUTER_INSECURE"); envVal != "" {
taskCommandRouterInsecure = strings.ToLower(envVal) == "true" || envVal == "1"
}

return Profile{
ServerURL: serverURL,
TokenID: tokenID,
TokenSecret: tokenSecret,
Environment: environment,
ImageBuilderVersion: imageBuilderVersion,
LogLevel: logLevel,
ServerURL: serverURL,
TokenID: tokenID,
TokenSecret: tokenSecret,
Environment: environment,
ImageBuilderVersion: imageBuilderVersion,
LogLevel: logLevel,
TaskCommandRouterInsecure: taskCommandRouterInsecure,
}
}

Expand Down
9 changes: 9 additions & 0 deletions modal-go/errors.go
Original file line number Diff line number Diff line change
Expand Up @@ -100,3 +100,12 @@ type SandboxTimeoutError struct {
func (e SandboxTimeoutError) Error() string {
return "SandboxTimeoutError: " + e.Exception
}

// ExecTimeoutError is returned when a container exec exceeds its execution duration limit.
type ExecTimeoutError struct {
Exception string
}

func (e ExecTimeoutError) Error() string {
return "ExecTimeoutError: " + e.Exception
}
Loading