Skip to content
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

Pass and respect a Context when initializing VUs #2800

Merged
merged 7 commits into from
Jan 11, 2023
Merged

Conversation

na--
Copy link
Member

@na-- na-- commented Dec 5, 2022

This closes #2790. It is not very urgent, it doesn't need to be released in v0.42.0, instead it is meant to be merged some time early in the v0.43.0 cycle.

Most of the LoC changes are just boilerplate churn, mostly test and API signature adjustments. They have been grouped together into the first 2 commits of the PR and should contain no functional or test changes.

The important changes are focused in the next 2 commits, which should be the reviewed carefully. I may add some more tests there, though I am not sure what they should be 🤔 If anyone has any ideas, please share 🙏

@na-- na-- added this to the v0.43.0 milestone Dec 5, 2022
@na-- na-- requested review from mstoykov and imiric December 5, 2022 12:33
@codecov-commenter
Copy link

codecov-commenter commented Dec 5, 2022

Codecov Report

Merging #2800 (b641de7) into master (8418147) will decrease coverage by 0.18%.
The diff coverage is 100.00%.

❗ Current head b641de7 differs from pull request most recent head 9c9e35f. Consider uploading reports for the commit 9c9e35f to get more accurate results

@@            Coverage Diff             @@
##           master    #2800      +/-   ##
==========================================
- Coverage   76.04%   75.85%   -0.19%     
==========================================
  Files         213      211       -2     
  Lines       16554    16577      +23     
