Skip to content

feat: allow custom pools#4417

Merged
sheremet-va merged 15 commits intovitest-dev:mainfrom
sheremet-va:feat/custom-pool
Nov 18, 2023
Merged

feat: allow custom pools#4417
sheremet-va merged 15 commits intovitest-dev:mainfrom
sheremet-va:feat/custom-pool

Conversation

@sheremet-va
Copy link
Member

@sheremet-va sheremet-va commented Oct 31, 2023

Description

This PR adds a possibility to specify a filepath or package name in pool option. Vitest expects that specified module will have a default export which is a function that accepts Vitest as its parameter. This function should return on object that satisfies this interface:

import { ProcessPool, WorkspaceProject } from 'vitest/node'

export interface ProcessPool {
  name: string
  runTests: (files: [project: WorkspaceProject, testFile: string][], invalidates?: string[]) => Promise<void>
  close?: () => Promise<void>
}

runTests is called when user runs vitest command and then each time watch mode is triggered. This API is primarily designed to be used by library authors because it requires deep knowledge of how Vitest works internally. More about this option can be found in documentation.

Please don't delete this checklist! Before submitting the PR, please make sure you do the following:

  • It's really useful if your PR references an issue where it is discussed ahead of time. If the feature is substantial or introduces breaking changes without a discussion, PR might be closed.
  • Ideally, include a test that fails without this PR but passes with it.
  • Please, don't make changes to pnpm-lock.yaml unless you introduce a new test example.

Tests

  • Run the tests with pnpm test:ci.

Documentation

  • If you introduce new functionality, document it. You can run documentation with pnpm run docs command.

Changesets

  • Changes in changelog are generated from PR name. Please, make sure that it explains your changes in an understandable manner. Please, prefix changeset messages with feat:, fix:, perf:, docs:, or chore:.

@bolt-new-by-stackblitz
Copy link

Review PR in StackBlitz Codeflow Run & review this pull request in StackBlitz Codeflow.

@netlify
Copy link

netlify bot commented Oct 31, 2023

Deploy Preview for fastidious-cascaron-4ded94 canceled.

Name Link
🔨 Latest commit 1ae44c9
🔍 Latest deploy log https://app.netlify.com/sites/fastidious-cascaron-4ded94/deploys/65588376049e19000801d813

@sheremet-va sheremet-va marked this pull request as ready for review November 2, 2023 11:50
@sheremet-va
Copy link
Member Author

Note: this PR just opens up a possibility to do this, we still need to improve how to run tests in the new runtime - like exposing the logic of runtime/{worker,child,vmThreads}.ts. But I don't think we can do this without exposing this option first.

Copy link
Member

@AriPerkkio AriPerkkio left a comment

Choose a reason for hiding this comment

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

Tested a custom pool in locally linked project and seems to work nice.


## API

The file specified in `pool` option should export a function (can be async) that accepts `Vitest` interface as its first option. This functions needs to return an object matching `ProcessPool` interface:
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
The file specified in `pool` option should export a function (can be async) that accepts `Vitest` interface as its first option. This functions needs to return an object matching `ProcessPool` interface:
The file specified in `pool` option should export a function (can be async) that accepts `Vitest` interface as its first option. This function needs to return an object matching `ProcessPool` interface:


Vitest will wait until `runTests` is executed before finishing a run (i.e., it will emit [`onFinished`](/guide/reporters) only after `runTests` is resolved).

If you are using a custom pool, you will have to provide test files and their results yourself - you can reference [`vitest.state`](https://github.com/vitest-dev/vitest/blob/feat/custom-pool/packages/vitest/src/node/state.ts) for that (mose important are `collectFiles` and `updateTasks`). Vitest uses `startTests` function from `@vitest/runner` package to do that.
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
If you are using a custom pool, you will have to provide test files and their results yourself - you can reference [`vitest.state`](https://github.com/vitest-dev/vitest/blob/feat/custom-pool/packages/vitest/src/node/state.ts) for that (mose important are `collectFiles` and `updateTasks`). Vitest uses `startTests` function from `@vitest/runner` package to do that.
If you are using a custom pool, you will have to provide test files and their results yourself - you can reference [`vitest.state`](https://github.com/vitest-dev/vitest/blob/feat/custom-pool/packages/vitest/src/node/state.ts) for that (most important are `collectFiles` and `updateTasks`). Vitest uses `startTests` function from `@vitest/runner` package to do that.

And the URL should eventually point at main instead of work branch.

return sequencer.sort(specs)
}

await Promise.all(Object.entries(filesByPool).map(async (entry) => {
Copy link
Member

Choose a reason for hiding this comment

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

This issue seems to be in main branch too, but all pools are executed parallel here, right?

If user has threads pool and vmThreads pools set, and each are using default max-threads, the execution will spawn too many workers at the same time.

Copy link
Member Author

Choose a reason for hiding this comment

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

Yes, this is how it works. That's why I wanted agnostic implementation of tinypool.

Copy link
Member

Choose a reason for hiding this comment

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

Tinypool can run worker_threads and child_process parallel.

https://github.com/tinylibs/tinypool/blob/999778ed8acccf18303760558f807f0e208c8b3b/test/runtime.test.ts#L151-L170

It's possible to push all threads tasks in the pool, then wait for queue to be empty (remaining tasks are running, nothing in queue), and then change the runtime and push more tasks in the queue to wait for previous ones to finish. Like here is done:

// Once all tasks are running or finished, recycle worker for isolation.
// On-going workers will run in the previous environment.
await new Promise<void>(resolve => pool.queueSize === 0 ? resolve() : pool.once('drain', resolve))
await pool.recycleWorkers()

Copy link
Member Author

@sheremet-va sheremet-va Nov 2, 2023

Choose a reason for hiding this comment

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

Ideally, I would like an API that we can expose to reuse the same Tinypool instance in different pools:

function createThreadsPool(ctx, { pool }) {
  function runTests(testFile) {
    const context = { config: ctx.config, files: [testFile], executeFile: resolve('./dist/worker.js') }
    await pool.run(context, { runtime: 'worker_threads', name: 'run' })
  }
}

Maybe instead of having separate worker.js/child.js/vmWorker.js files we have a single file where inside of a context we pass down information on how we want to run it? So, we don't need to change filename option in Tinypool. This should also make it easier for external pools to reuse it

Copy link
Member

@AriPerkkio AriPerkkio Nov 2, 2023

Choose a reason for hiding this comment

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

I like the idea. From Tinypool's side I think that kind of API should already be possible - some kind of wrappers around it might be needed though.
There's also some need for refactoring in threads and forks pools to reduce code duplication. While doing that it might be good to look into this kind of API. But all this can be left out of this PR as it's not relevant to these changes.

@sheremet-va sheremet-va merged commit a3fd5f8 into vitest-dev:main Nov 18, 2023
@sheremet-va sheremet-va deleted the feat/custom-pool branch November 18, 2023 09:42
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants