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

Add progress perc to loading window for export-db module #445

Merged
Show file tree
Hide file tree
Changes from all 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
4 changes: 4 additions & 0 deletions build/locales/en/translations.json
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,10 @@
"confirmButtonText": "OK",
"title": "Database export",
"message": "Exported successfully"
},
"loadingWindow": {
"description": "Exporting DB ...",
"archiveSize": "archive size {{prettyArchiveSize}}"
}
},
"importDB": {
Expand Down
4 changes: 4 additions & 0 deletions build/locales/ru/translations.json
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,10 @@
"confirmButtonText": "OK",
"title": "Экспорт базы данных",
"message": "Экспортирована успешно"
},
"loadingWindow": {
"description": "Экспортирование БД ...",
"archiveSize": "размер архива {{prettyArchiveSize}}"
}
},
"importDB": {
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
},
"license": "Apache-2.0",
"dependencies": {
"archiver": "5.3.0",
"archiver": "7.0.1",
"bfx-svc-test-helper": "git+https://github.com/bitfinexcom/bfx-svc-test-helper.git",
"bittorrent-dht": "10.0.2",
"changelog-parser": "3.0.1",
Expand Down
109 changes: 96 additions & 13 deletions src/archiver.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,17 +9,66 @@ const {
InvalidFileNameInArchiveError
} = require('./errors')

const zip = (
const getTotalFilesStats = async (filePaths) => {
const promises = filePaths.map((filePath) => {
return fs.promises.stat(filePath)
})
const stats = await Promise.all(promises)
const size = stats.reduce((size, stat) => {
return Number.isFinite(stat?.size)
? size + stat.size
: size
}, 0)

return {
size,
stats
}
}

const bytesToSize = (bytes) => {
const sizes = ['Bytes', 'KB', 'MB', 'GB', 'TB']

if (bytes <= 0) {
return '0 Byte'
}

const i = Number.parseInt(Math.floor(Math.log(bytes) / Math.log(1024)))
const val = Math.round(bytes / Math.pow(1024, i), 2)
const size = sizes[i]

return `${val} ${size}`
}

const zip = async (
zipPath,
filePaths = [],
params = {}
filePaths,
params
) => {
return new Promise((resolve, reject) => {
const _filePaths = Array.isArray(filePaths)
? filePaths
: [filePaths]
const {
size,
stats
} = await getTotalFilesStats(_filePaths)

return new Promise((_resolve, _reject) => {
let interval = null
const resolve = (...args) => {
clearInterval(interval)
return _resolve(...args)
}
const reject = (err) => {
clearInterval(interval)
return _reject(err)
}

try {
const _filePaths = Array.isArray(filePaths)
? filePaths
: [filePaths]
const { zlib } = { ...params }
const {
zlib,
progressHandler
} = params ?? {}
const _params = {
...params,
zlib: {
Expand All @@ -36,16 +85,50 @@ const zip = (
archive.on('error', reject)
archive.on('warning', reject)

if (typeof progressHandler === 'function') {
let processedBytes = 0

const asyncProgressHandler = async () => {
try {
if (
!Number.isFinite(size) ||
size === 0 ||
!Number.isFinite(processedBytes)
) {
return
}

const progress = processedBytes / size
const archiveBytes = archive.pointer()
const prettyArchiveSize = bytesToSize(archiveBytes)

await progressHandler({
progress,
archiveBytes,
prettyArchiveSize
})
} catch (err) {
console.debug(err)
}
}

archive.on('progress', async (e) => {
processedBytes = e.fs.processedBytes ?? 0
await asyncProgressHandler()
})
interval = setInterval(asyncProgressHandler, 3000)
}

archive.pipe(output)

_filePaths.forEach((file) => {
const readStream = fs.createReadStream(file)
const name = path.basename(file)
for (const [i, filePath] of _filePaths.entries()) {
const readStream = fs.createReadStream(filePath)
const name = path.basename(filePath)

readStream.on('error', reject)

archive.append(readStream, { name })
})
archive.append(readStream, { name, stats: stats[i] })
}

archive.finalize()
} catch (err) {
Expand Down
31 changes: 28 additions & 3 deletions src/export-db.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,8 @@ const showErrorModalDialog = require('./show-error-modal-dialog')
const showMessageModalDialog = require('./show-message-modal-dialog')
const {
showLoadingWindow,
hideLoadingWindow
hideLoadingWindow,
setLoadingDescription
} = require('./window-creators/change-loading-win-visibility-state')
const wins = require('./window-creators/windows')
const isMainWinAvailable = require('./helpers/is-main-win-available')
Expand Down Expand Up @@ -67,13 +68,37 @@ module.exports = ({
throw new InvalidFilePathError()
}

await showLoadingWindow()
await showLoadingWindow({
description: i18next
.t('common.exportDB.loadingWindow.description')
})

const progressHandler = async (args) => {
const {
progress,
prettyArchiveSize
} = args ?? {}

const _description = i18next.t('common.exportDB.loadingWindow.description')
const _archived = i18next.t(
'common.exportDB.loadingWindow.archiveSize',
{ prettyArchiveSize }
)

const archived = prettyArchiveSize
? `<br><small style="color:#808b93">${_archived}</small>`
: ''
const description = `${_description}${archived}`

await setLoadingDescription({ progress, description })
}

await zip(filePath, [
dbPath,
dbShmPath,
dbWalPath,
secretKeyPath
])
], { progressHandler })
await hideLoadingWindow()

await showMessageModalDialog(win, {
Expand Down
2 changes: 1 addition & 1 deletion src/show-error-modal-dialog.js
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ module.exports = async (win, title = 'Error', err) => {
return _showErrorBox(win, title, message)
}

const message = i18next.t('common.showErrorModalDialog.syncFrequencyChangingErrorMessage')
const message = i18next.t('common.showErrorModalDialog.unexpectedExceptionMessage')

return _showErrorBox(win, title, message)
}
86 changes: 65 additions & 21 deletions src/window-creators/change-loading-win-visibility-state.js
Original file line number Diff line number Diff line change
Expand Up @@ -59,11 +59,12 @@ const _setParentWindow = (noParent) => {
wins.loadingWindow.setParentWindow(win)
}

const _runProgressLoader = (opts = {}) => {
const _runProgressLoader = (opts) => {
const {
win = wins.loadingWindow,
isIndeterminateMode = false
} = { ...opts }
isIndeterminateMode = false,
progress
} = opts ?? {}

if (
!win ||
Expand All @@ -72,6 +73,20 @@ const _runProgressLoader = (opts = {}) => {
) {
return
}
if (Number.isFinite(progress)) {
if (
progress >= 1 &&
!isIndeterminateMode
) {
win.setProgressBar(-0.1)

return
}

win.setProgressBar(progress)

return
}
if (isIndeterminateMode) {
// Change to indeterminate mode when progress > 1
win.setProgressBar(1.1)
Expand All @@ -83,14 +98,14 @@ const _runProgressLoader = (opts = {}) => {
const duration = 3000 // ms
const interval = duration / fps // ms
const step = 1 / (duration / interval)
let progress = 0
let _progress = 0

intervalMarker = setInterval(() => {
if (progress >= 1) {
progress = 0
if (_progress >= 1) {
_progress = 0
}

progress += step
_progress += step

if (
!win ||
Expand All @@ -102,7 +117,7 @@ const _runProgressLoader = (opts = {}) => {
return
}

win.setProgressBar(progress)
win.setProgressBar(_progress)
}, interval).unref()
}

Expand All @@ -123,8 +138,14 @@ const _stopProgressLoader = (
win.setProgressBar(-0.1)
}

const _setLoadingDescription = async (win, description) => {
const setLoadingDescription = async (params) => {
try {
const {
win = wins.loadingWindow,
progress,
description = ''
} = params ?? {}

if (
!win ||
typeof win !== 'object' ||
Expand All @@ -134,11 +155,31 @@ const _setLoadingDescription = async (win, description) => {
return
}

const _progressPerc = (
Number.isFinite(progress) &&
progress > 0
)
? Math.floor(progress * 100)
: null
const progressPerc = (
Number.isFinite(_progressPerc) &&
_progressPerc > 100
)
? 100
: _progressPerc
const descriptionChunk = description
? `<p>${description}</p>`
: '<p></p>'
const progressChunk = Number.isFinite(progressPerc)
? `<p>${progressPerc} %</p>`
: '<p></p>'
const _description = `${progressChunk}${descriptionChunk}`

const loadingDescReadyPromise = GeneralIpcChannelHandlers
.onLoadingDescriptionReady()

GeneralIpcChannelHandlers
.sendLoadingDescription(win, { description })
.sendLoadingDescription(win, { description: _description })

const loadingRes = await loadingDescReadyPromise

Expand All @@ -152,6 +193,7 @@ const _setLoadingDescription = async (win, description) => {

const showLoadingWindow = async (opts) => {
const {
progress,
description = '',
isRequiredToCloseAllWins = false,
isNotRunProgressLoaderRequired = false,
Expand All @@ -170,14 +212,18 @@ const showLoadingWindow = async (opts) => {

_setParentWindow(isRequiredToCloseAllWins || noParent)

if (!isNotRunProgressLoaderRequired) {
_runProgressLoader({ isIndeterminateMode })
const _progress = Number.isFinite(progress)
? Math.floor(progress * 100) / 100
: progress

if (
!isNotRunProgressLoaderRequired ||
Number.isFinite(progress)
) {
_runProgressLoader({ progress: _progress, isIndeterminateMode })
}

await _setLoadingDescription(
wins.loadingWindow,
description
)
await setLoadingDescription({ progress: _progress, description })

if (!wins.loadingWindow.isVisible()) {
centerWindow(wins.loadingWindow)
Expand All @@ -197,10 +243,7 @@ const hideLoadingWindow = async (opts) => {
} = opts ?? {}

// need to empty description
await _setLoadingDescription(
wins.loadingWindow,
''
)
await setLoadingDescription({ description: '' })
_stopProgressLoader()

if (isRequiredToShowMainWin) {
Expand All @@ -224,5 +267,6 @@ const hideLoadingWindow = async (opts) => {

module.exports = {
showLoadingWindow,
hideLoadingWindow
hideLoadingWindow,
setLoadingDescription
}