How to pass DB connections between stages?

Hello!
My idea is to open and iterate over the test data file and create a hashset of schema name and connection in set up stage so all VUs can use the same connections when needed as the intent is not to load test DB with these connections and to query for some decision making in the test.
The current restriction from the K6 site is it only allows passing data (JSON) between stages.
Is there any alternate option to this?

Hi there, welcome to the forum :slight_smile:

I’m assuming that you’re using the xk6-sql extension.

You’re right that it’s not possible to pass the DB connection from, say, setup() to the default function.

But why do you need to do that? When you create the connection in the init context/stage, all VUs would use that same connection, so you don’t need to pass it from setup().

There’s a minor quirk with how the init context is evaluated, since the code there is run at least twice, but at most 2 DB connections will be created regardless of how many VUs you run with. You can confirm this on Postgres with select count(*) from pg_stat_activity;.

Also see this this comment on a related issue for details.

I am confused over how many times init code executes. I see the solution from 973 says init code is executed MaxVus + 3 Times. Does that mean it would create SQL connections multiple times instead of twice you mentioned ?

Yes, the init code runs several times. No, only 2 DB connections would be created regardless of how many VUs you run the test with.

Please confirm this on your RDBMS, and let us know if that’s not the case.

I opened the connections per schema in init stage(Example: 2 connections for 2 schemas).

Inside default function, each VU would query choosing those open connection depending on their test data input. (Example: Max VUs:- 5, Out of 5, 4 VUs use same schema (so they suppose to share same connection) and rest 1 use another schema which uses another connection).

I observe there exists 1 pid per schema in pg_stat_activity at the beginning of the test. Later on, I see a separate pid for each VU as they start to query. Example: 4 pids trying to query same schema and 1 pid querying another schema.

I took another look at this, and you’re right, a connection is created for each VU. I reopened issue #25 so we can discuss potential solutions to this, but it’s unlikely this will be changed anytime soon, sorry. We currently don’t have the bandwidth to prioritize this, and as I mentioned here, I’m not sure if this is an issue.

2 Likes

BTW, as a workaround, you can open the connection inside the default() function, and only do it once for one VU:

import sql from 'k6/x/sql';
import exec from 'k6/execution';

let db;

export function teardown() {
  if (db) {
    db.close();
  }
}

export default function () {
  if (exec.vu.idInInstance == 1 && exec.vu.iterationInInstance == 0) {
    db = sql.open('postgres', 'postgres://...');
    db.exec('...');
  }

  // other VU code
}

You can also open it inside setup() and just return static data to all VUs. In both cases only one connection will be opened.

But if you want all VUs to be able to execute queries while sharing a single connection, then that’s not possible at the moment.

1 Like

Thanks for the workaround and exploring the potential solutions if at all needed.