TL;DR A piece of Javascript code works flawlessly on Linux whilst behaving inconsistently on Windows.
I am coding an Electron app, using Vue.js for frontend, Vuex for data management and LokiJS for persistence storage (with its File System adapter at the background). I develop this application on Linux, but from time to time I have to switch to Windows to create a Windows build for the client. The Linux build always works flawlessly, the Windows one misbehaves. I assumed it was a LokiJS issue, however, upon the isolation of LokiJS-specific code, it worked properly even on Windows.
Here is simplified store.js
file, which contains all relevant Vuex and LokiJS-related code in my application.
import loki from 'lokijs'
import LokiSFSAdapter from 'lokijs/src/loki-fs-structured-adapter'
import MainState from '../index' // a Vuex.Store object
const state = {
ads: [],
profiles: []
}
var sfsAdapter = new LokiSFSAdapter('loki')
var db = new loki('database.json', {
autoupdate: true,
autoload: true,
autoloadCallback: setupHandler,
adapter: sfsAdapter
})
function setupCollection (collectionName) {
var collection = db.getCollection(collectionName)
if (collection === null) {
collection = db.addCollection(collectionName)
}
}
function setupHandler () {
setupCollection('ads')
setupCollection('profiles')
MainState.commit('updateAds')
MainState.commit('updateProfiles')
}
window.onbeforeunload = function () {
db.saveDatabase()
db.close()
}
const mutations = {
updateAds (state) {
state.ads = db.getCollection('ads').data.slice()
},
updateProfiles (state) {
state.profiles = db.getCollection('profiles').data.slice()
}
}
const actions = {
async addProfile (context) {
db.getCollection('profiles').insert({ /* default data */ })
db.saveDatabase()
context.commit('updateProfiles')
},
async updateProfile (context, obj) {
db.getCollection('profiles').update(obj)
db.saveDatabase()
context.commit('updateProfiles')
},
async deleteProfile (context, id) {
db.getCollection('profiles').removeWhere({'$loki': {'$eq': id}})
db.saveDatabase()
context.commit('updateProfiles')
},
async addAd (context) {
db.getCollection('ads').insert({ /* default data */ })
db.saveDatabase()
context.commit('updateAds')
},
async deleteAd (context, id) {
db.getCollection('ads').removeWhere({'$loki': {'$eq': id}})
db.saveDatabase()
context.commit('updateAds')
}
}
Behaviour on Linux
- it calls
setupHandler
every time the application starts, - it correctly saves data to
database.json
and the respective collections todatabase.json.0
anddatabase.json.1
forads
andprofiles
- when
addAd()
is called, it can access all the data properly by callingdb.getCollection('ads')
, and theninsert()
on it.
Behaviour on Windows
- only calls
setupHandler
ifdatabase.json
doesn't exist. It correctly createsdatabase.json
if it doesn't exist, though. - creates only one file -
database.json.0
, but doesn't save any data there, it's just an empty file. It doesn't even createdatabase.json.1
for the second collection. - obviously, since no data is actually saved,
db.getCollection('ads')
and returnsnull
, which results intoTypeError: Cannot read property 'insert' of null
when callingaddAd()
on the successive application runs. - if this run
database.json
was created, the application behaves normally,insert()
seems to work, however, no data is saved on exit and the successive runs result in the behaviour in the point above.
Question
Is this a bug somewhere deep in LokiJS/Vuex, or is it just me misusing their API?