==========================================
- Hits        12588    12575      -13     
- Misses       3195     3223      +28     
- Partials      771      779       +8     
Flag Coverage Δ
ubuntu ?
windows 75.85% <100.00%> (+0.09%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

Impacted Files Coverage Δ
js/initcontext.go 88.18% <ø> (ø)
core/local/local.go 89.70% <100.00%> (-0.45%) ⬇️
js/bundle.go 90.62% <100.00%> (+0.62%) ⬆️
js/runner.go 85.26% <100.00%> (+0.07%) ⬆️
lib/testutils/minirunner/minirunner.go 82.43% <100.00%> (+0.24%) ⬆️
lib/netext/tls.go 27.08% <0.00%> (-22.92%) ⬇️
api/v1/metric.go 63.63% <0.00%> (-22.73%) ⬇️
loader/readsource.go 75.86% <0.00%> (-10.35%) ⬇️
metrics/value_type.go 62.50% <0.00%> (-6.25%) ⬇️
lib/executor/vu_handle.go 92.52% <0.00%> (-5.61%) ⬇️
... and 13 more

Help us with your feedback. Take ten seconds to tell us how you rate us. Have a feature suggestion? Share it here.

@na-- na-- force-pushed the fix-run-error-wait branch 2 times, most recently from cea7276 to a8ff4a1 Compare December 5, 2022 15:41
Base automatically changed from fix-run-error-wait to master December 5, 2022 16:26
@na-- na-- force-pushed the init-vus-with-context branch 2 times, most recently from 8398f3f to 11564b3 Compare December 5, 2022 21:45
@na-- na-- changed the base branch from master to prevent-real-network-requests-in-tests December 5, 2022 23:09
Base automatically changed from prevent-real-network-requests-in-tests to master December 6, 2022 08:29
@na-- na-- changed the base branch from master to master-next December 7, 2022 09:21
@na-- na-- requested a review from codebien December 9, 2022 11:19
Copy link
Contributor

@imiric imiric left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM from a first look, will make another pass later.

Nice job splitting it into atomic commits, makes reviewing much easier 👍

As for additional tests, and maybe I'm missing it, but I think there should be a test replicating the user pressing ^C during VU initialization. I see a couple of tests sending os.Interrupt, but it happens while the test is running. The tests aborted in init should cover the same code paths, but receiving SIGINT should trigger it as well.

js/bundle.go Outdated Show resolved Hide resolved
mstoykov
mstoykov previously approved these changes Dec 13, 2022
@na--
Copy link
Member Author

na-- commented Dec 14, 2022

@imiric, I was super surprised that a test didn't exist, and when I started to add it, I realized why I hadn't done it originally 😅

This PR makes it so VU initializations are going to be gracefully aborted with Ctrl+C, true. However, k6 won't return the right exit code or send the run_status value yet... 😞 IIRC, this is when I started writing #2804 😅

Still, I decided to go ahead and add a test anyway, even if it needs to check the current values of these... I just added a couple of TODOs, so we know the test doesn't verify the desired behavior, but the current one.

So, I cherry-picked one commit (d5124d1) from #2807, to simplify the integration tests that use Ctrl+C or REST API to stop k6, and then added ed39495 with the actual test to check what happens when an interrupt signal is given while VUs are initializing.

Copy link
Contributor

@codebien codebien left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for doing it, I saw very nice improvements. 🙇 I was reviewing when you force-pushed so something could be lost on my side.

js/initcontext.go Outdated Show resolved Hide resolved
js/runner.go Outdated Show resolved Hide resolved
Comment on lines +339 to +347
// TODO: make something cleaner for interrupting scripts, and more unified
// (e.g. as a part of the event loop or RunWithPanicCatching()?
initCtxDone := init.moduleVUImpl.ctx.Done()
initDone := make(chan struct{})
watchDone := make(chan struct{})
go func() {
select {
case <-initCtxDone:
rt.Interrupt(init.moduleVUImpl.ctx.Err())
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I need to check what the logic is in the other cases (not init) but if it is the same maybe could we delegate this listener directly in moduleVUImpl? 🤔

If the logic is different, we should use this opportunity to wrap the error so we know it is generated by the init process.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unfortunately it wasn't straightforward to unify this init interrupt logic with the rest of the test abort logic during test execution 😞 At least I didn't see how to do that without a much, much bigger refactoring of the whole js/ package... 😞

So I chose to make only minor improvements in this PR (see the Simplify the js/Bundle.instantiate() API commit) and leave the rest for a future PR (see the TODO in the code snippet you've selected).

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If the logic is different, we should use this opportunity to wrap the error so we know it is generated by the init process.

What about this, is it doable?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm not sure what additional information we can add here, as the rest of the code is now 🤔 I think it will be much easier to fix this after we have the NewTestRunContext() in a "higher" place, i.e. after #2813 🤔

@na-- na-- requested a review from codebien December 14, 2022 12:16
js/initcontext.go Outdated Show resolved Hide resolved
js/runner.go Outdated Show resolved Hide resolved
Comment on lines +339 to +347
// TODO: make something cleaner for interrupting scripts, and more unified
// (e.g. as a part of the event loop or RunWithPanicCatching()?
initCtxDone := init.moduleVUImpl.ctx.Done()
initDone := make(chan struct{})
watchDone := make(chan struct{})
go func() {
select {
case <-initCtxDone:
rt.Interrupt(init.moduleVUImpl.ctx.Err())
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If the logic is different, we should use this opportunity to wrap the error so we know it is generated by the init process.

What about this, is it doable?

imiric
imiric previously approved these changes Dec 14, 2022
Copy link
Contributor

@imiric imiric left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM 👍

Just left a minor comment about test helpers.

})
}

func asyncWaitForStdoutAndStopTestFromRESTAPI(
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This function is only called from TestAbortedByUserWithRestAPI, and just wraps another helper function. So I would inline the asyncWaitForStdoutAndRun() call, and remove this.

asyncWaitForStdoutAndRun() is also called with the same arguments, except for the callback func. So I would drop the unneded arguments, and add them once they're needed.

In general, abstractions add a layer of indirection that complicates code comprehension, so I wouldn't use them so liberally, and would prefer even some duplication between tests. Or, if tests really are similar, turn them into table tests and avoid the helper functions.

Copy link
Member Author

@na-- na-- Jan 10, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree and I was about to fix this, but I think the "fix" here is to just add more tests that abort the test run via the k6 REST API 😅 See #2804, we need more tests about this behavior... 😞

In #2815 or soon after it, we should be able to nicely abort the test with the REST even during VU init or setup(), so I'd prefer to keep this helper method here and add more tests that use it in that PR.

With some extra work, this will allow us to gracefully interrupt VUs in the middle of their initialization.
As I've mentioned in the code comments, this test doesn't test the eventually desired behavior, it tests the currently expected behavior as it is. The current behavior is still much better than the behavior before this PR, where the VU init was interrupted without any handling and graceful stops. However, the fix to actually abort k6 with the correct exit code and run_status will be in another PR.
Copy link
Contributor

@codebien codebien left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@na-- na-- merged commit e9d390d into master Jan 11, 2023
@na-- na-- deleted the init-vus-with-context branch January 11, 2023 13:29
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Propagate the real context when initializing VUs
5 participants