diff --git a/examples/experimental/fs/fs-openclose.js b/examples/experimental/fs/fs-openclose.js index 5e7eb7a91a02..414c1e8555a8 100644 --- a/examples/experimental/fs/fs-openclose.js +++ b/examples/experimental/fs/fs-openclose.js @@ -2,8 +2,8 @@ import { open } from "k6/experimental/fs"; import { sleep } from "k6"; export const options = { - vus: 10, - iterations: 10, + vus: 1, + iterations: 1, }; let file; @@ -11,7 +11,11 @@ let file; file = await open("bonjour.txt"); })(); +export async function setup() { + return { something: 'crazy' }; +} + export default async function () { file.close(); - sleep(10); + sleep(1); } \ No newline at end of file diff --git a/js/modules/k6/experimental/fs/cache.go b/js/modules/k6/experimental/fs/cache.go index e584b11a11a5..a60bd595c596 100644 --- a/js/modules/k6/experimental/fs/cache.go +++ b/js/modules/k6/experimental/fs/cache.go @@ -64,15 +64,28 @@ func (fr *cache) open(filename string, fromFs afero.Fs) ([]byte, error) { panic(fmt.Errorf("registry's file %s is not stored as a byte slice", filename)) } - // Increase the ref count. + // As this is the first time we open the file, initialize + // the ref count to 1. fr.mutex.Lock() - fr.openedRefCounts[filename]++ - fmt.Println("cache.open[file already loaded]: openedRefCount=", fr.openedRefCounts[filename]) + fmt.Println("cache.open[initializing open]: openedRefCount=", 1) + if c, ok := fr.openedRefCounts[filename]; ok { + fr.openedRefCounts[filename] = c + 1 + } else { + fr.openedRefCounts[filename] = 1 + } + // fr.openedRefCounts[filename] = 1 + fmt.Println("cache.open[initializing open]: openedRefCount=", 1) fr.mutex.Unlock() return data, nil } + // // Increase the ref count. + // fr.mutex.Lock() + // fr.openedRefCounts[filename]++ + // fmt.Println("cache.open[file already loaded]: openedRefCount=", fr.openedRefCounts[filename]) + // fr.mutex.Unlock() + // The underlying afero.Fs.Open method will cache the file content during this // operation. Which will lead to effectively holding the content of the file in memory twice. // However, as per #1079, we plan to eventually reduce our dependency on afero, and @@ -90,13 +103,6 @@ func (fr *cache) open(filename string, fromFs afero.Fs) ([]byte, error) { fr.openedFiles.Store(filename, data) - // As this is the first time we open the file, initialize - // the ref count to 1. - fr.mutex.Lock() - fr.openedRefCounts[filename] = 1 - fmt.Println("cache.open[initializing open]: openedRefCount=", 1) - fr.mutex.Unlock() - return data, nil } @@ -116,6 +122,7 @@ func (fr *cache) close(filename string) error { } // Decrease the ref count. + fmt.Println("cache.close: decreasing ref count") fr.openedRefCounts[filename]-- fmt.Println("cache.close: openedRefCount=", fr.openedRefCounts[filename]) diff --git a/js/modules/k6/experimental/fs/module.go b/js/modules/k6/experimental/fs/module.go index df45e6ea54c0..00dd7b852bc8 100644 --- a/js/modules/k6/experimental/fs/module.go +++ b/js/modules/k6/experimental/fs/module.go @@ -57,6 +57,7 @@ func (mi *ModuleInstance) Exports() modules.Exports { // Open opens a file and returns a promise that will resolve to a [File] instance func (mi *ModuleInstance) Open(path goja.Value) *goja.Promise { + fmt.Println("Open called") promise, resolve, reject := promises.New(mi.vu) // Files can only be opened in the init context. @@ -169,6 +170,13 @@ func (f *File) Stat() *goja.Promise { // Close closes the file. func (f *File) Close() { + if f.vu.State() == nil { + common.Throw( + f.vu.Runtime(), + newFsError(ForbiddenError, "close() failed; reason: closing a file outside of the VU stage is forbidden"), + ) + } + if err := f.file.close(); err != nil { common.Throw(f.vu.Runtime(), err) }