Skip to content

Commit

Permalink
feat: clean all if no space left
Browse files Browse the repository at this point in the history
  • Loading branch information
x1unix committed Feb 5, 2024
1 parent ba9a2fa commit db25919
Show file tree
Hide file tree
Showing 3 changed files with 62 additions and 1 deletion.
20 changes: 20 additions & 0 deletions internal/builder/compiler.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,11 @@ package builder
import (
"bytes"
"context"
"errors"
"fmt"
"os"
"syscall"
"time"

"github.com/x1unix/go-playground/internal/builder/storage"
"github.com/x1unix/go-playground/pkg/util/osutil"
Expand Down Expand Up @@ -94,6 +97,10 @@ func (s BuildService) Build(ctx context.Context, files map[string][]byte) (*Resu

workspace, err := s.storage.CreateWorkspace(aid, files)
if err != nil {
if errors.Is(err, syscall.ENOSPC) {
// Immediately schedule cleanup job!
s.handleNoSpaceLeft()
}
return nil, err
}

Expand All @@ -110,6 +117,19 @@ func (s BuildService) buildSource(ctx context.Context, workspace *storage.Worksp
return s.runGoTool(ctx, workspace.WorkDir, "build", "-o", workspace.BinaryPath, ".")
}

func (s BuildService) handleNoSpaceLeft() {
s.log.Warn("no space left on device, immediate clean triggered!")
ctx, cancelFn := context.WithTimeout(context.Background(), time.Minute)
defer cancelFn()

if err := s.storage.Clean(ctx); err != nil {
s.log.Error("failed to clear storage", zap.Error(err))
}
if err := s.Clean(ctx); err != nil {
s.log.Error("failed to clear Go cache", zap.Error(err))
}
}

func (s BuildService) runGoTool(ctx context.Context, workDir string, args ...string) error {
cmd := newGoToolCommand(ctx, args...)
cmd.Dir = workDir
Expand Down
39 changes: 38 additions & 1 deletion internal/builder/compiler_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (
"io/ioutil"
"os"
"strings"
"syscall"
"testing"

"github.com/stretchr/testify/require"
Expand All @@ -27,6 +28,7 @@ type testStorage struct {
hasItem func(id storage.ArtifactID) (bool, error)
getItem func(id storage.ArtifactID) (storage.ReadCloseSizer, error)
createWorkspace func(id storage.ArtifactID, entries map[string][]byte) (*storage.Workspace, error)
clean func(ctx context.Context) error
}

func (ts testStorage) HasItem(id storage.ArtifactID) (bool, error) {
Expand All @@ -41,6 +43,14 @@ func (ts testStorage) CreateWorkspace(id storage.ArtifactID, entries map[string]
return ts.createWorkspace(id, entries)
}

func (ts testStorage) Clean(ctx context.Context) error {
if ts.clean != nil {
return ts.clean(ctx)
}

return errors.New("not implemented")
}

func TestBuildService_GetArtifact(t *testing.T) {
cases := map[string]struct {
artifactID storage.ArtifactID
Expand Down Expand Up @@ -95,6 +105,7 @@ func TestBuildService_Build(t *testing.T) {
cases := map[string]struct {
skip bool
files map[string][]byte
env osutil.EnvironmentVariables
wantErr string
wantResult func(files map[string][]byte) *Result
beforeRun func(t *testing.T)
Expand Down Expand Up @@ -227,6 +238,30 @@ func TestBuildService_Build(t *testing.T) {
return nil, nil
},
},
"handle no space left": {
wantErr: "no space left",
env: osutil.EnvironmentVariables{
"PATH": ".",
"GOPATH": "/tmp",
},
files: map[string][]byte{
"main.go": []byte("package main"),
},
store: func(t *testing.T, _ map[string][]byte) (storage.StoreProvider, func() error) {
return testStorage{
hasItem: func(id storage.ArtifactID) (bool, error) {
return false, nil
},
createWorkspace: func(id storage.ArtifactID, entries map[string][]byte) (*storage.Workspace, error) {
return nil, &os.PathError{Err: syscall.ENOSPC, Op: "write"}
},
clean: func(_ context.Context) error {
t.Log("cleanup called")
return nil
},
}, nil
},
},
}

for n, c := range cases {
Expand All @@ -249,7 +284,9 @@ func TestBuildService_Build(t *testing.T) {
}()
}

bs := NewBuildService(zaptest.NewLogger(t), BuildEnvironmentConfig{}, store)
bs := NewBuildService(zaptest.NewLogger(t), BuildEnvironmentConfig{
IncludedEnvironmentVariables: c.env,
}, store)
got, err := bs.Build(context.TODO(), c.files)
if c.wantErr != "" {
if c.onErrorCheck != nil {
Expand Down
4 changes: 4 additions & 0 deletions internal/builder/storage/storage.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package storage

import (
"context"
"errors"
"io"
)
Expand Down Expand Up @@ -38,4 +39,7 @@ type StoreProvider interface {

// CreateWorkspace creates workspace entry in storage
CreateWorkspace(id ArtifactID, files map[string][]byte) (*Workspace, error)

// Clean truncates storage contents
Clean(ctx context.Context) error
}

0 comments on commit db25919

Please sign in to comment.