-
Notifications
You must be signed in to change notification settings - Fork 175
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
feat(starter): starter improvements to avoid port clashes #505
Conversation
…nt connection info.
VAX-1087 Prefix starter template container name with app name.
As per #489 et al, we currently have a clash of container names from multiple invocations of the starter template. One fix is to prefix the container name in the generated docker compose with the app name. Basically to stop Docker from reusing the same container / volume. |
…connecting to another app's Electric instance.
`docker run \ | ||
-e "DATABASE_URL=${db}" \ | ||
-e "LOGICAL_PUBLISHER_HOST=localhost" \ | ||
-e "AUTH_MODE=insecure" \ | ||
-p 5133:5133 \ | ||
-p ${electricPort}:5133 \ | ||
-p 5433:5433 ${electric}` |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do we still need to expose this port?
The compose file is not binding to 5433 so i'm assuming it is not necessary here either and we can remove it?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
5433 is the logical publisher port. I think it is being exposed here to support setup where people are running their own postgres on the host while Electric itself is run inside a Docker container.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we do need to expose it, because we need the PG to be able to connect to the electric. In this case, isn’t the script for when you’re running Electric without Postgres in the same compose?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh yes, i see. Perhaps i'll leave a comment to remember.
No the script for running only Electric is this separate file that executes docker run
because there are some differences (PG url can be passed as an argument, and 5433 is not exposed in compose file).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks great 👍
`docker run \ | ||
-e "DATABASE_URL=${db}" \ | ||
-e "LOGICAL_PUBLISHER_HOST=localhost" \ | ||
-e "AUTH_MODE=insecure" \ | ||
-p 5133:5133 \ | ||
-p ${electricPort}:5133 \ | ||
-p 5433:5433 ${electric}` |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
5433 is the logical publisher port. I think it is being exposed here to support setup where people are running their own postgres on the host while Electric itself is run inside a Docker container.
Btw: at least someone else than me should try this out to see that everything works fine. |
A few quick thoughts, (Aside: I feel strongly that all starters, examples and docs need to just use plain npm. Anyone that uses yarn or pnpm knows how to rewrite a command for it.) If we do change the starter to use Vite as discussed on Discord earlier, the code for setting the dev web server port is not needed. Vite will enumerate ports until it finds one free and print it. (still need logic for electric) I also feel that having the change port command rewrite the package.json and other committed files, isn't right. Different dev will want to use different ports. Local config should not be in committed files. Should we not have an optional not committed |
I had a similar opinion but we decided to stick with yarn everywhere a while ago.
Yep but should be a separate PR, so for now best to do this such that the starter works with several apps.
This has been a bit of a rabbit hole. We have discussed and iterated on several strategies this week. |
Just to chip in, I think @samwillis's points are very valid but also @kevin-dp is right that it's probably time to merge this and we can change to npm when we change to vite in subsequent PRs.
This does make sense to me. I was assuming we would persist in some kind of env file. Could that work rather than patching |
Notes from my testing:
|
@alco Output of |
I have found this package which is a lightweight wrapper of |
…about being accessed before initialization.
1: Moved to using shell-js. Output is colored now. 2: Thanks! Not sure how this went unnoticed. 3: done! 4: Ok change is very small so addressed it here also. 5: Indeed, the esbuild server runs on port 8000 by default. If it is already taken it will take another available port with preference for ports in the range 8000 to 8009. Not sure why this matters though? I made sure that the app's 6: This is actually good! It did detect the problem and wanted to raise it as an error but somehow the |
Yep had also seen it but was not sure about its stability and maturity though. |
This makes backend:start/backend:stop and backend:up/backend:down more similar to "docker compose start/stop" and "docker compose up/down", respectively.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Top notch! 🏆
I've pushed one commit as a suggestion, feel free to keep it or remove it.
…520) This is a follow-up to #505 and #502. I'm addressing a few different concerns in the same PR only because we don't have automated tests for the starter and redoing the same manual testing steps multiple times is error-prone. Here's a brief description of changes. ## Removed `shelljs-live` This reverts a8764b0. Turns out `shelljs-live` is not a drop-in replacement for `shelljs`. It only uses shelljs's config but implements a different API for executing a subprocess that only returns the status code to the caller. This broke our error handling in `startCompose.js` and `startElectric.js` that expects the return value to have the `stderr` field. I discovered this problem when I executed `yarn backend:up` instead of `yarn backend:start`: $ yarn backend:up yarn run v1.22.19 warning package.json: No license field warning ../../../package.json: No license field $ yarn backend:start --detach warning package.json: No license field warning ../../../package.json: No license field $ node ./backend/startCompose.js --detach [+] Running 5/5 ✔ Network app_default Created 0.1s ✔ Volume "app_pg_data" Created 0.0s ✔ Volume "app_electric_data" Created 0.0s ✔ Container app-postgres-1 Started 0.1s ✔ Container app-electric-1 Started 0.1s /home/alco/code/tmp/app/backend/startCompose.js:11 if (res.code !== 0 && res.stderr.includes('port is already allocated')) { ^ TypeError: Cannot read properties of undefined (reading 'includes') at Object.<anonymous> (/home/alco/code/tmp/app/backend/startCompose.js:11:34) at Module._compile (node:internal/modules/cjs/loader:1256:14) at Module._extensions..js (node:internal/modules/cjs/loader:1310:10) at Module.load (node:internal/modules/cjs/loader:1119:32) at Module._load (node:internal/modules/cjs/loader:960:12) at Function.executeUserEntryPoint [as runMain] (node:internal/modules/run_main:86:12) at node:internal/main/run_main_module:23:47 Node.js v18.18.0 error Command failed with exit code 1. info Visit https://yarnpkg.com/en/docs/cli/run for documentation about this command. error Command failed with exit code 1. info Visit https://yarnpkg.com/en/docs/cli/run for documentation about this command. It does mean we lose colorized output from `yarn backend:start`. But I believe it can be restored by getting rid of `shelljs` completely and using `cross-spawn` like `shelljs-live` does. ## Replaced ad-hoc migration runner with @databases/pg-migrations This package does everything we need: it can run multiple migrations and keeps track of already applied migrations. The way `@databases/pg-migrations` keeps track of applied migrations is a bit noisy: ``` [localhost] postgres:app=# \d List of relations Schema │ Name │ Type │ Owner ────────┼───────────────────────────────────────┼──────────┼────────── public │ atdatabases_migrations_applied │ table │ postgres public │ atdatabases_migrations_applied_id_seq │ sequence │ postgres public │ atdatabases_migrations_version │ table │ postgres public │ foo │ table │ postgres public │ items │ table │ postgres (5 rows) ``` But I don't think it's a problem for the starter template. Once we introduce integrations with backend frameworks, we'll replace this migrations runner with framework-specific ones. ## Reset terminal color back to default after printing an error message Our colorized error messages where missing the "reset" ANSI escape which was causing the output following the error message to also be colored, namely, the `Done` line printed by `yarn`.
This PR improves the starter to enable several (independent) Electric applications to run on the same machine and thus fixes #497 and #489. Also addressed VAX-1114. The changes are as follows: - Avoid volume clashes by putting project name on the app name - Avoid web server port clashes by supporting a custom port to be used and fix it everywhere in the template - Avoid Electric port clashes by supporting a custom port to be used and fix it everywhere in the template - Introduced 2 modes for the starter: fast mode and interactive mode - Fast mode: app name and ports (optional) are provided as command line arguments - Interactive mode: no arguments to the script, app name and ports are asked via prompts - Changed start to check that the chosen port for Electric is free. If not, prompt user if they want to change the port - Script to change the project’s configuration with other Electric and web server ports. Exposed as a new `ports:configure` command. - Changed `backend:start` to check for port clashes and if there is a port clash suggest to run `ports:configure`. - Changed `yarn start` and `client:generate` to check that the Electric port the app is configured to use is the app's own Electric service (e.g. catches problem where project 1 is running Electric on port 5133 and another project is accidentally configured to also connect to port 5133). - Modified build script to use forward requests to right esbuild server. This fixes a bug where if an esbuild server was already running, the new app would forward its requests to the esbuild server of the other app. tldr: it should now be possible to run several Electric applications. Port clashes should always be detected and reported with a suggestion to reconfigure the app with other ports. --------- Co-authored-by: Oleksii Sholik <[email protected]>
…520) This is a follow-up to #505 and #502. I'm addressing a few different concerns in the same PR only because we don't have automated tests for the starter and redoing the same manual testing steps multiple times is error-prone. Here's a brief description of changes. ## Removed `shelljs-live` This reverts a8764b0. Turns out `shelljs-live` is not a drop-in replacement for `shelljs`. It only uses shelljs's config but implements a different API for executing a subprocess that only returns the status code to the caller. This broke our error handling in `startCompose.js` and `startElectric.js` that expects the return value to have the `stderr` field. I discovered this problem when I executed `yarn backend:up` instead of `yarn backend:start`: $ yarn backend:up yarn run v1.22.19 warning package.json: No license field warning ../../../package.json: No license field $ yarn backend:start --detach warning package.json: No license field warning ../../../package.json: No license field $ node ./backend/startCompose.js --detach [+] Running 5/5 ✔ Network app_default Created 0.1s ✔ Volume "app_pg_data" Created 0.0s ✔ Volume "app_electric_data" Created 0.0s ✔ Container app-postgres-1 Started 0.1s ✔ Container app-electric-1 Started 0.1s /home/alco/code/tmp/app/backend/startCompose.js:11 if (res.code !== 0 && res.stderr.includes('port is already allocated')) { ^ TypeError: Cannot read properties of undefined (reading 'includes') at Object.<anonymous> (/home/alco/code/tmp/app/backend/startCompose.js:11:34) at Module._compile (node:internal/modules/cjs/loader:1256:14) at Module._extensions..js (node:internal/modules/cjs/loader:1310:10) at Module.load (node:internal/modules/cjs/loader:1119:32) at Module._load (node:internal/modules/cjs/loader:960:12) at Function.executeUserEntryPoint [as runMain] (node:internal/modules/run_main:86:12) at node:internal/main/run_main_module:23:47 Node.js v18.18.0 error Command failed with exit code 1. info Visit https://yarnpkg.com/en/docs/cli/run for documentation about this command. error Command failed with exit code 1. info Visit https://yarnpkg.com/en/docs/cli/run for documentation about this command. It does mean we lose colorized output from `yarn backend:start`. But I believe it can be restored by getting rid of `shelljs` completely and using `cross-spawn` like `shelljs-live` does. ## Replaced ad-hoc migration runner with @databases/pg-migrations This package does everything we need: it can run multiple migrations and keeps track of already applied migrations. The way `@databases/pg-migrations` keeps track of applied migrations is a bit noisy: ``` [localhost] postgres:app=# \d List of relations Schema │ Name │ Type │ Owner ────────┼───────────────────────────────────────┼──────────┼────────── public │ atdatabases_migrations_applied │ table │ postgres public │ atdatabases_migrations_applied_id_seq │ sequence │ postgres public │ atdatabases_migrations_version │ table │ postgres public │ foo │ table │ postgres public │ items │ table │ postgres (5 rows) ``` But I don't think it's a problem for the starter template. Once we introduce integrations with backend frameworks, we'll replace this migrations runner with framework-specific ones. ## Reset terminal color back to default after printing an error message Our colorized error messages where missing the "reset" ANSI escape which was causing the output following the error message to also be colored, namely, the `Done` line printed by `yarn`.
This PR improves the starter to enable several (independent) Electric applications to run on the same machine and thus fixes #497 and #489. Also addressed VAX-1114.
The changes are as follows:
ports:configure
command.backend:start
to check for port clashes and if there is a port clash suggest to runports:configure
.yarn start
andclient:generate
to check that the Electric port the app is configured to use is the app's own Electric service (e.g. catches problem where project 1 is running Electric on port 5133 and another project is accidentally configured to also connect to port 5133).tldr: it should now be possible to run several Electric applications. Port clashes should always be detected and reported with a suggestion to reconfigure the app with other ports.