My project is a medium sized Electron app, and I use promise-mysql to reach the back end. While there are several good examples covering how to connect to MySQL in Electron, none I have found are using a connection pool.
The database server I am using is very small (a NUC), and so I wish to use a pool of connections to keep a lid on things. It seems to me that the natural place to instantiate the connection pool would be in Electron's main.js file just before the app launches the window. This is so that all the renderers can get to it. To get and release connections I wrote ipc handlers like this:
// MySQL setup
const ipc = require('electron').ipcMain;
var mysql = require('promise-mysql');
var mysqlParms = require("./mysqlConfig.json");
let cfMySQLPool = mysql.createPool({
host: mysqlParms.host,
user: mysqlParms.user,
password: mysqlParms.password,
database: mysqlParms.database,
multipleStatements: true,
connectionLimit: 4 // NUC is a small box
});
ipc.on('getCFConnection', function (event, arg) {
event.sender.send('cfConnection', cfMySQLPool.getConnection()); // send a connection Promise
})
ipc.on('releaseCFConnection', function (event, cfConnection) {
cfMySQLPool.releaseConnection(cfConnection); // release the connection from the pool
})
However, this fails. The renderers do not receive the Promise from getConnection(), and I think I found out why. When event.sender.send (which is webcontents.send) passes the argument, the docs state:
"Arguments will be serialized in JSON internally and hence no functions or prototype chain will be included."
So it appears the ability to .then() the getConnection promise in the renderer is stripped away by JSON serialization.
Does anyone have any solutions to offer on implementing the promise-mysql connection pool in Electron so that any renderer can call getConnection / releaseConnection on it? Thank you.
Although this IS an answer to the question "How to implement...", I surely wish and hope that my answer doesn't end up being the accepted one. I will hold out for a while to see if one of you brainiacs come up with something better.
But one way to implement the promise-mysql connection pool is to simply "give in" and not only have the Electron's main.js instantiate the pool, but have main.js run all your MySQL process Promises too.
On the renderer side, all that is needed is an IPCRenderer request to kick off the process. Main.js then responds by running the Promise chain itself. Here is a simple ping:
// process 1: ping MySQL server to see if its up; oParms not used
ipc.on('_mp1', function (event, oParms) {
let localConn = null;
cfMySQLPool.getConnection().then((conn) => {
localConn = conn;
localConn.ping((err) => {
cfMySQLPool.releaseConnection(localConn);
if (err) {
event.sender.send("mp1_", {error: null, result: false});
} else {
event.sender.send("mp1_", {error: null, result: true});
}
})
.catch((err) => {
event.sender.send("mp1_", {error: err, result: null});
});
});
});
The results from the query() method, whose return is simply an array of resulting field data, is not impacted by Electron's internal JSON serialization; there are no functions / prototype to strip away. Releasing the connection back to the pool and sending the data to the requesting renderer is easy and completes the process.
So, in hindsight, this problem is actually less about promise-mysql really, and more about why Electron cannot pass "rich" objects with functions intact to renderers via IPC. The resulting work-around implementation makes for a LOT of unnecessary IPC handling.
Unless someone sees things differently...?