-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathbackup.go
101 lines (88 loc) · 2.46 KB
/
backup.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
package main
import (
"time"
"github.com/flynn/flynn/pkg/postgres"
"github.com/flynn/flynn/pkg/random"
)
type Backup struct {
AppID string
BackupID string
StartedAt *time.Time
CompletedAt *time.Time
Bytes int64
}
type BackupRepo struct {
db *postgres.DB
}
func NewBackupRepo(db *postgres.DB) (*BackupRepo, error) {
if err := migrate(db); err != nil {
return nil, err
}
return &BackupRepo{db: db}, nil
}
func (r *BackupRepo) NewBackup(appID string) (*Backup, error) {
now := time.Now()
b := &Backup{
AppID: appID,
BackupID: random.UUID(),
StartedAt: &now,
CompletedAt: nil,
Bytes: 0,
}
err := r.db.Exec("INSERT INTO pgbackups (app_id, backup_id, started_at, completed_at, bytes) VALUES ($1, $2, $3, $4, $5)",
b.AppID, b.BackupID, b.StartedAt, nil, 0)
return b, err
}
func (r *BackupRepo) GetBackup(backupID string) (*Backup, error) {
rows, err := r.db.Query("SELECT * FROM pgbackups WHERE backup_id = $1", backupID)
if err != nil {
return nil, err
}
// this scanning is repeated to avoid importing pgx and having
// deployment/godep errors, as flynn uses godep for pgx (known issues)
defer rows.Close()
backups := []*Backup{}
for rows.Next() {
b := &Backup{}
err := rows.Scan(&b.AppID, &b.BackupID, &b.StartedAt, &b.CompletedAt, &b.Bytes)
if err != nil {
rows.Close()
return nil, err
}
backups = append(backups, b)
}
if err != nil || len(backups) == 0 {
return nil, err
}
return backups[0], nil
}
func (r *BackupRepo) GetBackups(appID string) ([]*Backup, error) {
rows, err := r.db.Query("SELECT * FROM pgbackups WHERE app_id = $1 ORDER BY started_at ASC", appID)
if err != nil {
return nil, err
}
// this scanning is repeated to avoid importing pgx and having
// deployment/godep errors, as flynn uses godep for pgx (known issues)
defer rows.Close()
backups := []*Backup{}
for rows.Next() {
b := &Backup{}
err := rows.Scan(&b.AppID, &b.BackupID, &b.StartedAt, &b.CompletedAt, &b.Bytes)
if err != nil {
rows.Close()
return nil, err
}
backups = append(backups, b)
}
return backups, rows.Err()
}
func (r *BackupRepo) CompleteBackup(b *Backup, bytes int64) error {
now := time.Now()
b.CompletedAt = &now
b.Bytes = bytes
err := r.db.Exec("UPDATE pgbackups SET completed_at = $1, bytes = $2 WHERE backup_id = $3", now, b.Bytes, b.BackupID)
return err
}
func (r *BackupRepo) DeleteBackup(b *Backup) error {
return r.db.Exec("DELETE FROM pgbackups WHERE backup_id = $1", b.BackupID)
}