capacitor-community / sqlite

Community plugin for native & electron SQLite databases
MIT License
433 stars 106 forks source link

Drop database in electron #287

Closed CosminCraciun closed 1 year ago

CosminCraciun commented 1 year ago

Deleting the database from an electron app fails with the following error: Error: Error invoking remote method 'CapacitorSQLite-deleteDatabase': Error: Delete: Error: DeleteDB: deleteFile failed DeleteFileName: delete filePath failed DeleteFilePath: Error: EBUSY: resource busy or locked, unlink ...

It works fine for other devices (web / android / ios). I have tried closing the before deleting, but the same issue appears. Looks like the connection still exists when trying to delete the database.

LgArcida commented 1 year ago

+1

jepiqueau commented 1 year ago

@CosminCraciun can you share a small repro code showing the error. It will help me to identify the error.

CosminCraciun commented 1 year ago

@jepiqueau I created a simple app for you to try this. It just runs web and electron. I have specified how to run them in the readme. You can find it here The app initializes the database on startup and tries to delete it when you press the button. The db location in electron is in C:\ProgramData\Test-delete-db

jepiqueau commented 1 year ago

@CosminCraciun this is the procedure i followed

git clone https://github.com/CosminCraciun/db-delete.git
npm install
modify the capacitor.config.ts 
-> webDir: 'dist/db-delete'
-> add a location for the database: 
  plugins: {
    // eslint-disable-next-line @typescript-eslint/naming-convention
    CapacitorSQLite: {
      electronWindowsLocation: 'C:\\ProgramData\\CapacitorDatabases',
      electronMacLocation: '/YOUR_LOCATION/CapacitorDatabases',
      electronLinuxLocation: 'Databases'
    }
  }

delete the electron folder from the app
npm run build
npx cap add @capacitor-community/electron
npx cap sync
npx cap sync @capacitor-community/electron
npm run build
npx cap copy
npx cap copy @capacitor-community/electron
npm run start
npx cap open @capacitor-community/electron or cd electron npm run electron:start

and everything work fine in the browser to see that the database is deleted do not forget to refresh JeepSqliteStore and you will see under database that the key testSQLite.db is not there anymore

jepiqueau commented 1 year ago

@CosminCraciun Can you tell me if you have succeed to implement it and if it works. without news from you i will close the issue

CosminCraciun commented 1 year ago

@jepiqueau sorry for the late response

in the browser it works fine. Electron is the issue. Electron is not using JeepSqliteStore, the database is saved in C:\ProgramData...

Regarding your steps: deleting the electron folder also deletes capacitor.config.ts,. On generation the new one does not have the plugin section with the sqlite location.

But I ran a few more tests now. And it does not seem consistent. Sometimes it manages to delete without a problem, while sometimes it throws the error I mentioned. It looks like the connection is closed, but the db file is still present in ProgramData. When it DOES work I get this error in the capacitor console: Error: Close failed: ${this.dbName} I am not sure if there is still a process hanging on the database, or the close() is not fully awaited.

What I did notice is that it never managed to delete if I waited a few seconds before clicking delete. All the time it succeeded for me was if I click as soon as the app starts

jepiqueau commented 1 year ago

@CosminCraciun i will publish the app i clone from you as what you described never happen to me so you can test it

jepiqueau commented 1 year ago

@CosminCraciun look at https://github.com/jepiqueau/db-delete

CosminCraciun commented 1 year ago

I have tried your repo and followed the steps described and I got the error on the first run. To clarify, I am running Windows. I have seen it under both windows 10 and 11.

main.6f0cddbb95640978.js:1 ERROR Error: Uncaught (in promise): Error: Error invoking remote method 'CapacitorSQLite-deleteDatabase': Error: Delete: Error: DeleteDB: deleteFile testSQLite.db failed DeleteFileName: delete filePath failed DeleteFilePath: Error: EBUSY: resource busy or locked, unlink 'C:\ProgramData\CapacitorDatabases\db-delete\testSQLite.db' Error: Error invoking remote method 'CapacitorSQLite-deleteDatabase': Error: Delete: Error: DeleteDB: deleteFile testSQLite.db failed DeleteFileName: delete filePath failed DeleteFilePath: Error: EBUSY: resource busy or locked, unlink 'C:\ProgramData\CapacitorDatabases\db-delete\testSQLite.db' at G (polyfills.7ed0ed6da77d9d75.js:1) at polyfills.7ed0ed6da77d9d75.js:1 at q (main.6f0cddbb95640978.js:1) at nt (main.6f0cddbb95640978.js:1) at T.invoke (polyfills.7ed0ed6da77d9d75.js:1) at Object.onInvoke (main.6f0cddbb95640978.js:1) at T.invoke (polyfills.7ed0ed6da77d9d75.js:1) at I.run (polyfills.7ed0ed6da77d9d75.js:1) at polyfills.7ed0ed6da77d9d75.js:1 at T.invokeTask (polyfills.7ed0ed6da77d9d75.js:1)

jepiqueau commented 1 year ago

@CosminCraciun OK i did not test under Windows but under Mac so i will have a look when i got time free

jepiqueau commented 1 year ago

@CosminCraciun I took some time to look at it. i reproduce the error. now if i remove

        await this._db!.execute(`PRAGMA journal_mode=WAL;`,false);

in method ensureTablesExist() of database.service.ts it is working well

jepiqueau commented 1 year ago

@CosminCraciun i do not really what to do from there. Do you really need to use the journal_mode WAL ?

CosminCraciun commented 1 year ago

That was added due to a different issue. Concurrent writes to the database interfered with each other: https://github.com/capacitor-community/sqlite/issues/215 It looked like just Android had WAL as a default.

I could try reverting the pragma before deleting. Do you think it's rather an issue with sqlite3 under windows?

CosminCraciun commented 1 year ago

@jepiqueau I have tried setting journal_mode to OFF. And it partly worked. I also had to add a delay after closing the database. Otherwise operation went through without errors, but the db file was still present on disk

jepiqueau commented 1 year ago

@CosminCraciun remove the execute command where you set up the pragma so the default delete will be set. Delete physically the database files on your disk and restart the app fir me it works

jepiqueau commented 1 year ago

@CosminCraciun it is a Windows problem with sqlite3 as it works fine on Mac. Test if the platform is Electron under Windows and do not do the execute with the pragma that's all what i can say. You must avoid concurrent writes on the db .

CosminCraciun commented 1 year ago

It is a bit hard to avoid, as we have a few services that could be triggered in parallel. I was hoping the database will handle that. My solution is:

  1. set journal mode to OFF
  2. close the db
  3. have a small delay (~100ms)
  4. delete the db

This seems to work fine. Thanks for your help!

jepiqueau commented 1 year ago

@CosminCraciun it may be better to set the journal_mode to DELETE than OFF. Anyhow if you find a solution which works it is fine as i do not know what to do with it. Have a good development