Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
19 changes: 19 additions & 0 deletions docs/worker/lambda-config.md
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,25 @@ With this configuration:

This is useful when you want to use conventional naming (e.g., `app.py` for Flask applications) or integrate existing code without renaming files.

### d. Sandbox Reuse

#### reuse_sandbox
By default, OpenLambda reuses the same sandbox across multiple invocations of a lambda function to improve performance. In some cases, such as when strict isolation is required or when avoiding state persistence between invocations, it may be desirable to create a fresh sandbox for each invocation.

This behavior can be controlled using the reuse-sandbox option.

Example:
```yaml
reuse-sandbox: false
```

With this configuration:

- A new sandbox is created for each lambda invocation
- The sandbox is destroyed after the invocation completes

If reuse-sandbox is not specified, OpenLambda defaults to reusing sandboxes across invocations.

## 4. How to Use
### a. Define Configuration
Create an `ol.yaml` file inside the lambda function directory with the desired configuration.
Expand Down
14 changes: 12 additions & 2 deletions go/common/lambdaConfig.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,8 +43,10 @@ type KafkaTrigger struct {

// LambdaConfig defines the overall configuration for the lambda function.
type LambdaConfig struct {
Triggers Triggers `yaml:"triggers"` // List of HTTP triggers
Environment map[string]string `yaml:"environment"` // Environment variables for the lambda
Triggers Triggers `yaml:"triggers"` // List of HTTP triggers
Environment map[string]string `yaml:"environment"` // Environment variables for the lambda
ReuseSandbox *bool `yaml:"reuse-sandbox,omitempty"` // controls whether a sandbox is reused across
// invocations.
// Additional configurations can be added here.
}

Expand Down Expand Up @@ -172,6 +174,14 @@ func ExtractConfigFromTarGz(tarPath string) (*LambdaConfig, error) {
return LoadDefaultLambdaConfig(), nil
}

// ReuseSandboxEnabled returns true if sandbox reuse is enabled, defaulting to true if not specified.
func (c *LambdaConfig) ReuseSandboxEnabled() bool {
if c == nil || c.ReuseSandbox == nil {
return true
}
return *c.ReuseSandbox
}

// IsHTTPMethodAllowed checks if a method is permitted for this function
func (config *LambdaConfig) IsHTTPMethodAllowed(method string) bool {
for _, trigger := range config.Triggers.HTTP {
Expand Down
16 changes: 15 additions & 1 deletion go/worker/lambda/lambdaInstance.go
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,12 @@ func (linst *LambdaInstance) Task() {
return
}

reuse := linst.meta.Config.ReuseSandboxEnabled()
if !reuse && sb != nil {
sb.Destroy("reuse-sandbox disabled: fresh sandbox per invocation")
sb = nil
}

t := common.T0("LambdaInstance-WaitSandbox")
// if we have a sandbox, try unpausing it to see if it is still alive
if sb != nil {
Expand Down Expand Up @@ -192,6 +198,14 @@ func (linst *LambdaInstance) Task() {
}
f.doneChan <- req

// If reuse is disabled, destroy the sandbox after invocation and stop processing more requests.
if !reuse && sb != nil {
sb.Destroy("reuse-sandbox disabled: destroying sandbox after invocation")
sb = nil
req = nil
break
}

// check whether we should shutdown (non-blocking)
select {
case killed := <-linst.killChan:
Expand Down Expand Up @@ -229,7 +243,7 @@ func (linst *LambdaInstance) Task() {
}
}

if sb != nil {
if reuse && sb != nil {
if err := sb.Pause(); err != nil {
f.printf("discard sandbox %s due to Pause error: %v", sb.ID(), err)
sb = nil
Expand Down