Skip to content

timers: refactor how setTimeout and co are made available globally #4563

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

Merged
merged 2 commits into from
Feb 20, 2025

Conversation

mstoykov
Copy link
Contributor

What?

This makes the setTimeout and co. timers package into a not js module package. The current one is tc55, the newly made common API to make technical committee alongside tc39. This might be changed later.

This also allows us to make them globally available without importing js module "k6/timers" allowing us to fix #3814.

Why?

Reporting k6/timers as always used is not good.

Also, setTimeout and co shouldn't; be dependent on being in a module.

Likely more changes will happen in the future and tc55 will either grow or disappear as a package.

breaking change is set only because previously in modulestest k6/timers was automatically made available - I doubt anyone used that, but it is a thing.

Checklist

  • I have performed a self-review of my code.
  • I have added tests for my changes.
  • I have run linter locally (make lint) and all checks pass.
  • I have run tests locally (make tests) and all tests pass.
  • I have commented on my code, particularly in hard-to-understand areas.

Related PR(s)/Issue(s)

This makes the setTimeout and co. timers package into a not js module
package. The current one is tc55, the newly made common API to make
technical committee alongside tc39. This might be changed later.

This also allows us to make them globally available without importing js
module "k6/timers" allowing us to fix #3814.
@mstoykov mstoykov added the breaking change for PRs that need to be mentioned in the breaking changes section of the release notes label Feb 19, 2025
@mstoykov mstoykov added this to the v1.0.0-rc1 milestone Feb 19, 2025
@mstoykov mstoykov requested a review from a team as a code owner February 19, 2025 14:49
@mstoykov mstoykov requested review from inancgumus and oleiade and removed request for a team February 19, 2025 14:49
@olegbespalov olegbespalov self-requested a review February 19, 2025 17:30
inancgumus
inancgumus previously approved these changes Feb 20, 2025
Copy link
Contributor

@inancgumus inancgumus left a comment

Choose a reason for hiding this comment

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

LGTM 👍 With mild suggestions.


func (e *timers) setupTaskTimeout() {
e.queue.stopTimer()
delay := -time.Since(e.timers[e.queue.first().id])
Copy link
Contributor

Choose a reason for hiding this comment

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

Wouldn't this panic if first() returns nil?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

this is always ran after either a thing has been added or after it was checked that it isn't empty, so there is no way for this to happen.

Co-authored-by: İnanç Gümüş <inanc.gumus@grafana.com>
olegbespalov
olegbespalov previously approved these changes Feb 20, 2025
Copy link
Contributor

@olegbespalov olegbespalov left a comment

Choose a reason for hiding this comment

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

In my opinion, the current timers implementation still hardly coupled to the k6's modules and can't be really named as the tc55 thing, so it's just increasing of the complexity.

But if you had a plan how it should evolve, I'm fine with it

@mstoykov
Copy link
Contributor Author

How is it coupled ? Do you want me to not have modules.VU in it at all as well? I can refactor it more to not care about anything from k6 as well, it just doesn't make that much sense until we put more work into moving stuff such as the event loop outside of k6

@olegbespalov
Copy link
Contributor

How is it coupled ? Do you want me to not have modules.VU in it at all as well?

Yes, that's what I meant. Like I said, if you have a plan, it's good, for now. I don't want changes right now. Frankly, I mostly care about wrapping the work on the #4278 which I'm going to align, once this will be merged

Copy link
Contributor

@oleiade oleiade left a comment

Choose a reason for hiding this comment

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

LGTM as-is 👍🏻 🚀

Absolutely non-blocking comment from me—just sharing my perspective (feel free to proceed as-is). The only real downside I see here is that the way the timers module integrates feels somewhat implicit. Specifically, it relies on certain functions being injected into the global object as a side effect of calling a function from the tc55/timers module in the bundle code.

It took me about five minutes to connect the dots in the context of this PR, but I’m not confident it will be as easy six months from now. If I were to revisit this code in isolation—outside the context of this PR—I’d likely be a bit confused about the expectation that the timers functions should be set in the global object. Tracing back where and how this setup happens would take some effort.

I don’t have a concrete alternative in mind, just an intuition: since we’ll likely be adding more to the global object over time, maybe it would be worth having a single, explicit place in the code dedicated to managing its state? Something like a centralized abstraction or entry point where all GlobalObject().Set calls related to module function injection live, making it clear where to look.

Once again, I'm happy to merge as-is, this is really me dumping my brain 🧠 🙇🏻

@mstoykov
Copy link
Contributor Author

modules.VU isn't really about modules to be honest, but removing that means providing all the things we use from it to the timers implementation, which currently means context, logger, runtime and a way to register the callback.

Context gets reset every iteration, so for that we either need a function or we need to make new timers every iteration.

Arguably I can just make a different interface that only has the things timers cares about put it in timers.

I do not currently think that this iwll benefit us much unless we also move event loop to not be k6 dependant and start making a much bigger separation between this components and k6 and make them only depend on Sobek.

IIRC this has been shelved for later.

tl;dr modules.VU is just a way to get stuff from the VU, it has very little to do with the modules. It is what the modules need so it is defined as n interface there.

@mstoykov
Copy link
Contributor Author

I wrote the above comment before I saw the approvals or your comment @oleiade .

Specifically, it relies on certain functions being injected into the global object as a side effect of calling a functio

I did originally set them globally from the bundle and modulestest and had to have SetTimeout and co. exported, but :

  1. it has code repeated - arguably as I've mentioned in other places, modulestest and bundle should share a lot more code. But this will be even bigger problem IMO
  2. timers don't really make much of a sense if they are not set globally - that is practically the idea, so it being part of the package made sense. I specifically also chose a function name that made it more obvious this is happening. But to be honest bundle in particular does so many things setuping stuff, that I too constantly wonder why is this done here, and hten I remember the interconnections, but a lot of the stuff depend on each other.

I will try to get through bundle and maybe reorder stuff and see if I can make most of them in setGlobal and move setInitGlobals there as well.

@mstoykov mstoykov merged commit c5fb807 into master Feb 20, 2025
29 checks passed
@mstoykov mstoykov deleted the timersReporting branch February 20, 2025 10:20
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
breaking change for PRs that need to be mentioned in the breaking changes section of the release notes
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Fix k6/timers always being reported as used
4 participants