-
Notifications
You must be signed in to change notification settings - Fork 1.8k
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
Support executing multiple dependent long-running tasks in parallel #1497
Comments
Reminds me of https://www.npmjs.com/package/wait-on |
I have a similar requirement. In my mono repo, I have an app in which I need to have multiple long-running processors started at the beginning. The order doesn’t really matter to me. I just have three long-running that at all need to start. I have a Vite build with the watch flag. Another process that needs to be run and a custom web server process. Each can start independently and in parallel. This can be achieved with NPM, Scripps and packages to enable parallel processes, but turborepo does not seem to support this via the pipelines. Turborepo will wait for the first process to complete, which never happens due to the long runing nature. |
That would be so cool. Imagine having multiple packages that all need to spin up (run |
Yeah, this would be useful, I sometimes want to run some integration tests and want to make sure the backend services are running before they start. |
Not to spam anymore in the thread, but for anyone looking for a nice alternative on top of turborepo would be to configure Visual Studio Code to have a special "task" to spin all processes in a shared terminal session. Here's my gist that spins two processes, useful for development workflow: https://gist.github.com/grabbou/1e19049ebc6127b269f4230bfaed5170 |
I've been looking for something like this for a while now. For me this addresses my docker compose problem. I don't like to keep my docker compose services running in the background:
Additionally things start to get messy when you're integrating a few OSS tools that each depend on multiple services. Imagine for example you're building some sort of webrtc app,
So what I've considered in the past is making small npm wrappers as "apps" for different associated services, since that's where they would be if they were run from source. |
In my case I want to run these in sequence and I can't find a proper way to do it currently as dev is a long-running task so
|
Hi guys I want to throw my protocol into the mix as a possible solution to this as well. It's a very simple way how task-runners like (turborepo, Nx, you name it) could talk to non-terminating watch-processes and tell them when to rebuild, and get the results of those builds. The idea is that we settle on one protocol, that then can be implemented by a lot of task runners and build tools. I'd really like to get your feedback on this! I hope to get the discussion started here |
the protocol looks a xstate state machine |
could you provide an example of how I would get started using your protocol for managing tsup --watch or tsc -w to restart some file-watching server when some other package has a file change? |
Usually this kind of management is required for (as bare minimum) TS lib + website, when TS lib in watch mode has to produce some output at least once, then website can pick up the output and keep watching it. See my old article, section
In any case build+watch approach for library may cause web to be built twice, first after build then after first output of watch, if website rebuild is looking at timestamps, not contents. |
If you have interdependent processes you want to run, I think just putting a "wait" task in front of them makes sense. Can use wait-on to wait for the port to open. This doesn't seem to require special support from turborepo to work. |
True, but it’s an extra tool and it looks awkward to have all such scripts like this: “wait-on blabla && real-thing”. It would be much more convenient if turbo config can have “waitOn” property for such tasks. Property can either call an NPM script that has to exit when condition is met, or a list of files/globs/URLs. It would be a nice advantage over NX which has same problem now. I've implemented the wait approach in my Next Redux Wrapper repo, it works, but does not look as sleek as Turbo configs can look: https://github.com/kirill-konshin/next-redux-wrapper/blob/3a14963a0c8a3ebf39baa331b6a467bbc6cb8ee5/packages/wrapper/package.json#L21 |
Hmm true. Not sure how far down the road of being a dev job runner turbo wants to go but it could be handy to have all that stuff integrated, especially if it could watch files and rebuild and restart the dev processes. |
I’d say that it could directly call wait-on package, by passing args. Or just call a certain NPM wait script like in my case. It should be just a gate to delay dev process start, that’s all what is needed. Actual watching and restarting is the dev processes’ own responsibility. This approach will clearly separate concerns and provide good looking user friendly tool. |
Interesting, what do you use to get your dev process to restart that isn't some clutter on the command line like wait-on
Regards,
Dobes
…On Feb 8, 2023, 5:50 PM -0800, Kirill Konshin ***@***.***>, wrote:
I’d say that it could directly call wait-on package, by passing args. Or just call a certain NPM wait script like in my case. It should be just a gate to delay dev process start, that’s all what is needed. Actual watching and restarting is the dev processes’ own responsibility. This approach will clearly separate concerns and provide good looking user friendly tool.
—
Reply to this email directly, view it on GitHub, or unsubscribe.
You are receiving this because you commented.Message ID: ***@***.***>
|
For example, Next.js dev restarts by itself when it detects changes in next.config.js, for other cases I use nodemon and so on. The idea is that dev script should be self-aware and know how to restart, that’s not turbo responsibility. But knowledge that dev script depends on something in order to run - is a turbo responsibility, since it manages all that kind of stuff. |
Hmm I'm not sure about that. Turbo knows about running things to build things, orchestrating dev servers seems a bit extra. Especially if you are already doing nodemon you might as well throw in wait-on in a similar way
…On Feb 8, 2023, 6:07 PM -0800, Kirill Konshin ***@***.***>, wrote:
For example, Next.js dev restarts by itself when it detects changes in next.config.js, for other cases I use nodemon and so on. The idea is that dev script should be self-aware and know how to restart, that’s not turbo responsibility.
But knowledge that dev script depends on something in order to run - is a turbo responsibility, since it manages all that kind of stuff.
—
Reply to this email directly, view it on GitHub, or unsubscribe.
You are receiving this because you commented.Message ID: ***@***.***>
|
Turbo manages dependencies between scripts. That’s the essence. Dev scripts can do whatever - restart, die, that’s lifecycle thing. Waiting for files to be able to launch dev script without error is a dependency problem. |
In my case wait scripts watch other packages files, that’s awkward :) because for all non-dev scripts turbo takes care of it. E.g. if package A depends on package B, build scripts of B will be scheduled to run before build script of A, turbo takes care of it. But this somehow does not apply on dev scripts. That’s what I mean by managing dependencies. |
I think if you are waiting for files to be built, you can do that with turbo as it is, if the files are generated by a process that exits. Are the files you are waiting for being generated by a process that does not exit ? |
Consider following: package A is a library, built with TSC, has So in order to run There are 2 tasks that can emit these files:
SolutionWe can introduce # package-a/package.json
{
"scripts": {
"build": "tsc ...",
"dev": "yarn build --watch",
"wait": "wait-on lib/index.js"
}
}
# package-b/package.json
{
"scripts": {
"dev": "next dev"
}
}
# turbo.json
{
"$schema": "https://turbo.build/schema.json",
"pipeline": {
"dev": {
"cache": false,
"persistent": true,
"dependsOn": ["^wait"]
},
"wait": {
"cache": false,
}
}
} If you want to be even more explicit, you can override {
"$schema": "https://turbo.build/schema.json",
"pipeline": {
"dev": {
"cache": false,
"persistent": true,
"dependsOn": ["^wait"] // <--- by default all dev tasks depend on wait
},
"A#dev": {
"cache": false,
"persistent": true,
"dependsOn": [] // <--- except for package A, dev has no dependencies
},
"wait": {
"cache": false
}
}
} In both cases
As expected. I believe this solution is worthy of being documented to clearly explain the proper way to run development tasks. P.S. Since we can define output for tasks that do exit, maybe we can also define it for those that don’t exit and treat it as permission to move on, which will allow non-exit tasks to be used as dependencies? Similar to waiting but more inline with turbo naming. |
@kirill-konshin Thanks for this! I was able to simplify it for my use case by setting {
"$schema": "https://turbo.build/schema.json",
"pipeline": {
"dev": {
"cache": false,
"persistent": true,
"dependsOn": ["^wait"]
},
"wait": {
"cache": false
}
}
} Then with that I didn't have to do anything special for "Package A" |
@justinwaite I'm glad my findings were useful for you. The only thing I'd like to highlight is that if |
I think I see what your saying. If Package B depends on A, and you try and run dev on B without running dev on A, then this would get stuck. Right? But if you're always running them together, then I don't see how this could get stuck waiting. |
@justinwaite if you configure it like in your example, all |
I think you might be mistaken here. I have it set to From the docs:
And I can confirm from my own repo that Package A does not run or wait on the Edit:
|
@justinwaite you're right, I overlooked the I have edited my original solution to be more concise. |
Wanted to also request such a feature. Without going into specifics we start up a little Apollo Server to modify/generate types from an external API. When I have to do that before my test script for example, my turbo run looks something like A solution like described in the original issue would be a huge improvement. |
I'd like to share, in case anyone comes here looking for simple answers for running persistent tasks in parallel, the This is what my
And the 3 persistent tasks run in parallel. Although they execute in that order, they are not dependent of each other. |
Thanks for all the disucssion here. In the interest of cleanup, I'm marking this as a duplicate of #986. |
@mehulkar Not really a duplicate imo. This issue was more of a functionality to allow dependsOn packages to run persistent. E.g. package-A requires to be transpiled for app-A, but we want to continue watching the changes in package-A while also running app-A after package-A transpiled once |
Yes, @Netail is right. Please reopen this issue! |
cc @chris-olszewski @NicholasLYang re-opened this, fyi |
I think if nothing changes in the output files for x seconds, it should give a start signal to the dependents to start the run command |
wireit listen to FYI my use case to this feature is for firebase projects. I need to populate the database (Firestore) after starting emulators. If i try to run the populate script just after emulators start, it does not work. I need to wait the services be ready. Currently, to detect when emulators are ready, i use wait-on coupled with a firebase functions 'ping' endpoint. Having a feature similar to wireit would help streamline my build setup |
Good one, for Typescript that would be "Watching for file changes." |
Trying to do same tried 2nd option (dependsOn). But it stuck on
because backend#dev have watch mode |
Describe the feature you'd like to request
In our monorepo, we have multiple services that to some degree depend on each other. For local development, we have to start a mock service first, then a second one, and then all others in any order.
For local development and testing, it would be great, to be able to start all these services or only one service and it's dependencies via turborepo in one step.
Describe the solution you'd like
It would be cool if turbo can be configured to not wait for a process to exit, but for some string or regexp to appear on stdout|stderr and put all processes into background until Turbo itself is terminated via Ctrl+C.
We could then just configure our
server
tasks like this:For dependencies, it would be needed to be able to specify an explicit package, as runtime dependencies do not necessarily match build time dependencies. I'm not sure if this is already possble, but at least it's not documented.
A leaf task should not need to configure a waiting condition, but having them for all background tasks would make it possible to output some informative message that all background tasks had a successful startup and now everything is up and running.
If a dependency is detected on a task that has
longRunning: true
, turbo could fail to run because of misconfiguration.Nice-to-have on top:
/hide mock-service#server
,/grep ERROR
Describe alternatives you've considered
Create a command line tool that starts a process, puts it in background and exits by itself when some message appears on stdout or stderr. I'm not sure if it's possible then to stop that background processes if the turbo command is interrupted via Ctrl+C.
The text was updated successfully, but these errors were encountered: