CytubeBot icon indicating copy to clipboard operation
CytubeBot copied to clipboard

CytubeBot fails to create a working database

Open SeleneASong opened this issue 10 years ago • 3 comments

When CytubeBot creates it's database, it does it in such a way that it'll crash when it tries to supply values to the users table. I have fixed this on my own machine by manually dropping the users table and creating a new one with this command: CREATE TABLE users(uname TEXT, blacklisted TEXT, block TEXT, rank INTEGER, primary key(uname));

I believe the bug exists in line 22 of lib/database.js, which reads:

this.db.run("CREATE TABLE IF NOT EXISTS users(uname TEXT, blacklisted TEXT, block TEXT, primary key(uname))")

but should read:

this.db.run("CREATE TABLE IF NOT EXISTS users(uname TEXT, blacklisted TEXT, block TEXT, rank INTEGER, primary key(uname))")

Adding "rank INTEGER," which seems to have been left out.

SeleneASong avatar Feb 14 '16 13:02 SeleneASong

Rank should be added when it updates the tables though. https://github.com/nuclearace/CytubeBot/blob/master/lib/database.js#L40

nuclearace avatar Feb 14 '16 15:02 nuclearace

For me, it crashed before it got to that point.

http://pastebin.com/QkWEVWy9

SeleneASong avatar Feb 14 '16 15:02 SeleneASong

The database initialization code is fragile and has race conditions. What probably happened is the disk was slow and the network was fast so the bot joined the room and got the list of users before running ALTER TABLE users ADD rank INTEGER.

  1. serialize() does not lock the database. Other threads can still put new commands onto the queue. Your use of update.run(callback) gives another thread ample opportunity to run a command (inserting users, in this case) before the ALTER TABLE command is put onto the queue. Even without the callback other threads could still interleave commands with the initialization code.
  2. The version number is incremented before issuing the ALTER TABLE command. If the ALTER TABLE command fails it will never be reattempted because the version is already '1'. These should be done together in a transaction so that if one fails both are rolled back and reattempted when the bot restarts.
  3. parallelize() is never called unless it's the first time the bot is run. On all subsequent runs the database will remain in serial mode. I'd image the database is one of your bottlenecks, especially with no indices.

The trick for #1 is to lock the database during initialization but not require threads to acquire locks after that point or you'll remove any parallelism.

awused avatar Sep 15 '16 04:09 awused