-
Notifications
You must be signed in to change notification settings - Fork 96
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
Is createPool actually async? #180
Comments
this is the second time there is an issue with typescript (https://jira.mariadb.org/browse/CONJS-171) that cannot normally occur. |
"typescript": "^4.1.3" The issue is reproducible with these versions, but I don't believe it's related to a specific TS version |
I actually dug into this a bit.
Everything is called synchronously. this.initialize = function () {
// ...snip
connectionCreationLoop(self, 0, timeoutEnd)
.then((conn) => {
... So |
Newbie here, assuming you do get this fixed, can you also do a TS example?
This doesn't error out, but it doesn't seem to solve the problem either. Desperate for some help. Thanks!
|
|
|
@whitebyte managed to resolve this? trying the same thing, and it is really annoying, that the createPool function, despite it being not asynchronous, calls an asynchronous function which can fail - now, the error could be possibly catched, but the success response is much harder this way. |
Unfortunately no |
Would updating the Type definition for A script with just these two lines will not terminate:
|
To be complete: the pool is not asynchronous => the pool object is immediately returned, but therefore the loading of connections into the pool is asynchronous. It was originally done this way for compatibility with mysql2 /mysql (with promise-mysql). There are 2 possible format for mariadb.createPool :
At first I thought it was a bad design and would prefer the Promise solution, but I changed my mind: what if there was a network problem just when the server started? then promise to return an error and you have to restart the app for the pool to work?! Since the latest version, the connector will let you know if it fails to create a connection, but the pool will work immediately after fixing this problem without any application restart. Don't hesitate to express your opinion! Another solution could also be to offer both solutions:
|
for @RevealedFrom import mariadb from "mariadb";
const pool = mariadb.createPool({ host: "localhost", database: "x", user: "x", password: "xxx"}); this is expected: pool is active. I thing node.js doesn't end when there is an active timer, and pool set an interval for validating existing connection. |
Why would one want a pool that can't provide a connection? IMO a pool without at least one successfully established connection has no reason to exist. Also it makes a false impression that the DB is connected and operational, which is not true in this case |
@rusher Please open the issue tracker over at https://github.com/mariadb-corporation/mariadb-connector-python ; Hosting issues on Jira is a high friction way to ruin adoption; you're just going to get one-off accounts asking one-off questions, with no real collaboration or discussion. Tangentially related, coming from the Python library, also concerned about this as there's no usage of Doesn't help the Django adoption story because Django is moving to full async for 5.0.. and all the other popular ASGI frameworks (FastAPI, Starlette, Sanic) |
@gnat Question are usually ask and answer on stackoverflow, so i don't think that's a big deal. I've not the priviledge to do that. What you indicate concerns Python driver and is clearly some new feature, and i won't be the right guy for that. So please describe you problem here : https://jira.mariadb.org/projects/CONPY/issues/CONPY-197?filter=allopenissues . Python database spec are synchronous. I'm not completly sure but i think green thread are implemented in python. If that's the case, using synchronous spec + green thread would probably be easier and better than an async implementation. anyway please create your idea and problem. |
As much as I also find it interesting to think what the python ecosystem would look like to have settled on green threads, the built-in MariaDB support in Django, etc. is just going to get stuck behind an async MySQL driver if the team is going to keep this kind of friction, because no new project is going to commit to using a blocking connector when the whole rest of the stack is async. |
I don't see any problem with the creation of the pool being synchronise. But everything about the connections has to be asynchronise. The pool should get created and destroyed once. No big deal. But the connection will be gotten and released thousands of times. |
These errors turned out to be the result of host misconfiguration. |
Is there any update on this? I wouldn't mind working on it by myself and opening a PR, but what's the consensus? @rusher |
There are other problems in pool bigger than this and I don't see the benefit of converting the create process of the pool that happens one time at startup to async. There is no way to force a reset of the connection as you are returning it to the pool and the prepare object can linger. I already have a ticket in for the prepare object, but would love to have a .release(true) to force a hard reset of the connection as it is being returned to the pool. |
@whitebyte Because the database might not be ready to accept connections when the app starts, but it will be ready to accept connections later (within a few seconds). This is a common problem when using Docker: the web app starts immediately, but the database needs longer time to start, so the web app can't establish an connection to it immediately. Also, that you manage to connect to the database when the pool is created is no guarantee that you will be able to connect to it later (maybe the DB crashes after 1 minute), so you always need to deal with DB connection errors every time you use it anyway, so your reasoning a pool without at least one successfully established connection has no resaon to exist I simply disagree with; I don't want my web app to crash just because the database has crashed; my web app should continue to function on its own (i.e. show internal server error message), and when the database has been fixed and restarted, the pool should automatically established a new connection to it the next time the web app requests a connection from it. So, in my opinion, a pool with no functional connections is useful. It's also much easier to implement and learn how to use the package if the pool is just a pool, and doesn't try use connections on its own. And if you need to test if the connection to the DB works upon pool creation, you can still very easily do that yourself by obtaining a connection from the pool after pool creation.
That is only true if you have the belief that the pool is responsible for connecting to the database upon creation. Where have you got that belief from? And, you can also look at this the other way: by giving an error when the pool can't connect upon creation, that can give the false impression that at least one connection in the pool will always work if you don't get the error (and that is wrong, since the database can crash on its own after a while). |
@PeppeL-G I actually don't have a strong opinion on this one. My point is that the current behavior is misleading. Either sync or async, but pick one. Currently |
Boy, am I stupid or what. I came here looking for clues to a weird behavior I'm experiencing, and I got stuck on your question In short, the problem can be summarized as this (see the comments, the code below is all code in the program): const mariadb = require('mariadb')
// 1. I have no Maria DB database up and running, but the
// pool is created without problem, as expected.
const pool = mariadb.createPool({
host: "localhost",
port: 3306,
user: "root",
password: "abc123",
database: "abc",
})
// 2. The program continues to run.
I'm guessing the Promise version of the code was written before Node.js version 15, when unhandled promise rejections were simply silently ignored, but from version 15 and on they instead stop the process, so we can become aware of that something is wrong. So, to summarize (IMO):
So a fix to (3) in the list above would make me happy :) |
ouch, that wasn't clear for me either.
As a workaround, you can just add : pool.on('error', () => {}); this will be corrected in 3.1.1 |
Hi, an update on index.d.ts to add on(ev: 'error', callback: (err: Error) => void): Pool; Could be good to let the typescript developer catch error too. |
Hello folks, is this issue already resolved in the latest (3.2.3)? Earlier any error from the pool was thrown async and not handled within the client code. After the upgrade, it no longer throws an error and seems to be captured and logged to stdout. Which I assume is handled here? If yes, just curious to know why there can be multiple errors when trying to establish connection such that they are to be captured and handled only internally within the client? For example, if I give an incorrect port to establish a connection I first get an error which I can handle:
And then after some time, I get this logged separately, which I'm not handling (in the earlier version this used to crash the node server):
|
Consider the following code:
If the DB is unavailable (e.g. because of a network failure) I expect to see
DB init error
in console. In practice, I see it AND something like this:I took a brief look at the connector code and it seems
createPool
usesmariadb-connector-nodejs/lib/pool-base.js
Line 138 in bc9f6c7
The text was updated successfully, but these errors were encountered: