Skip to content

Commit

Permalink
fix: crashing bug on partial backup (#39)
Browse files Browse the repository at this point in the history
  • Loading branch information
garethgeorge authored Dec 23, 2023
1 parent df9e0ae commit fba6c8d
Show file tree
Hide file tree
Showing 7 changed files with 35 additions and 36 deletions.
8 changes: 3 additions & 5 deletions internal/api/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -193,11 +193,9 @@ func (s *Server) GetOperationEvents(ctx context.Context, req *connect.Request[em
return
}

go func() {
if err := resp.Send(event); err != nil {
errorChan <- fmt.Errorf("failed to send event: %w", err)
}
}()
if err := resp.Send(event); err != nil {
errorChan <- fmt.Errorf("failed to send event: %w", err)
}
}
s.oplog.Subscribe(&callback)
defer s.oplog.Unsubscribe(&callback)
Expand Down
8 changes: 3 additions & 5 deletions internal/orchestrator/repo.go
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ func (r *RepoOrchestrator) Backup(ctx context.Context, plan *v1.Plan, progressCa

summary, err := r.repo.Backup(ctx, progressCallback, opts...)
if err != nil {
return nil, fmt.Errorf("failed to backup: %w", err)
return summary, fmt.Errorf("failed to backup: %w", err)
}

r.l.Debug("Backup completed", zap.String("repo", r.repoConfig.Id), zap.Duration("duration", time.Since(startTime)))
Expand Down Expand Up @@ -115,16 +115,12 @@ func (r *RepoOrchestrator) Forget(ctx context.Context, plan *v1.Plan) ([]*v1.Res
return nil, fmt.Errorf("plan %q has no retention policy", plan.Id)
}

l := r.l.With(zap.String("plan", plan.Id))

l.Debug("Forget snapshots", zap.Any("policy", policy))
result, err := r.repo.Forget(
ctx, protoutil.RetentionPolicyFromProto(plan.Retention),
restic.WithFlags("--tag", tagForPlan(plan)), restic.WithFlags("--group-by", "tag"))
if err != nil {
return nil, fmt.Errorf("get snapshots for repo %v: %w", r.repoConfig.Id, err)
}
l.Debug("Forget result", zap.Any("result", result))

var forgotten []*v1.ResticSnapshot
for _, snapshot := range result.Remove {
Expand All @@ -135,6 +131,8 @@ func (r *RepoOrchestrator) Forget(ctx context.Context, plan *v1.Plan) ([]*v1.Res
forgotten = append(forgotten, snapshotProto)
}

zap.L().Debug("Forgot snapshots", zap.String("plan", plan.Id), zap.Int("count", len(forgotten)), zap.Any("policy", policy))

return forgotten, nil
}

Expand Down
4 changes: 2 additions & 2 deletions pkg/restic/restic.go
Original file line number Diff line number Diff line change
Expand Up @@ -137,7 +137,7 @@ func (r *Repo) Backup(ctx context.Context, progressCallback func(*BackupProgress
if err := cmd.Wait(); err != nil {
var exitErr *exec.ExitError
if errors.As(err, &exitErr) {
if exitErr.ExitCode() == 1 {
if exitErr.ExitCode() == 3 {
cmdErr = ErrPartialBackup
} else {
cmdErr = fmt.Errorf("exit code %v: %w", exitErr.ExitCode(), ErrBackupFailed)
Expand All @@ -151,7 +151,7 @@ func (r *Repo) Backup(ctx context.Context, progressCallback func(*BackupProgress
wg.Wait()

if cmdErr != nil || readErr != nil {
return nil, newCmdErrorPreformatted(cmd, output.String(), errors.Join(cmdErr, readErr))
return summary, newCmdErrorPreformatted(cmd, output.String(), errors.Join(cmdErr, readErr))
}

return summary, nil
Expand Down
3 changes: 2 additions & 1 deletion webui/src/components/OperationList.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,8 @@ export const OperationList = ({
size="small"
dataSource={backups}
renderItem={(backup) => {
const ops = backup.operations;
const ops = [...backup.operations];
ops.reverse();
return (
<Card size="small" style={{ margin: "5px" }}>
{ops.map((op) => {
Expand Down
21 changes: 2 additions & 19 deletions webui/src/components/OperationTree.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import React, { useEffect, useMemo, useState } from "react";
import {
BackupInfo,
BackupInfoCollector,
colorForStatus,
displayTypeToString,
getOperations,
getTypeForDisplay,
Expand Down Expand Up @@ -260,27 +261,9 @@ const buildTreeDay = (keyPrefix: string, operations: BackupInfo[]): OpTreeNode[]

const buildTreeLeaf = (operations: BackupInfo[]): OpTreeNode[] => {
const entries = _.map(operations, (b): OpTreeNode => {
let iconColor = "grey";
let iconColor = colorForStatus(b.status);
let icon: React.ReactNode | null = <QuestionOutlined />;

switch (b.status) {
case OperationStatus.STATUS_PENDING:
iconColor = "grey";
break;
case OperationStatus.STATUS_SUCCESS:
iconColor = "green";
break;
case OperationStatus.STATUS_ERROR:
iconColor = "red";
break;
case OperationStatus.STATUS_INPROGRESS:
iconColor = "blue";
break;
case OperationStatus.STATUS_USER_CANCELLED:
iconColor = "orange";
break;
}

if (b.status === OperationStatus.STATUS_ERROR) {
icon = <ExclamationOutlined style={{ color: iconColor }} />;
} else {
Expand Down
22 changes: 21 additions & 1 deletion webui/src/state/oplog.ts
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ export class BackupInfoCollector {
private createBackup(operations: Operation[]): BackupInfo {
// deduplicate and sort operations.
operations.sort((a, b) => {
return Number(b.unixTimeStartMs - a.unixTimeStartMs);
return Number(a.unixTimeStartMs - b.unixTimeStartMs);
});

// use the lowest ID of all operations as the ID of the backup, this will be the first created operation.
Expand Down Expand Up @@ -258,6 +258,26 @@ export const displayTypeToString = (type: DisplayType) => {
return "Unknown";
}
};

export const colorForStatus = (status: OperationStatus) => {
switch (status) {
case OperationStatus.STATUS_PENDING:
return "grey";
case OperationStatus.STATUS_INPROGRESS:
return "blue";
case OperationStatus.STATUS_ERROR:
return "red";
case OperationStatus.STATUS_WARNING:
return "orange";
case OperationStatus.STATUS_SUCCESS:
return "green";
case OperationStatus.STATUS_USER_CANCELLED:
return "orange";
default:
return "grey";
}
}

// detailsForOperation returns derived display information for a given operation.
export const detailsForOperation = (
op: Operation
Expand Down
5 changes: 2 additions & 3 deletions webui/src/views/AddPlanModal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,6 @@ export const AddPlanModal = ({

try {
let config = await fetchConfig();
config.plans = config.plans || [];

if (!template) {
throw new Error("template not found");
Expand Down Expand Up @@ -82,10 +81,9 @@ export const AddPlanModal = ({
setConfirmLoading(true);

try {
let plan = await validateForm<Plan>(form);
let plan = new Plan(await validateForm<Plan>(form));

let config = await fetchConfig();
config.plans = config.plans || [];

// Merge the new plan (or update) into the config
if (template) {
Expand All @@ -103,6 +101,7 @@ export const AddPlanModal = ({
showModal(null);
} catch (e: any) {
alertsApi.error("Operation failed: " + e.message, 15);
console.error(e);
} finally {
setConfirmLoading(false);
}
Expand Down

0 comments on commit fba6c8d

Please sign in to comment.