Skip to content
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

question: .function API with user defiend async function/Promise ? #319

Closed
yw662 opened this issue Nov 2, 2019 · 6 comments
Closed

question: .function API with user defiend async function/Promise ? #319

yw662 opened this issue Nov 2, 2019 · 6 comments

Comments

@yw662
Copy link

yw662 commented Nov 2, 2019

Can I make sqlite3 work with user defined async function ?
sth. like

db.function('foo', () => new Promise((s,j)=>setTimeout(s, 1000, 1)));
db.prepare('select foo();').get();

This will result in TypeError: User-defined function foo() returned an invalid value for now. Any work around for this ?

@yw662
Copy link
Author

yw662 commented Nov 2, 2019

I realised this is hard in better-sqlite3, since it uses sync API. However I still want to see some ideas on this.

@JoshuaWise
Copy link
Member

You should never keep SQLite3 transactions open across event loop ticks in Node.js. SQLite3 serializes all statements/transactions. This means, if you try to run an asynchronous function within an SQL statement, you'll block all other statements/transactions across your entire program. better-sqlite3 doesn't support it, and it never will, because it's a very bad idea.

Instead, you should gather all information required for your transaction (reading files, waiting on sockets, etc.) BEFORE you start the transaction. Then, when everything is ready, run the transaction synchronously, within a single event loop tick.

@Prinzhorn
Copy link
Contributor

We might get to jail for this if the JavaScript police catches us, but I'm taking the risk. If you absolutely know what you are doing and there is absolutely no other (proper) way, then you could use https://github.com/ForbesLindesay/sync-rpc which essentially abuses spawnSync to execute asynchronous operations in a new process but makes them look synchronous in the main process.

This has very limited use-cases but it can be useful. For example I would never recommend this at all in a server side application with multiple clients. However, in my case it's an Electron app and the user of said app can do cool things with SQL. On their own computer. In their private space. No JavaScript police in sight. There's a dedicated process/thread with a readonly SQLite client for these user-issued queries (shout outs to #311). So in this case performance is not a key concern. The fact that the thing you're doing is possible at all is the main concern. It doesn't matter much if it takes 10ms or 10s.

You have been warned.

@Prinzhorn
Copy link
Contributor

To whoever it may concern: spawning a process for every single call is not a great idea. Shockingly, I know. https://github.com/mmhunter/node-sync-ipc does a similar thing but uses synchronous pipe operations to communicate with another process.

This is not a proper benchmark but the order of magnitude roughly looks like this (using a SELECT with a few rows and a function call for each row)

  • 1ms for a bunch of regular user-defined function calls
  • 100ms for the same synchronous function but inside another process
  • 10,000ms for the same synchronous function but with a new process for every call

So depending on your use-case these might be acceptable numbers or not.

@Prinzhorn
Copy link
Contributor

Looks like someone found a way to use Worker Threads instead of sub processes. Seems to perform reasonably well if you really need to use an async API and you have no alternative https://github.com/un-ts/synckit

@FunctionDJ
Copy link

FunctionDJ commented Oct 19, 2022

We might get to jail for this if the JavaScript police catches us, but I'm taking the risk. If you absolutely know what you are doing

when a github comment starts like this, you know it's gonna be good 😎

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Development

No branches or pull requests

4 participants