Skip to content

Commit 0682a7e

Browse files
authored
Merge pull request fastschema#23 from danslo/persistent-cache
add cacheDir option
2 parents e43d8a1 + 051736a commit 0682a7e

4 files changed

Lines changed: 45 additions & 1 deletion

File tree

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -719,6 +719,7 @@ type Option struct {
719719
MemoryLimit int // Memory usage limit
720720
MaxExecutionTime int // Execution timeout
721721
GCThreshold int // GC trigger threshold
722+
CacheDir string // Compilation cache directory
722723
}
723724
```
724725

options.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ type Option struct {
3838
// because every operation must check the done context, which introduces additional overhead.
3939
CloseOnContextDone bool
4040
DisableBuildCache bool
41+
CacheDir string
4142
MemoryLimit int
4243
MaxStackSize int
4344
MaxExecutionTime int

runtime.go

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ func createGlobalCompiledModule(
4040
ctx context.Context,
4141
closeOnContextDone bool,
4242
disableBuildCache bool,
43+
cacheDir string,
4344
quickjsWasmBytes ...[]byte,
4445
) (err error) {
4546
// Protect global compilation state with mutex
@@ -58,7 +59,13 @@ func createGlobalCompiledModule(
5859

5960
// Check if we need to compile or recompile
6061
if compiledQJSModule == nil || cachedBytesHash != currentHash || disableBuildCache {
61-
cache := wazero.NewCompilationCache()
62+
var cache wazero.CompilationCache
63+
if cacheDir == "" {
64+
cache = wazero.NewCompilationCache()
65+
} else if cache, err = wazero.NewCompilationCacheWithDir(cacheDir); err != nil {
66+
return fmt.Errorf("failed to create compilation cache with dir %s: %w", cacheDir, err)
67+
}
68+
6269
cachedRuntimeConfig = wazero.
6370
NewRuntimeConfig().
6471
WithCompilationCache(cache).
@@ -96,6 +103,7 @@ func New(options ...Option) (runtime *Runtime, err error) {
96103
option.Context,
97104
option.CloseOnContextDone,
98105
option.DisableBuildCache,
106+
option.CacheDir,
99107
option.QuickJSWasmBytes,
100108
); err != nil {
101109
return nil, fmt.Errorf("failed to create global compiled module: %w", err)

runtime_test.go

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ package qjs_test
33
import (
44
"context"
55
"fmt"
6+
"os"
67
"sync"
78
"testing"
89
"time"
@@ -255,6 +256,39 @@ func TestRuntime(t *testing.T) {
255256
require.NoError(t, err, "Normal runtime creation should still work after invalid attempt")
256257
defer rt2.Close()
257258
})
259+
260+
t.Run("CacheDirOption", func(t *testing.T) {
261+
cacheDir := t.TempDir()
262+
rt1, err := qjs.New(qjs.Option{CacheDir: cacheDir, DisableBuildCache: true})
263+
require.NoError(t, err)
264+
265+
val, err := rt1.Eval("test.js", qjs.Code("21 + 21"))
266+
require.NoError(t, err)
267+
assert.Equal(t, int32(42), val.Int32())
268+
val.Free()
269+
270+
rt1.Close()
271+
entries, err := os.ReadDir(cacheDir)
272+
require.NoError(t, err)
273+
assert.NotEmpty(t, entries, "Cache directory should not be empty")
274+
})
275+
276+
t.Run("CacheDirWithEmptyString", func(t *testing.T) {
277+
rt, err := qjs.New(qjs.Option{CacheDir: "", DisableBuildCache: true})
278+
require.NoError(t, err)
279+
defer rt.Close()
280+
281+
val, err := rt.Eval("test.js", qjs.Code("2 * 21"))
282+
require.NoError(t, err)
283+
assert.Equal(t, int32(42), val.Int32())
284+
val.Free()
285+
})
286+
287+
t.Run("CacheDirWithInvalidPath", func(t *testing.T) {
288+
_, err := qjs.New(qjs.Option{CacheDir: "/invalid/path/that/does/not/exist", DisableBuildCache: true})
289+
require.Error(t, err)
290+
assert.Contains(t, err.Error(), "failed to create compilation cache")
291+
})
258292
}
259293

260294
// Concurrent Runtime Usage Tests

0 commit comments

Comments
 (0)