-
Notifications
You must be signed in to change notification settings - Fork 1.3k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add a design document proposal to support open in VU context #3358
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,101 @@ | ||
# Opening files within the VU stage | ||
|
||
|
||
| Date | Change | | ||
| --- | --- | | ||
| Authors | @oleiade | | ||
| Status | Draft | | ||
| Issue | [#3020](https://github.com/grafana/k6/issues/3020) | ||
|
||
## Problem statement | ||
|
||
In its present state, k6's approach to handling external files, both in local/OSS and cloud contexts, restricts the ability to open files within the VU (Virtual User) stage. | ||
|
||
Question: **How might we enable k6 to access external resources directly from the VU stage?** | ||
|
||
|
||
### Rationale | ||
|
||
One of k6 main features is the ability to create reproducible, idempotent archives. These archives can be run consistently across various environments, permitting users to draft scripts locally and then either upload or execute them in the cloud. | ||
|
||
To accomplish this, k6 assembles user scripts and their associated assets (which can range from other scripts, as well as text (JSON, CSV, etc.) and binary files (protobuf, images, etc.)) into a specific tar archive format. Furthermore, k6 can initiate a test by unpacking and executing such an archive. | ||
|
||
However, when dealing with file access, a significant limitation arises: for k6 to maintain its idempotent behavior, it must preemptively recognize which resources to incorporate in the archive and their locations. | ||
|
||
|
||
Yet, if users dynamically determine file paths during script execution (rather than during compilation), k6 can't predict the resources accessed within the VU stage. | ||
|
||
This unpredictability stems from the fact that the VU stage is only evaluated (and any dynamic variables are only assigned) when k6 starts the VU execution of the script. Therefore, k6's current design confines file access to the init stage, which is executed a single time before VU activities commence, and any processes within the init stage are subsequently available to the VU stage. | ||
|
||
### Requirements | ||
|
||
- **File access in VU stage**: The adopted solution should permit file access both within the VU stage and the init stage. | ||
- **Idempotency and reproducibility**: The adopted solution should ensure that the archives remain reproducible and idempotent, irrespective of where files are accessed. | ||
- **Backward compatibility**: The adopted solution should be compatible with the current k6 archive command and should not require any change to the command itself. Namely, it should remain possible to open files in the init stage. | ||
- **Developer experience**: The adopted solution should improve the developer experience and limit the cost of adopting the new file handling. | ||
- **Error handling**: The adopted solution should allow for and provide precise error handling and transparent reporting, especially when dealing with file access issues or conflicts in the VU stage (which is a strength of the current way of handling files). | ||
- **Backward compatibility**: The adopted solution should refrain from introducing breaking changes to the current solution. | ||
|
||
## Possible Solutions | ||
|
||
### Solution A: Prior declaration of resources | ||
|
||
#### Using a dedicated API | ||
|
||
We can provide an API, possibly as part of the new fs module, for users to explicitly include files. | ||
|
||
```javascript | ||
import { open, include } from "k6/experimental/fs"; | ||
|
||
include('my/source/file.txt') | ||
include('my/dir') | ||
|
||
export default function () { | ||
// succeeds | ||
await open('my/source/file.txt'); | ||
|
||
// fails with 'resource csvs/data.csv not included by k6, ...' | ||
await open('csvs/data.csv') | ||
} | ||
``` | ||
|
||
**Key Points**: | ||
- The `include` function is only usable in the init stage. Invoking it within VU code will trigger an error. | ||
- Using `include` ensures a file's inclusion during the archive process, making it accessible in the VU stage. | ||
- Opening an un-included file in the VU stage will result in an error. | ||
Files opened in the init stage without prior inclusion should still operate as they currently do (though this is debatable) to maintain backward compatibility. | ||
|
||
#### Using dedicated option set | ||
|
||
In addition to, or instead of the API, users can specify which files to include via a set of options. | ||
|
||
```javascript | ||
export const options = { | ||
// ... | ||
|
||
include: [ | ||
'my/source/file.txt', | ||
'testdata', | ||
] | ||
} | ||
|
||
export default function () { | ||
// succeeds | ||
await open('my/source/file.txt'); | ||
|
||
// fails with 'resource csvs/data.csv not included by k6, ...' | ||
await open('csvs/data.csv') | ||
} | ||
``` | ||
|
||
**Key Points**: | ||
- The rules from the explicit API still apply: if a file isn't referenced in the options and is opened within the VU stage, an error occurs. | ||
- Attempting to open an un-referenced file within the init stage may not result in an error, ensuring backward compatibility. | ||
|
||
### Solution B: Awaiting Proposals | ||
|
||
Have a novel idea? Please share it with us in a dedicated commit :bow: | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I would argue we do not need a new API at all. There are two problems:
There is also the sligth twist that actually open("./someotherfile.txt") // will not error out for either the initial nor the VU with id `1`
if (__VU == 1) {
open("./somefile.txt") // will always error out as the initial VU did not open it.
} Again the first the tl;dr is that if we want to allow Adding API/configuration that adds files (again in the initial VU as discussed in #1771) is IMO a separate discussion. |
||
|
||
## Technical Decisions | ||
|
||
To be agreed upon and decided. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I evaluate it as a different proposal because they should be mutually exclusive. I don't see the reason why we should eventually implement both.