any idea what am i getting this error? i'm using MySQL + drizzle and not using multi-statement queri
any idea what am i getting this error? i'm using MySQL + drizzle and not using multi-statement queries
Error: Hyperdrive does not currently support MySQL multi-statement queries";) is triggering the error ; -> | in the user agent when inserting and then reverse that from | -> ; when selecting. Not ideal but would unblock you for now.mysql2 but I've ran into memory leak problems just by running the SHOW TABLES example from the Hyperdrive tutorial (https://developers.cloudflare.com/hyperdrive/examples/connect-to-mysql/#mysql2)eventHandler with the example code and ran the it 25 times and noticed that the Connection objects are not collected by GC.SELECT on a table, the connection is closed and collected by GC.drizzle and had the same issue.
mysql2 without Hyperdrive? Or is this only visible when using both together?wrangler dev .output/server/index.mjs --assets .output/public --env development --remote˙SHOW TABLES; to just a SELECT * FROM my_table; it works as expected. Each request has a new Connection which is cleared up inwaitUntilnode and tested the same event handler. The GC cleared the Connection after each request, so no issues there.FinalizationRegistry and WeakRef to track the number of existing connections withconsole.log in wrangler tail and it seems like the GC never clears them after the request. I tried this also with the SELECT * FROM my_table query too which worked in dev and nothing.FinalizationRegistry created message in the log once during my initial request and after the connection count reaches around 250 to 300.I see FinalizationRegistry created message in the log once during my initial requestAlso just an FYI that this is expected. The Workers runtime creates one isolate per metal/server (*currently) and TCP connections are sticky so you'll be routed to the same metal for a good bit after you make the initial request. The global scope is only run once at isolate startup so you'll only see that message once.
.end(), but GC happens later.If I create a new drizzle instance with a huge schema for each Connection they are going to be kept in memory too.Sure, but the GC collector will be run more often if you're near the memory limit, so theoretically you'd see those connections being cleaned up more frequently if they were an issue. But I expect they're super lightweight anyway if the connection itself is closed.
SHOW TABLES query onlySHOW TABLES; query the max number of connection objects I see is around 360. If I multiply that by the 256 kB retained size I get around 92 MB. If I add the default heap size of the app which is around 36 MB I get 128 MB. Is this a coincidence?FinalizationRegistry but I think that's a platform limitation.workerd will run a GC sweep and clean things up.FinalizationRegistry created is probably because you just get routed to a different server and a new isolate is spun up.Socket within mysql2 PromiseConnection.connection.stream prevents it from being cleared.||mysql2mysql2SHOW TABLESSHOW TABLESeventHandlerConnectionConnectionSELECTwrangler dev .output/server/index.mjs --assets .output/public --env development --remoteSHOW TABLES;SHOW TABLES;SELECT * FROM my_table;nodeFinalizationRegistryFinalizationRegistryWeakRefSELECT * FROM my_tableFinalizationRegistry createdFinalizationRegistry created.end()SocketPromiseConnection.connection.stream Failed to connect to the provided database: TLS handshake failed
[SSLV3_ALERT_HANDSHAKE_FAILURE] [HANDSHAKE_FAILURE_ON_CLIENT_HELLO] [code: 2015]npx wrangler hyperdrive create testingdb --connection-string="postgres://postgres:pgpassword@iphere:5432/postgres"import { createConnection, type Connection } from "mysql2/promise";
const registry = new FinalizationRegistry((value) => {
console.log(`"${value}" was GC'd`);
});
console.log("FinalizationRegistry created");
const connections: WeakRef<Connection>[] = [];
export default defineEventHandler(async (event) => {
const { env } = event.context.cloudflare;
const connection = await createConnection({
host: env.HYPERDRIVE.host,
user: env.HYPERDRIVE.user,
password: env.HYPERDRIVE.password,
database: env.HYPERDRIVE.database,
port: env.HYPERDRIVE.port,
disableEval: true
});
try {
registry.register(connection, "MySQL2 connection");
connections.push(new WeakRef(connection));
await connection.query("SELECT * FROM `my_table`;");
event.waitUntil(connection.end());
return Response.json({
connections: connections.filter((ref) => ref.deref() !== undefined).length
});
} catch (e) {
console.error(e);
}
});event.waitUntil(
connection.end().then(() => {
(connection as any).connection.stream.destroy();
})
);