Is data from the main function shared between VUs?

I’m running some tests using scenarios that have multiple steps, which I’ve described in separate files (some steps are reused between scenarios). Now, I’ve observed a rather weird behaviour… some data seems to be getting overlapped between VUs.

Here’s my script function (some parts omitted for clarity)

export default function () {
    const currentScenario = data[scenario.name]

    const sessionData = {}
    for (const step of currentScenario.steps) {
        const { payload, endpoint } = step.preStep(step, sessionData)

        const payloadString = JSON.stringify(payload)

        const response = http.post(
            endpoint,
            payloadString
        )

        step.postStep(response, sessionData)

        sleep(step.delay)
    }
}

Now, the preStep function is defined on the step like so:

preStep: (step, sessionData) => {
        const payload = Object.assign({}, step.payload)

        const offerId = sessionData[OFFER_ID]

        if (!offerId) {
            failTest("Previous step did not properly parse response data - missing offerId")
        }

        payload.offerIds.push(offerId)

        return { payload, endpoint: step.endpoint }
    },

It should always add a single offerId in the array, but on my target system I’ve noted requests coming in with two separate ids - this being equal to the number of VUs. It might be a coincidence, but maybe I’m missing something about how the system is actually working.

VUs are basically independent JavaScript runtimes, they have their own copies of any global variables. And if you have multiple scenarios which are not overlapping (i.e. one scenario’s startTime is after another scenario’s total duration + gracefulStop), k6 will reuse VUs between them. See this recent issue for an example of how that can be used. However, that should only matter if you’re using global variables, which I don’t think you are :confused:

Can you post a full example script that we demonstrates this issue? Maybe using https://test.k6.io/ or https://test-api.k6.io/ or just console.log()? It’s difficult to understand where the problem is without having the full context…

Thanks, ned!

That was my assumption as well, that as long as I use local variables everything should be ok. Scenarios do overlap to some degree, so there is a chance for VUs to be reused, but I don’t think that’s the case right now.

The only thing that’s global is the scenario itself, but there I was making sure not work on the global copy of the payload through Object.assign({}, step.payload).

In any case, I’ll add a few more console logs and I’ll post a complete script once I can reproduce it.

Well, coming back to the office after a short vacation showed me the errors of my ways.

As I was saying in my previous message, only the scenarios are global and I make sure I’m not working on the global copy of the payload through that Object.assign({}, step.payload) - however, that doesn’t work as intended if one of the properties of step.payload is also an object or array, since it does not do a deep copy. That was my case.

Problem solved and a lesson for everyone using shared resources between VUs.