You've already forked AstralRinth
forked from didirus/AstralRinth
Support updated servers backup route schema, remove backup locking (#5053)
* Use backup physical_id for progress updates matching * Remove locking * Fmt
This commit is contained in:
committed by
GitHub
parent
2e9730ea1f
commit
7eb1b38cc7
@@ -790,7 +790,7 @@ const handleBackupProgress = (data: Archon.Websocket.v0.WSBackupProgressEvent) =
|
|||||||
'list',
|
'list',
|
||||||
serverId,
|
serverId,
|
||||||
])
|
])
|
||||||
const backup = backupData?.find((b) => b.id === backupId)
|
const backup = backupData?.find((b) => (b.physical_id ?? b.id) === backupId)
|
||||||
|
|
||||||
if (backup?.ongoing && attempt < 3) {
|
if (backup?.ongoing && attempt < 3) {
|
||||||
// retry 3 times max, archon is slow compared to ws state
|
// retry 3 times max, archon is slow compared to ws state
|
||||||
|
|||||||
@@ -52,24 +52,6 @@ export class ArchonBackupsV0Module extends AbstractModule {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
/** POST /modrinth/v0/servers/:server_id/backups/:backup_id/lock */
|
|
||||||
public async lock(serverId: string, backupId: string): Promise<void> {
|
|
||||||
await this.client.request<void>(`/servers/${serverId}/backups/${backupId}/lock`, {
|
|
||||||
api: 'archon',
|
|
||||||
version: 'modrinth/v0',
|
|
||||||
method: 'POST',
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
/** POST /modrinth/v0/servers/:server_id/backups/:backup_id/unlock */
|
|
||||||
public async unlock(serverId: string, backupId: string): Promise<void> {
|
|
||||||
await this.client.request<void>(`/servers/${serverId}/backups/${backupId}/unlock`, {
|
|
||||||
api: 'archon',
|
|
||||||
version: 'modrinth/v0',
|
|
||||||
method: 'POST',
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
/** POST /modrinth/v0/servers/:server_id/backups/:backup_id/retry */
|
/** POST /modrinth/v0/servers/:server_id/backups/:backup_id/retry */
|
||||||
public async retry(serverId: string, backupId: string): Promise<void> {
|
public async retry(serverId: string, backupId: string): Promise<void> {
|
||||||
await this.client.request<void>(`/servers/${serverId}/backups/${backupId}/retry`, {
|
await this.client.request<void>(`/servers/${serverId}/backups/${backupId}/retry`, {
|
||||||
|
|||||||
@@ -76,32 +76,6 @@ export class ArchonBackupsV1Module extends AbstractModule {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
/** POST /v1/:server_id/worlds/:world_id/backups/:backup_id/lock */
|
|
||||||
public async lock(
|
|
||||||
serverId: string,
|
|
||||||
backupId: string,
|
|
||||||
worldId: string = DEFAULT_WORLD_ID,
|
|
||||||
): Promise<void> {
|
|
||||||
await this.client.request<void>(`/${serverId}/worlds/${worldId}/backups/${backupId}/lock`, {
|
|
||||||
api: 'archon',
|
|
||||||
version: 1,
|
|
||||||
method: 'POST',
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
/** POST /v1/:server_id/worlds/:world_id/backups/:backup_id/unlock */
|
|
||||||
public async unlock(
|
|
||||||
serverId: string,
|
|
||||||
backupId: string,
|
|
||||||
worldId: string = DEFAULT_WORLD_ID,
|
|
||||||
): Promise<void> {
|
|
||||||
await this.client.request<void>(`/${serverId}/worlds/${worldId}/backups/${backupId}/unlock`, {
|
|
||||||
api: 'archon',
|
|
||||||
version: 1,
|
|
||||||
method: 'POST',
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
/** POST /v1/:server_id/worlds/:world_id/backups/:backup_id/retry */
|
/** POST /v1/:server_id/worlds/:world_id/backups/:backup_id/retry */
|
||||||
public async retry(
|
public async retry(
|
||||||
serverId: string,
|
serverId: string,
|
||||||
|
|||||||
@@ -174,9 +174,9 @@ export namespace Archon {
|
|||||||
|
|
||||||
export type Backup = {
|
export type Backup = {
|
||||||
id: string
|
id: string
|
||||||
|
physical_id?: string
|
||||||
name: string
|
name: string
|
||||||
created_at: string
|
created_at: string
|
||||||
locked: boolean
|
|
||||||
automated: boolean
|
automated: boolean
|
||||||
interrupted: boolean
|
interrupted: boolean
|
||||||
ongoing: boolean
|
ongoing: boolean
|
||||||
|
|||||||
@@ -4,11 +4,8 @@ import {
|
|||||||
ClockIcon,
|
ClockIcon,
|
||||||
DownloadIcon,
|
DownloadIcon,
|
||||||
EditIcon,
|
EditIcon,
|
||||||
// LockIcon,
|
|
||||||
// LockOpenIcon,
|
|
||||||
MoreVerticalIcon,
|
MoreVerticalIcon,
|
||||||
RotateCounterClockwiseIcon,
|
RotateCounterClockwiseIcon,
|
||||||
// ShieldIcon,
|
|
||||||
TrashIcon,
|
TrashIcon,
|
||||||
UserRoundIcon,
|
UserRoundIcon,
|
||||||
XIcon,
|
XIcon,
|
||||||
@@ -25,7 +22,6 @@ import ProgressBar from '../../base/ProgressBar.vue'
|
|||||||
const { formatMessage } = useVIntl()
|
const { formatMessage } = useVIntl()
|
||||||
|
|
||||||
const emit = defineEmits<{
|
const emit = defineEmits<{
|
||||||
// TODO: Re-add 'lock' when lock functionality is implemented
|
|
||||||
(e: 'download' | 'rename' | 'restore' | 'retry'): void
|
(e: 'download' | 'rename' | 'restore' | 'retry'): void
|
||||||
(e: 'delete', skipConfirmation?: boolean): void
|
(e: 'delete', skipConfirmation?: boolean): void
|
||||||
}>()
|
}>()
|
||||||
@@ -94,8 +90,6 @@ const failedToRestore = computed(() => props.backup.task?.restore?.state === 'fa
|
|||||||
|
|
||||||
const backupIcon = computed(() => {
|
const backupIcon = computed(() => {
|
||||||
if (props.backup.automated) {
|
if (props.backup.automated) {
|
||||||
// TODO: Re-add locked icon when lock functionality is implemented
|
|
||||||
// return props.backup.locked ? ShieldIcon : ClockIcon
|
|
||||||
return ClockIcon
|
return ClockIcon
|
||||||
}
|
}
|
||||||
return UserRoundIcon
|
return UserRoundIcon
|
||||||
@@ -115,8 +109,6 @@ const overflowMenuOptions = computed<OverflowOption[]>(() => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
options.push({ id: 'rename', action: () => emit('rename') })
|
options.push({ id: 'rename', action: () => emit('rename') })
|
||||||
// TODO: Re-add when lock functionality is implemented
|
|
||||||
// options.push({ id: 'lock', action: () => emit('lock') })
|
|
||||||
|
|
||||||
// Delete only available when not creating (has separate Cancel button)
|
// Delete only available when not creating (has separate Cancel button)
|
||||||
if (!creating.value) {
|
if (!creating.value) {
|
||||||
@@ -139,19 +131,6 @@ const overflowMenuOptions = computed<OverflowOption[]>(() => {
|
|||||||
// }
|
// }
|
||||||
|
|
||||||
const messages = defineMessages({
|
const messages = defineMessages({
|
||||||
// TODO: Re-add when lock functionality is implemented
|
|
||||||
// locked: {
|
|
||||||
// id: 'servers.backups.item.locked',
|
|
||||||
// defaultMessage: 'Locked',
|
|
||||||
// },
|
|
||||||
// lock: {
|
|
||||||
// id: 'servers.backups.item.lock',
|
|
||||||
// defaultMessage: 'Lock',
|
|
||||||
// },
|
|
||||||
// unlock: {
|
|
||||||
// id: 'servers.backups.item.unlock',
|
|
||||||
// defaultMessage: 'Unlock',
|
|
||||||
// },
|
|
||||||
restore: {
|
restore: {
|
||||||
id: 'servers.backups.item.restore',
|
id: 'servers.backups.item.restore',
|
||||||
defaultMessage: 'Restore',
|
defaultMessage: 'Restore',
|
||||||
@@ -223,10 +202,6 @@ const messages = defineMessages({
|
|||||||
>
|
>
|
||||||
{{ formatMessage(messages.auto) }}
|
{{ formatMessage(messages.auto) }}
|
||||||
</span>
|
</span>
|
||||||
<!-- TODO: Re-add when lock functionality is implemented -->
|
|
||||||
<!-- <span v-if="backup.locked" class="flex items-center gap-1 text-sm text-secondary">
|
|
||||||
<LockIcon class="size-4" />
|
|
||||||
</span> -->
|
|
||||||
</div>
|
</div>
|
||||||
<div class="flex items-center gap-1.5 text-sm text-secondary">
|
<div class="flex items-center gap-1.5 text-sm text-secondary">
|
||||||
<template v-if="failedToCreate || failedToRestore">
|
<template v-if="failedToCreate || failedToRestore">
|
||||||
@@ -317,13 +292,6 @@ const messages = defineMessages({
|
|||||||
<template #rename>
|
<template #rename>
|
||||||
<EditIcon class="size-5" /> {{ formatMessage(messages.rename) }}
|
<EditIcon class="size-5" /> {{ formatMessage(messages.rename) }}
|
||||||
</template>
|
</template>
|
||||||
<!-- TODO: Re-add when lock functionality is implemented -->
|
|
||||||
<!-- <template v-if="backup.locked" #lock>
|
|
||||||
<LockOpenIcon class="size-5" /> {{ formatMessage(messages.unlock) }}
|
|
||||||
</template>
|
|
||||||
<template v-else #lock>
|
|
||||||
<LockIcon class="size-5" /> {{ formatMessage(messages.lock) }}
|
|
||||||
</template> -->
|
|
||||||
</OverflowMenu>
|
</OverflowMenu>
|
||||||
</ButtonStyled>
|
</ButtonStyled>
|
||||||
</template>
|
</template>
|
||||||
@@ -348,13 +316,6 @@ const messages = defineMessages({
|
|||||||
<template #rename>
|
<template #rename>
|
||||||
<EditIcon class="size-5" /> {{ formatMessage(messages.rename) }}
|
<EditIcon class="size-5" /> {{ formatMessage(messages.rename) }}
|
||||||
</template>
|
</template>
|
||||||
<!-- TODO: Re-add when lock functionality is implemented -->
|
|
||||||
<!-- <template v-if="backup.locked" #lock>
|
|
||||||
<LockOpenIcon class="size-5" /> {{ formatMessage(messages.unlock) }}
|
|
||||||
</template>
|
|
||||||
<template v-else #lock>
|
|
||||||
<LockIcon class="size-5" /> {{ formatMessage(messages.lock) }}
|
|
||||||
</template> -->
|
|
||||||
<template #delete>
|
<template #delete>
|
||||||
<TrashIcon class="size-5" /> {{ formatMessage(commonMessages.deleteLabel) }}
|
<TrashIcon class="size-5" /> {{ formatMessage(commonMessages.deleteLabel) }}
|
||||||
</template>
|
</template>
|
||||||
|
|||||||
@@ -87,7 +87,7 @@ const restoreBackup = () => {
|
|||||||
restoreMutation.mutate(currentBackup.value.id, {
|
restoreMutation.mutate(currentBackup.value.id, {
|
||||||
onSuccess: () => {
|
onSuccess: () => {
|
||||||
// Optimistically update backupsState to show restore in progress immediately
|
// Optimistically update backupsState to show restore in progress immediately
|
||||||
ctx.backupsState.set(currentBackup.value!.id, {
|
ctx.backupsState.set(currentBackup.value!.physical_id ?? currentBackup.value!.id, {
|
||||||
restore: { progress: 0, state: 'ongoing' },
|
restore: { progress: 0, state: 'ongoing' },
|
||||||
})
|
})
|
||||||
modal.value?.hide()
|
modal.value?.hide()
|
||||||
|
|||||||
@@ -160,15 +160,6 @@
|
|||||||
@download="() => triggerDownloadAnimation()"
|
@download="() => triggerDownloadAnimation()"
|
||||||
@rename="() => renameBackupModal?.show(backup)"
|
@rename="() => renameBackupModal?.show(backup)"
|
||||||
@restore="() => restoreBackupModal?.show(backup)"
|
@restore="() => restoreBackupModal?.show(backup)"
|
||||||
@lock="
|
|
||||||
() => {
|
|
||||||
if (backup.locked) {
|
|
||||||
unlockBackup(backup.id)
|
|
||||||
} else {
|
|
||||||
lockBackup(backup.id)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
"
|
|
||||||
@delete="
|
@delete="
|
||||||
(skipConfirmation?: boolean) =>
|
(skipConfirmation?: boolean) =>
|
||||||
skipConfirmation ? deleteBackup(backup) : deleteBackupModal?.show(backup)
|
skipConfirmation ? deleteBackup(backup) : deleteBackupModal?.show(backup)
|
||||||
@@ -251,24 +242,15 @@ const {
|
|||||||
})
|
})
|
||||||
|
|
||||||
const deleteMutation = useMutation({
|
const deleteMutation = useMutation({
|
||||||
mutationFn: (backupId: string) => client.archon.backups_v0.delete(serverId, backupId),
|
mutationFn: ({ id }: { id: string; physicalId: string }) =>
|
||||||
onSuccess: (_data, backupId) => {
|
client.archon.backups_v0.delete(serverId, id),
|
||||||
markBackupCancelled(backupId)
|
onSuccess: (_data, { physicalId }) => {
|
||||||
backupsState.delete(backupId)
|
markBackupCancelled(physicalId)
|
||||||
|
backupsState.delete(physicalId)
|
||||||
queryClient.invalidateQueries({ queryKey: backupsQueryKey })
|
queryClient.invalidateQueries({ queryKey: backupsQueryKey })
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|
||||||
const lockMutation = useMutation({
|
|
||||||
mutationFn: (backupId: string) => client.archon.backups_v0.lock(serverId, backupId),
|
|
||||||
onSuccess: () => queryClient.invalidateQueries({ queryKey: backupsQueryKey }),
|
|
||||||
})
|
|
||||||
|
|
||||||
const unlockMutation = useMutation({
|
|
||||||
mutationFn: (backupId: string) => client.archon.backups_v0.unlock(serverId, backupId),
|
|
||||||
onSuccess: () => queryClient.invalidateQueries({ queryKey: backupsQueryKey }),
|
|
||||||
})
|
|
||||||
|
|
||||||
const retryMutation = useMutation({
|
const retryMutation = useMutation({
|
||||||
mutationFn: (backupId: string) => client.archon.backups_v0.retry(serverId, backupId),
|
mutationFn: (backupId: string) => client.archon.backups_v0.retry(serverId, backupId),
|
||||||
onSuccess: () => queryClient.invalidateQueries({ queryKey: backupsQueryKey }),
|
onSuccess: () => queryClient.invalidateQueries({ queryKey: backupsQueryKey }),
|
||||||
@@ -278,7 +260,7 @@ const backups = computed(() => {
|
|||||||
if (!backupsData.value) return []
|
if (!backupsData.value) return []
|
||||||
|
|
||||||
const merged = backupsData.value.map((backup) => {
|
const merged = backupsData.value.map((backup) => {
|
||||||
const progressState = backupsState.get(backup.id)
|
const progressState = backupsState.get(backup.physical_id ?? backup.id)
|
||||||
if (progressState) {
|
if (progressState) {
|
||||||
const hasOngoingTask = Object.values(progressState).some((task) => task?.state === 'ongoing')
|
const hasOngoingTask = Object.values(progressState).some((task) => task?.state === 'ongoing')
|
||||||
const hasCompletedTask = Object.values(progressState).some((task) => task?.state === 'done')
|
const hasCompletedTask = Object.values(progressState).some((task) => task?.state === 'done')
|
||||||
@@ -404,22 +386,6 @@ function triggerDownloadAnimation() {
|
|||||||
setTimeout(() => (overTheTopDownloadAnimation.value = false), 500)
|
setTimeout(() => (overTheTopDownloadAnimation.value = false), 500)
|
||||||
}
|
}
|
||||||
|
|
||||||
const lockBackup = (backupId: string) => {
|
|
||||||
lockMutation.mutate(backupId, {
|
|
||||||
onError: (err) => {
|
|
||||||
console.error('Failed to lock backup:', err)
|
|
||||||
},
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
const unlockBackup = (backupId: string) => {
|
|
||||||
unlockMutation.mutate(backupId, {
|
|
||||||
onError: (err) => {
|
|
||||||
console.error('Failed to unlock backup:', err)
|
|
||||||
},
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
const retryBackup = (backupId: string) => {
|
const retryBackup = (backupId: string) => {
|
||||||
retryMutation.mutate(backupId, {
|
retryMutation.mutate(backupId, {
|
||||||
onError: (err) => {
|
onError: (err) => {
|
||||||
@@ -438,16 +404,19 @@ function deleteBackup(backup?: Archon.Backups.v1.Backup) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
deleteMutation.mutate(backup.id, {
|
deleteMutation.mutate(
|
||||||
onError: (err) => {
|
{ id: backup.id, physicalId: backup.physical_id ?? backup.id },
|
||||||
const message = err instanceof Error ? err.message : String(err)
|
{
|
||||||
addNotification({
|
onError: (err) => {
|
||||||
type: 'error',
|
const message = err instanceof Error ? err.message : String(err)
|
||||||
title: 'Error deleting backup',
|
addNotification({
|
||||||
text: message,
|
type: 'error',
|
||||||
})
|
title: 'Error deleting backup',
|
||||||
|
text: message,
|
||||||
|
})
|
||||||
|
},
|
||||||
},
|
},
|
||||||
})
|
)
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|||||||
@@ -2,9 +2,9 @@ import type { WSBackupState, WSBackupTask } from './websocket'
|
|||||||
|
|
||||||
export interface Backup {
|
export interface Backup {
|
||||||
id: string
|
id: string
|
||||||
|
physical_id?: string
|
||||||
name: string
|
name: string
|
||||||
created_at: string
|
created_at: string
|
||||||
locked: boolean
|
|
||||||
automated: boolean
|
automated: boolean
|
||||||
interrupted: boolean
|
interrupted: boolean
|
||||||
ongoing: boolean
|
ongoing: boolean
|
||||||
|
|||||||
Reference in New Issue
Block a user