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

feat: catch and log electron-store.set errors #2547

Merged
Merged
Show file tree
Hide file tree
Changes from 12 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 7 additions & 2 deletions src/automatic-gc.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,14 @@ function disable () {
}
}

/**
*
* @param {string[]} newFlags
*/
function applyConfig (newFlags) {
store.set('ipfsConfig.flags', newFlags)
ipcMain.emit(ipcMainEvents.IPFS_CONFIG_CHANGED) // trigger node restart
store.safeSet('ipfsConfig.flags', newFlags, () => {
ipcMain.emit(ipcMainEvents.IPFS_CONFIG_CHANGED) // trigger node restart
})
}

module.exports = async function () {
Expand Down
2 changes: 1 addition & 1 deletion src/common/config-keys.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/**
* Configuration key constants for the features in IPFS Desktop.
*
* @constant
* @type {Record<import('../types').CONFIG_KEYS, string>}
*/
const CONFIG_KEYS = {
Expand Down
40 changes: 30 additions & 10 deletions src/common/logger.js
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ logger.info(`[meta] logs can be found on ${logsPath}`)

/**
*
* @param {AnalyticsTimeOptions & import('countly-sdk-nodejs').CountlyAddEventOptions} args
* @param {AnalyticsTimeOptions & Omit<import('countly-sdk-nodejs').CountlyAddEventOptions, 'key'>} opts
*
* @returns {void} void
*/
Expand All @@ -79,11 +79,11 @@ module.exports = Object.freeze({
/**
*
* @param {string} msg
* @param {AnalyticsTimeOptions} opts
* @param {AnalyticsTimeOptions & Omit<import('countly-sdk-nodejs').CountlyAddEventOptions, 'key'>} opts
*
* @returns {AnalyticsTimeReturnValue} AnalyticsTimeReturnValue
*/
start: (msg, opts = {}) => {
start: (msg, opts) => {
const start = performance.now()
logger.info(`${msg} STARTED`)

Expand All @@ -107,19 +107,35 @@ module.exports = Object.freeze({
/**
*
* @param {string} msg
* @param {AnalyticsTimeOptions & import('countly-sdk-nodejs').CountlyAddEventOptions} opts
* @param {AnalyticsTimeOptions & Omit<import('countly-sdk-nodejs').CountlyAddEventOptions, 'key'>} [opts]
*
* @returns {void} void
*/
info: (msg, opts = {}) => {
addAnalyticsEvent({ count: 1, ...opts })
info: (msg, opts) => {
if (opts) {
addAnalyticsEvent({ count: 1, ...opts })
}

logger.info(msg)
},

error: (err) => {
Countly.log_error(err)
logger.error(err)
/**
*
* @param {Error|string} errMsg
* @param {Error|unknown} [error]
*/
error: (errMsg, error) => {
if (errMsg instanceof Error) {
Countly.log_error(errMsg)
logger.error(errMsg)
} else if (error != null && error instanceof Error) {
// errorMessage is not an instance of an error, but error is
Countly.log_error(error)
logger.error(errMsg, error)
} else {
Countly.log_error(new Error(errMsg))
logger.error(errMsg, error)
}
Comment on lines +127 to +138
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fix error logging

},

warn: (msg, meta) => {
Expand All @@ -131,5 +147,9 @@ module.exports = Object.freeze({
},

logsPath,
addAnalyticsEvent
addAnalyticsEvent,
/**
* For when you want to log something without potentially emitting it to countly
*/
fileLogger: logger
})
52 changes: 47 additions & 5 deletions src/common/store.js
Original file line number Diff line number Diff line change
@@ -1,22 +1,30 @@
const electron = require('electron')
const { app } = require('electron')
const Store = require('electron-store')

const logger = require('./logger')

const { fileLogger } = logger

/**
* @type {import('./types').DesktopPersistentStore}
*/
const defaults = {
ipfsConfig: {
type: 'go',
path: '',
flags: [
'--agent-version-suffix=desktop',
'--migrate',
'--enable-gc'
]
},
language: (electron.app || electron.remote.app).getLocale(),
experiments: {}
language: app.getLocale(),
experiments: {},
binaryPath: ''
}

const migrations = {
'>=0.11.0': store => {
fileLogger.info('Running migration: >=0.11.0')
store.delete('version')

const flags = store.get('ipfsConfig.flags', [])
Expand All @@ -26,6 +34,7 @@ const migrations = {
}
},
'>0.13.2': store => {
fileLogger.info('Running migration: >0.13.2')
const flags = store.get('ipfsConfig.flags', [])
const automaticGC = store.get('automaticGC', false)
// ensure checkbox follows cli flag config
Expand All @@ -34,6 +43,7 @@ const migrations = {
}
},
'>=0.17.0': store => {
fileLogger.info('Running migration: >=0.17.0')
let flags = store.get('ipfsConfig.flags', [])

// make sure version suffix is always present and normalized
Expand All @@ -53,6 +63,7 @@ const migrations = {
}
},
'>=0.20.6': store => {
fileLogger.info('Running migration: >=0.20.6')
let flags = store.get('ipfsConfig.flags', [])

// use default instead of hard-coded dhtclient
Expand All @@ -64,7 +75,38 @@ const migrations = {
}
}

const store = new Store({
/**
* @extends {Store<import('./types').DesktopPersistentStore>}
*/
class StoreWrapper extends Store {
constructor (options) {
super(options)

/**
* @template {unknown} R
* @param {string} key
* @param {unknown} value
* @param {() => Promise<R>|R|void} [onSuccessFn]
* @returns {Promise<R|void>}
*/
this.safeSet = async function (key, value, onSuccessFn) {
try {
this.set(key, value)
if (typeof onSuccessFn === 'function') {
try {
return await onSuccessFn()
} catch (err) {
logger.error(`[store.safeSet] Error calling onSuccessFn for '${key}'`, /** @type {Error} */(err))
}
}
} catch (err) {
logger.error(`[store.safeSet] Could not set store key '${key}' to '${value}'`, /** @type {Error} */(err))
}
}
}
}

Comment on lines +78 to +108
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

TYSM ❤️

const store = new StoreWrapper({
defaults,
migrations
})
Expand Down
12 changes: 12 additions & 0 deletions src/common/types.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
export interface DesktopPersistentStore_IpfsdConfig {
path: string,
flags: string[]
}

export interface DesktopPersistentStore {

ipfsConfig: DesktopPersistentStore_IpfsdConfig,
language: string,
experiments: Record<string, boolean>,
binaryPath?: string
}
30 changes: 15 additions & 15 deletions src/custom-ipfs-binary.js
Original file line number Diff line number Diff line change
Expand Up @@ -40,23 +40,23 @@ async function setCustomBinary () {
return
}

store.set(SETTINGS_KEY, filePaths[0])
store.safeSet(SETTINGS_KEY, filePaths[0], () => {
opt = showDialog({
showDock: false,
title: i18n.t('setCustomIpfsBinarySuccess.title'),
message: i18n.t('setCustomIpfsBinarySuccess.message', { path: filePaths[0] }),
buttons: [
i18n.t('restart'),
i18n.t('close')
]
})

opt = showDialog({
showDock: false,
title: i18n.t('setCustomIpfsBinarySuccess.title'),
message: i18n.t('setCustomIpfsBinarySuccess.message', { path: filePaths[0] }),
buttons: [
i18n.t('restart'),
i18n.t('close')
]
})
logger.info(`[custom binary] updated to ${filePaths[0]}`)

logger.info(`[custom binary] updated to ${filePaths[0]}`)

if (opt === 0) {
restartIpfs()
}
if (opt === 0) {
restartIpfs()
}
})
})
}

Expand Down
4 changes: 2 additions & 2 deletions src/daemon/config.js
Original file line number Diff line number Diff line change
Expand Up @@ -234,13 +234,13 @@ function migrateConfig (ipfsd) {
if (changed) {
try {
writeConfigFile(ipfsd, config)
store.set(REVISION_KEY, REVISION)
store.safeSet(REVISION_KEY, REVISION)
} catch (err) {
logger.error(`[daemon] migrateConfig: error writing config file: ${err.message || err}`)
return
}
}
store.set(REVISION_KEY, REVISION)
store.safeSet(REVISION_KEY, REVISION)
}

/**
Expand Down
2 changes: 1 addition & 1 deletion src/daemon/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ async function setupDaemon () {
// not set.
if (!config.path || typeof config.path !== 'string') {
config.path = ipfsd.path
store.set('ipfsConfig', config)
store.safeSet('ipfsConfig', config)
}

log.end()
Expand Down
7 changes: 4 additions & 3 deletions src/enable-namesys-pubsub.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,12 +25,13 @@ function disable () {
}

function applyConfig (newFlags) {
store.set('ipfsConfig.flags', newFlags)
ipcMain.emit(ipcMainEvents.IPFS_CONFIG_CHANGED) // trigger node restart
store.safeSet('ipfsConfig.flags', newFlags, () => {
ipcMain.emit(ipcMainEvents.IPFS_CONFIG_CHANGED) // trigger node restart
})
}

module.exports = async function () {
const activate = ({ newValue, oldValue }) => {
const activate = ({ newValue, oldValue = null }) => {
if (newValue === oldValue) return

try {
Expand Down
7 changes: 4 additions & 3 deletions src/enable-pubsub.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,12 +25,13 @@ function disable () {
}

function applyConfig (newFlags) {
store.set('ipfsConfig.flags', newFlags)
ipcMain.emit(ipcMainEvents.IPFS_CONFIG_CHANGED) // trigger node restart
store.safeSet('ipfsConfig.flags', newFlags, () => {
ipcMain.emit(ipcMainEvents.IPFS_CONFIG_CHANGED) // trigger node restart
})
}

module.exports = async function () {
const activate = ({ newValue, oldValue }) => {
const activate = ({ newValue, oldValue = null }) => {
if (newValue === oldValue) return

try {
Expand Down
2 changes: 1 addition & 1 deletion src/i18n.js
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ module.exports = async function () {
return
}

store.set('language', lang)
store.safeSet('language', lang)

await i18n.changeLanguage(lang)
ipcMain.emit(ipcMainEvents.LANG_UPDATED, lang)
Expand Down
20 changes: 11 additions & 9 deletions src/move-repository-location.js
Original file line number Diff line number Diff line change
Expand Up @@ -69,23 +69,25 @@ module.exports = function ({ stopIpfs, startIpfs }) {
await fs.move(currDir, newDir)
logger.info(`[move repository] moved from ${currDir} to ${newDir}`)
} catch (err) {
logger.error(`[move repository] ${err.toString()}`)
logger.error(`[move repository] error moving from '${currDir}' to '${newDir}'`, err)
return recoverableErrorDialog(err, {
title: i18n.t('moveRepositoryFailed.title'),
message: i18n.t('moveRepositoryFailed.message', { currDir, newDir })
})
}

config.path = newDir
store.set('ipfsConfig', config)
logger.info('[move repository] configuration updated', { withAnalytics: analyticsKeys.MOVE_REPOSITORY })

showDialog({
title: i18n.t('moveRepositorySuccessDialog.title'),
message: i18n.t('moveRepositorySuccessDialog.message', { location: newDir }),
showDock: false
})
await store.safeSet('ipfsConfig', config, async () => {
logger.info('[move repository] configuration updated', { withAnalytics: analyticsKeys.MOVE_REPOSITORY })

showDialog({
title: i18n.t('moveRepositorySuccessDialog.title'),
message: i18n.t('moveRepositorySuccessDialog.message', { location: newDir }),
showDock: false
})

await startIpfs()
await startIpfs()
})
})
}
3 changes: 1 addition & 2 deletions src/tray.js
Original file line number Diff line number Diff line change
Expand Up @@ -405,8 +405,7 @@ module.exports = async function () {
await setupMenu()

createToggler(CONFIG_KEYS.MONOCHROME_TRAY_ICON, async ({ newValue }) => {
store.set(CONFIG_KEYS.MONOCHROME_TRAY_ICON, newValue)
return true
return store.safeSet(CONFIG_KEYS.MONOCHROME_TRAY_ICON, newValue, () => true)
})

ctx.setProp('tray', tray)
Expand Down
8 changes: 4 additions & 4 deletions src/utils/create-toggler.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,10 @@ module.exports = function (settingsOption, activate) {
const newValue = !oldValue

if (await activate({ newValue, oldValue, feedback: true })) {
store.set(settingsOption, newValue)

const action = newValue ? 'enabled' : 'disabled'
logger.info(`[${settingsOption}] ${action}`)
store.safeSet(settingsOption, newValue, () => {
const action = newValue ? 'enabled' : 'disabled'
logger.info(`[${settingsOption}] ${action}`)
})
}

// We always emit the event so any handlers for it can act upon
Expand Down
Loading