mirror of
https://github.com/pockethost/pockethost.git
synced 2025-06-07 06:36:43 +00:00
chore: restore autocancellation
This commit is contained in:
parent
b5d3cf48a6
commit
0a09500439
@ -24,11 +24,6 @@ export const createPbClient = (url: string) => {
|
|||||||
)
|
)
|
||||||
|
|
||||||
const client = new PocketBase(url)
|
const client = new PocketBase(url)
|
||||||
client.beforeSend = (url: string, reqConfig: { [_: string]: any }) => {
|
|
||||||
// dbg(reqConfig)
|
|
||||||
delete reqConfig.signal
|
|
||||||
return reqConfig
|
|
||||||
}
|
|
||||||
|
|
||||||
const adminAuthViaEmail = safeCatch(
|
const adminAuthViaEmail = safeCatch(
|
||||||
`adminAuthViaEmail`,
|
`adminAuthViaEmail`,
|
||||||
|
@ -1,11 +1,13 @@
|
|||||||
import {
|
import {
|
||||||
assertTruthy,
|
assertTruthy,
|
||||||
|
BackupRecord,
|
||||||
BackupStatus,
|
BackupStatus,
|
||||||
createTimerManager,
|
createTimerManager,
|
||||||
InstanceBackupJobPayload,
|
InstanceBackupJobPayload,
|
||||||
InstanceRestoreJobPayload,
|
InstanceRestoreJobPayload,
|
||||||
JobCommands,
|
JobCommands,
|
||||||
} from '@pockethost/common'
|
} from '@pockethost/common'
|
||||||
|
import Bottleneck from 'bottleneck'
|
||||||
import { PocketbaseClientApi } from '../db/PbClient'
|
import { PocketbaseClientApi } from '../db/PbClient'
|
||||||
import { backupInstance } from '../util/backupInstance'
|
import { backupInstance } from '../util/backupInstance'
|
||||||
import { dbg } from '../util/dbg'
|
import { dbg } from '../util/dbg'
|
||||||
@ -60,6 +62,7 @@ export const createBackupService = async (
|
|||||||
)
|
)
|
||||||
|
|
||||||
const tm = createTimerManager({})
|
const tm = createTimerManager({})
|
||||||
|
const limiter = new Bottleneck({ maxConcurrent: 1 })
|
||||||
tm.repeat(async () => {
|
tm.repeat(async () => {
|
||||||
const backupRec = await client.getNextBackupJob()
|
const backupRec = await client.getNextBackupJob()
|
||||||
if (!backupRec) {
|
if (!backupRec) {
|
||||||
@ -67,8 +70,10 @@ export const createBackupService = async (
|
|||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
const instance = await client.getInstance(backupRec.instanceId)
|
const instance = await client.getInstance(backupRec.instanceId)
|
||||||
|
const _update = (fields: Partial<BackupRecord>) =>
|
||||||
|
limiter.schedule(() => client.updateBackup(backupRec.id, fields))
|
||||||
try {
|
try {
|
||||||
await client.updateBackup(backupRec.id, {
|
await _update({
|
||||||
status: BackupStatus.Running,
|
status: BackupStatus.Running,
|
||||||
})
|
})
|
||||||
let progress = backupRec.progress || {}
|
let progress = backupRec.progress || {}
|
||||||
@ -78,12 +83,12 @@ export const createBackupService = async (
|
|||||||
(_progress) => {
|
(_progress) => {
|
||||||
progress = { ...progress, ..._progress }
|
progress = { ...progress, ..._progress }
|
||||||
dbg(_progress)
|
dbg(_progress)
|
||||||
return client.updateBackup(backupRec.id, {
|
return _update({
|
||||||
progress,
|
progress,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
await client.updateBackup(backupRec.id, {
|
await _update({
|
||||||
bytes,
|
bytes,
|
||||||
status: BackupStatus.FinishedSuccess,
|
status: BackupStatus.FinishedSuccess,
|
||||||
})
|
})
|
||||||
@ -95,7 +100,7 @@ export const createBackupService = async (
|
|||||||
}
|
}
|
||||||
return s
|
return s
|
||||||
})()
|
})()
|
||||||
await client.updateBackup(backupRec.id, {
|
await _update({
|
||||||
status: BackupStatus.FinishedError,
|
status: BackupStatus.FinishedError,
|
||||||
message,
|
message,
|
||||||
})
|
})
|
||||||
|
@ -39,10 +39,6 @@ export type PocketbaseClientApi = ReturnType<typeof createPocketbaseClient>
|
|||||||
|
|
||||||
export const createPocketbaseClient = (url: string) => {
|
export const createPocketbaseClient = (url: string) => {
|
||||||
const client = new PocketBase(url)
|
const client = new PocketBase(url)
|
||||||
client.beforeSend = (url, reqConfig) => {
|
|
||||||
delete reqConfig.signal
|
|
||||||
return reqConfig
|
|
||||||
}
|
|
||||||
|
|
||||||
const { authStore } = client
|
const { authStore } = client
|
||||||
|
|
||||||
|
@ -1,92 +1,13 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { PUBLIC_APP_DOMAIN } from '$env/static/public'
|
import type { InstancesRecord } from '@pockethost/common'
|
||||||
import { client } from '$src/pocketbase'
|
|
||||||
import { createCleanupManagerSync } from '$util/CleanupManager'
|
|
||||||
import {
|
|
||||||
BackupStatus,
|
|
||||||
type BackupRecord,
|
|
||||||
type InstancesRecord,
|
|
||||||
type RecordId
|
|
||||||
} from '@pockethost/common'
|
|
||||||
import { reduce, sortBy } from '@s-libs/micro-dash'
|
|
||||||
import prettyBytes from 'pretty-bytes'
|
|
||||||
import { onDestroy, onMount } from 'svelte'
|
|
||||||
import { writable } from 'svelte/store'
|
|
||||||
|
|
||||||
export let instance: InstancesRecord
|
export let instance: InstancesRecord
|
||||||
|
|
||||||
const cm = createCleanupManagerSync()
|
|
||||||
const backups = writable<BackupRecord[]>([])
|
|
||||||
let isBackingUp = false
|
|
||||||
onMount(async () => {
|
|
||||||
const { watchBackupsByInstanceId } = client()
|
|
||||||
watchBackupsByInstanceId(instance.id, (r) => {
|
|
||||||
// console.log(`Handling backup update`, r)
|
|
||||||
const { action, record } = r
|
|
||||||
const _backups = reduce(
|
|
||||||
$backups,
|
|
||||||
(c, b) => {
|
|
||||||
c[b.id] = b
|
|
||||||
return c
|
|
||||||
},
|
|
||||||
{} as { [_: RecordId]: BackupRecord }
|
|
||||||
)
|
|
||||||
_backups[record.id] = record
|
|
||||||
|
|
||||||
isBackingUp = false
|
|
||||||
backups.set(
|
|
||||||
sortBy(_backups, (e) => {
|
|
||||||
isBackingUp ||=
|
|
||||||
e.status !== BackupStatus.FinishedError && e.status !== BackupStatus.FinishedSuccess
|
|
||||||
return Date.parse(e.created)
|
|
||||||
}).reverse()
|
|
||||||
)
|
|
||||||
// console.log(record.id)
|
|
||||||
}).then(cm.add)
|
|
||||||
})
|
|
||||||
onDestroy(cm.cleanupAll)
|
|
||||||
|
|
||||||
const startRestore = () => {
|
|
||||||
const { createInstanceBackupJob } = client()
|
|
||||||
createInstanceBackupJob(instance.id)
|
|
||||||
}
|
|
||||||
|
|
||||||
let sourceBackupId = ''
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div class="py-4">
|
<div class="py-4">
|
||||||
<h2>Restore</h2>
|
<h2>Restore</h2>
|
||||||
|
|
||||||
{#if PUBLIC_APP_DOMAIN.toString().endsWith('.io')}
|
|
||||||
Contact support to perform a restore.
|
Contact support to perform a restore.
|
||||||
{/if}
|
|
||||||
{#if PUBLIC_APP_DOMAIN.toString().endsWith('.test')}
|
|
||||||
{#if $backups.length === 0}
|
|
||||||
You must create a backup first.
|
|
||||||
{/if}
|
|
||||||
{#if $backups.length > 0}
|
|
||||||
<select value={sourceBackupId}>
|
|
||||||
<option value=""> -- choose snapshot -- </option>
|
|
||||||
{#each $backups as { id, bytes, updated, platform, version, status, message, progress }}
|
|
||||||
{#if status === BackupStatus.FinishedSuccess}
|
|
||||||
<option value={id}>
|
|
||||||
{platform}:{version} ({prettyBytes(bytes)}) - Finished {new Date(updated)}#
|
|
||||||
</option>
|
|
||||||
{/if}
|
|
||||||
{/each}
|
|
||||||
</select>
|
|
||||||
|
|
||||||
<div class="text-center py-5">
|
|
||||||
<div class="text-danger">
|
|
||||||
Notice: Your instance will be placed in maintenance mode and then backed up before
|
|
||||||
restoring the selected snapshot.
|
|
||||||
</div>
|
|
||||||
<button class="btn btn-light" on:click={() => startRestore()} disabled={!sourceBackupId}>
|
|
||||||
<i class="bi bi-safe" /> Restore Now
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
{/if}
|
|
||||||
{/if}
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<style lang="scss">
|
<style lang="scss">
|
||||||
|
@ -140,7 +140,7 @@ open https://pockethost.io
|
|||||||
- [x] fix: more helpful error message when backup fails for nonexistent instance
|
- [x] fix: more helpful error message when backup fails for nonexistent instance
|
||||||
- [x] chore: move version number to base package.json
|
- [x] chore: move version number to base package.json
|
||||||
- [ ] chore: refactor logging and async helpers
|
- [ ] chore: refactor logging and async helpers
|
||||||
- [ ] chore: restore autocancellation
|
- [x] chore: restore autocancellation
|
||||||
- [x] chore: rebuild with go 1.19.3 and include in bin name
|
- [x] chore: rebuild with go 1.19.3 and include in bin name
|
||||||
- [ ] fix: Disallow backups if data dir doesn't exist
|
- [ ] fix: Disallow backups if data dir doesn't exist
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user