Skip to content

Commit

Permalink
Merge pull request #445 from ZIMkaRU/feature/add-progress-perc-to-loa…
Browse files Browse the repository at this point in the history
…ding-win-for-export-db-module

Add progress perc to loading window for export-db module
  • Loading branch information
ezewer authored Nov 18, 2024
2 parents f7a3799 + fba2cec commit 5fd813e
Show file tree
Hide file tree
Showing 7 changed files with 199 additions and 39 deletions.
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
}

0 comments on commit 5fd813e

Please sign in to comment.