mirror of
https://github.com/advplyr/audiobookshelf.git
synced 2025-03-28 00:21:47 +01:00
Add: db error recovery check, Fix: bookmarks modal UI overflow #115
This commit is contained in:
parent
f7a780032f
commit
f212ea91f9
@ -3,7 +3,7 @@
|
|||||||
<nuxt-link :to="`/audiobook/${streamAudiobook.id}`" class="absolute -top-16 left-4 cursor-pointer">
|
<nuxt-link :to="`/audiobook/${streamAudiobook.id}`" class="absolute -top-16 left-4 cursor-pointer">
|
||||||
<cards-book-cover :audiobook="streamAudiobook" :width="88" />
|
<cards-book-cover :audiobook="streamAudiobook" :width="88" />
|
||||||
</nuxt-link>
|
</nuxt-link>
|
||||||
<div class="flex items-center pl-24">
|
<div class="flex items-start pl-24">
|
||||||
<div>
|
<div>
|
||||||
<nuxt-link :to="`/audiobook/${streamAudiobook.id}`" class="hover:underline cursor-pointer text-lg">
|
<nuxt-link :to="`/audiobook/${streamAudiobook.id}`" class="hover:underline cursor-pointer text-lg">
|
||||||
{{ title }} <span v-if="stream && $isDev" class="text-xs text-gray-400">({{ stream.id }})</span>
|
{{ title }} <span v-if="stream && $isDev" class="text-xs text-gray-400">({{ stream.id }})</span>
|
||||||
@ -22,7 +22,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="flex-grow" />
|
<div class="flex-grow" />
|
||||||
<span v-if="stream" class="material-icons px-4 cursor-pointer" @click="cancelStream">close</span>
|
<span v-if="stream" class="material-icons p-4 cursor-pointer" @click="cancelStream">close</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<audio-player ref="audioPlayer" :chapters="chapters" :loading="isLoading" :bookmarks="bookmarks" @close="cancelStream" @updateTime="updateTime" @loaded="(d) => (totalDuration = d)" @showBookmarks="showBookmarks" @hook:mounted="audioPlayerMounted" />
|
<audio-player ref="audioPlayer" :chapters="chapters" :loading="isLoading" :bookmarks="bookmarks" @close="cancelStream" @updateTime="updateTime" @loaded="(d) => (totalDuration = d)" @showBookmarks="showBookmarks" @hook:mounted="audioPlayerMounted" />
|
||||||
|
@ -11,8 +11,8 @@
|
|||||||
<div class="w-full h-px bg-white bg-opacity-10" />
|
<div class="w-full h-px bg-white bg-opacity-10" />
|
||||||
<form @submit.prevent="submitCreateBookmark">
|
<form @submit.prevent="submitCreateBookmark">
|
||||||
<div v-show="canCreateBookmark" class="flex px-4 py-2 items-center text-center border-b border-white border-opacity-10 text-white text-opacity-80">
|
<div v-show="canCreateBookmark" class="flex px-4 py-2 items-center text-center border-b border-white border-opacity-10 text-white text-opacity-80">
|
||||||
<div class="w-16 text-center">
|
<div class="w-16 max-w-16 text-center">
|
||||||
<p class="text-sm font-mono">
|
<p class="text-sm font-mono text-gray-400">
|
||||||
{{ this.$secondsToTimestamp(currentTime) }}
|
{{ this.$secondsToTimestamp(currentTime) }}
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
@ -1,12 +1,12 @@
|
|||||||
<template>
|
<template>
|
||||||
<div :key="bookmark.id" :id="`bookmark-row-${bookmark.id}`" class="flex items-center px-4 py-4 justify-start relative hover:bg-bg" :class="wrapperClass" @click="click" @mouseover="mouseover" @mouseleave="mouseleave">
|
<div :key="bookmark.id" :id="`bookmark-row-${bookmark.id}`" class="flex items-center px-4 py-4 justify-start relative hover:bg-bg" :class="wrapperClass" @click="click" @mouseover="mouseover" @mouseleave="mouseleave">
|
||||||
<!-- <span class="material-icons" :class="highlight ? 'text-success' : 'text-white text-opacity-80'">{{ highlight ? 'bookmark' : 'bookmark_border' }}</span> -->
|
<!-- <span class="material-icons" :class="highlight ? 'text-success' : 'text-white text-opacity-80'">{{ highlight ? 'bookmark' : 'bookmark_border' }}</span> -->
|
||||||
<div class="w-12 min-w-12 text-center">
|
<div class="w-16 max-w-16 text-center">
|
||||||
<p class="text-sm font-mono text-white text-opacity-80">
|
<p class="text-sm font-mono text-gray-400">
|
||||||
{{ this.$secondsToTimestamp(bookmark.time) }}
|
{{ this.$secondsToTimestamp(bookmark.time) }}
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
<div class="flex-grow overflow-hidden">
|
<div class="flex-grow overflow-hidden px-2">
|
||||||
<template v-if="isEditing">
|
<template v-if="isEditing">
|
||||||
<form @submit.prevent="submitUpdate">
|
<form @submit.prevent="submitUpdate">
|
||||||
<div class="flex items-center">
|
<div class="flex items-center">
|
||||||
|
@ -20,6 +20,7 @@ module.exports = {
|
|||||||
maxWidth: {
|
maxWidth: {
|
||||||
'6': '1.5rem',
|
'6': '1.5rem',
|
||||||
'12': '3rem',
|
'12': '3rem',
|
||||||
|
'16': '4rem',
|
||||||
'24': '6rem',
|
'24': '6rem',
|
||||||
'32': '8rem',
|
'32': '8rem',
|
||||||
'48': '12rem',
|
'48': '12rem',
|
||||||
|
63
server/Db.js
63
server/Db.js
@ -1,5 +1,6 @@
|
|||||||
const Path = require('path')
|
const Path = require('path')
|
||||||
const njodb = require("njodb")
|
const njodb = require("njodb")
|
||||||
|
const fs = require('fs-extra')
|
||||||
const jwt = require('jsonwebtoken')
|
const jwt = require('jsonwebtoken')
|
||||||
const Logger = require('./Logger')
|
const Logger = require('./Logger')
|
||||||
const Audiobook = require('./objects/Audiobook')
|
const Audiobook = require('./objects/Audiobook')
|
||||||
@ -187,6 +188,11 @@ class Db {
|
|||||||
return true
|
return true
|
||||||
}).catch((error) => {
|
}).catch((error) => {
|
||||||
Logger.error(`[DB] Update entity ${entityName} Failed: ${error}`)
|
Logger.error(`[DB] Update entity ${entityName} Failed: ${error}`)
|
||||||
|
|
||||||
|
if (error && error.code === 'ENOENT') {
|
||||||
|
this.attemptDataRecovery(entityName)
|
||||||
|
}
|
||||||
|
|
||||||
return false
|
return false
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@ -204,6 +210,63 @@ class Db {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async attemptDataRecovery(entityName) {
|
||||||
|
var dbDirName = this.getEntityArrayKey(entityName)
|
||||||
|
var dbdir = Path.join(this.ConfigPath, dbDirName)
|
||||||
|
console.log('Attempting data recovery for:', dbdir)
|
||||||
|
|
||||||
|
var exists = await fs.pathExists(dbdir)
|
||||||
|
if (!exists) {
|
||||||
|
console.error('Db dir does not exist', dbdir)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
var dbdatadir = Path.join(dbdir, 'data')
|
||||||
|
var dbtmpdir = Path.join(dbdir, 'tmp')
|
||||||
|
|
||||||
|
var datafiles = await fs.readdir(dbdatadir)
|
||||||
|
var tempfiles = await fs.readdir(dbtmpdir)
|
||||||
|
|
||||||
|
var orphanOld = datafiles.find(df => df.endsWith('.old'))
|
||||||
|
if (orphanOld) {
|
||||||
|
// Get data file num
|
||||||
|
var dbnum = orphanOld.split('.')[1]
|
||||||
|
console.log('Found orphan json.old', orphanOld, `Num: ${dbnum}`)
|
||||||
|
|
||||||
|
var dbDataFilename = `data.${dbnum}.json`
|
||||||
|
|
||||||
|
// make sure data.#.json does not already exist
|
||||||
|
if (datafiles.includes(dbDataFilename)) {
|
||||||
|
console.warn(`${dbDataFilename} already exists, not recovering`)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// find temp file that was supposed to be renamed
|
||||||
|
var matchingTmp = tempfiles.find(tmp => tmp.startsWith(`data.${dbnum}`))
|
||||||
|
if (matchingTmp) {
|
||||||
|
console.log('found matching tmp file', matchingTmp)
|
||||||
|
|
||||||
|
var tmpfileFullPath = Path.join(dbtmpdir, matchingTmp)
|
||||||
|
var renameToPath = Path.join(dbdatadir, dbDataFilename)
|
||||||
|
|
||||||
|
console.log(`Renamining "${tmpfileFullPath}" => "${renameToPath}"`)
|
||||||
|
await fs.rename(tmpfileFullPath, renameToPath)
|
||||||
|
|
||||||
|
console.log('Data recovery successful -- unlinking old')
|
||||||
|
|
||||||
|
await fs.unlink(orphanOld)
|
||||||
|
console.log('Removed .old file')
|
||||||
|
var lockdirpath = Path.join(dbdatadir, `data.${dbnum}.lock`)
|
||||||
|
await fs.rmdir(lockdirpath)
|
||||||
|
console.log('Removed lock dir')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Data recovery failed', error)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
recreateAudiobookDb() {
|
recreateAudiobookDb() {
|
||||||
return this.audiobooksDb.drop().then((results) => {
|
return this.audiobooksDb.drop().then((results) => {
|
||||||
Logger.info(`[DB] Dropped audiobook db`, results)
|
Logger.info(`[DB] Dropped audiobook db`, results)
|
||||||
|
Loading…
Reference in New Issue
Block a user