Refactor: extract 'get the embedded filesystem' to a separate function

The global `scriptFS` variable was too easy to access, which caused an
issue where the mandatory `"scripts"` subdirectory was not passed.
Accessing via a getter function that hides this requirement prevents this.
This commit is contained in:
Sybren A. Stüvel 2022-06-20 17:43:08 +02:00
parent 201236cf46
commit defa5b0431
4 changed files with 66 additions and 11 deletions

View File

@ -61,7 +61,7 @@ func Load(ts TimeService) (*Service, error) {
staticFileLoader := func(path string) ([]byte, error) { staticFileLoader := func(path string) ([]byte, error) {
// TODO: this should try different filesystems, once we allow loading from // TODO: this should try different filesystems, once we allow loading from
// disk as well. // disk as well.
content, err := loadScriptBytes(scriptsFS, path) content, err := loadScriptBytes(getEmbeddedScriptFS(), path)
if err != nil { if err != nil {
// The 'require' module uses this to try different variations of the path // The 'require' module uses this to try different variations of the path
// in order to find it (without .js, with .js, etc.), so don't log any of // in order to find it (without .js, with .js, etc.), so don't log any of

View File

@ -3,7 +3,6 @@ package job_compilers
// SPDX-License-Identifier: GPL-3.0-or-later // SPDX-License-Identifier: GPL-3.0-or-later
import ( import (
"embed"
"fmt" "fmt"
"io" "io"
"io/fs" "io/fs"
@ -15,18 +14,10 @@ import (
"github.com/rs/zerolog/log" "github.com/rs/zerolog/log"
) )
//go:embed scripts
var scriptsFS embed.FS
// loadScripts iterates over all JavaScript files, compiles them, and stores the // loadScripts iterates over all JavaScript files, compiles them, and stores the
// result into `s.compilers`. // result into `s.compilers`.
func (s *Service) loadScripts() error { func (s *Service) loadScripts() error {
scriptsSubFS, err := fs.Sub(scriptsFS, "scripts") compilers, err := loadScriptsFrom(getEmbeddedScriptFS())
if err != nil {
return fmt.Errorf("failed to find embedded 'scripts' directory: %w", err)
}
compilers, err := loadScriptsFrom(scriptsSubFS)
if err != nil { if err != nil {
return err return err
} }

View File

@ -0,0 +1,28 @@
package job_compilers
// SPDX-License-Identifier: GPL-3.0-or-later
import (
"embed"
"fmt"
"io/fs"
)
// Scripts from the `./scripts` subdirectory are embedded into the executable
// here. Note that accessing these files still requires explicit use of the
// `scripts/` subdirectory, which is abstracted away by `getEmbeddedScriptFS()`.
// It is recommended to use that function to get the embedded scripts
// filesystem.
//go:embed scripts
var _embeddedScriptsFS embed.FS
// getEmbeddedScriptFS returns the `fs.FS` interface that allows access to the
// embedded job compiler scripts.
func getEmbeddedScriptFS() fs.FS {
scriptsSubFS, err := fs.Sub(_embeddedScriptsFS, "scripts")
if err != nil {
panic(fmt.Sprintf("failed to find embedded 'scripts' directory: %v", err))
}
return scriptsSubFS
}

View File

@ -1,9 +1,12 @@
package job_compilers package job_compilers
// SPDX-License-Identifier: GPL-3.0-or-later
import ( import (
"os" "os"
"testing" "testing"
"github.com/rs/zerolog"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
) )
@ -27,6 +30,39 @@ func TestLoadScriptsFrom_on_disk_js(t *testing.T) {
assert.Equal(t, expectKeys, keys(compilers)) assert.Equal(t, expectKeys, keys(compilers))
} }
func TestLoadScriptsFrom_embedded(t *testing.T) {
compilers, err := loadScriptsFrom(getEmbeddedScriptFS())
assert.NoError(t, err)
expectKeys := map[string]bool{
"echo-sleep-test": true,
"simple-blender-render": true,
}
assert.Equal(t, expectKeys, keys(compilers))
}
func BenchmarkLoadScripts_fromEmbedded(b *testing.B) {
zerolog.SetGlobalLevel(zerolog.Disabled)
embeddedFS := getEmbeddedScriptFS()
for i := 0; i < b.N; i++ {
compilers, err := loadScriptsFrom(embeddedFS)
assert.NoError(b, err)
assert.NotEmpty(b, compilers)
}
}
func BenchmarkLoadScripts_fromDisk(b *testing.B) {
zerolog.SetGlobalLevel(zerolog.Disabled)
onDiskFS := os.DirFS("scripts-for-unittest")
for i := 0; i < b.N; i++ {
compilers, err := loadScriptsFrom(onDiskFS)
assert.NoError(b, err)
assert.NotEmpty(b, compilers)
}
}
// keys returns the set of keys of the mapping. // keys returns the set of keys of the mapping.
func keys[K comparable, V any](mapping map[K]V) map[K]bool { func keys[K comparable, V any](mapping map[K]V) map[K]bool {
keys := map[K]bool{} keys := map[K]bool{}