Skip to content

Commit 01eb998

Browse files
authored
Merge pull request #1263 from jcechace/PBM-1665-pitr-backup-profile-storage
PBM-1665 keep PITR running and prioritize different node for profile backups
2 parents 8925737 + 1f31f29 commit 01eb998

File tree

3 files changed

+57
-15
lines changed

3 files changed

+57
-15
lines changed

cmd/pbm-agent/backup.go

Lines changed: 46 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -93,8 +93,10 @@ func (a *Agent) Backup(ctx context.Context, cmd *ctrl.BackupCmd, opid ctrl.OPID,
9393
}
9494
}
9595

96-
if cmd.Type == defs.LogicalBackup {
97-
// wakeup the slicer to not wait for the tick
96+
if cmd.Type == defs.LogicalBackup && cmd.Profile == "" {
97+
// For backups to the main storage,
98+
// wake up the slicer to not wait for the tick.
99+
// This will slice and pause the main PITR
98100
go a.sliceNow(opid)
99101
}
100102

@@ -156,20 +158,25 @@ func (a *Agent) Backup(ctx context.Context, cmd *ctrl.BackupCmd, opid ctrl.OPID,
156158
// not replset. So an `incremental && not_base` backup should land on
157159
// the agent that made a previous (src) backup.
158160
const srcHostMultiplier = 3.0
159-
var c map[string]float64
161+
c := make(map[string]float64)
160162
if cmd.Type == defs.IncrementalBackup && !cmd.IncrBase {
161163
src, err := backup.LastIncrementalBackup(ctx, a.leadConn)
162164
if err != nil {
163165
// try backup anyway
164166
l.Warning("define source backup: %v", err)
165167
} else {
166-
c = make(map[string]float64)
167168
for _, rs := range src.Replsets {
168169
c[rs.Node] = srcHostMultiplier
169170
}
170171
}
171172
}
172173

174+
// When a logical backup targets an external profile (different storage),
175+
// PITR keeps running. Deprioritize nodes currently running PITR slicer
176+
if cmd.Type == defs.LogicalBackup && cmd.Profile != "" {
177+
c = a.deprioritizePITRNodes(ctx, c, l)
178+
}
179+
173180
agents, err := topo.ListSteadyAgents(ctx, a.leadConn)
174181
if err != nil {
175182
l.Error("get agents list: %v", err)
@@ -267,6 +274,41 @@ func (a *Agent) getValidCandidates(agents []topo.AgentStat, backupType defs.Back
267274
return validCandidates
268275
}
269276

277+
// deprioritizePITRNodes adds low-priority coefficients for nodes currently running PITR slicing.
278+
// It only modifies the coefficient map for nodes not already present (e.g., incremental src host).
279+
// Returns the (possibly modified) coefficient map.
280+
func (a *Agent) deprioritizePITRNodes(
281+
ctx context.Context,
282+
coefficients map[string]float64,
283+
l log.LogEvent,
284+
) map[string]float64 {
285+
pitrLocks, err := lock.GetOpLocks(ctx, a.leadConn, &lock.LockHeader{Type: ctrl.CmdPITR})
286+
if err != nil {
287+
l.Warning("get pitr locks for deprioritization: %v", err)
288+
return coefficients
289+
}
290+
291+
ts, err := topo.GetClusterTime(ctx, a.leadConn)
292+
if err != nil {
293+
l.Warning("get cluster time for pitr deprioritization: %v", err)
294+
return coefficients
295+
}
296+
297+
for i := range pitrLocks {
298+
pl := &pitrLocks[i]
299+
if pl.Heartbeat.T+defs.StaleFrameSec < ts.T {
300+
continue // stale lock, ignore
301+
}
302+
303+
// Only set if not already present (preserve previous priorities)
304+
if _, exists := coefficients[pl.Node]; !exists {
305+
coefficients[pl.Node] = prio.DefaultScore - 0.1
306+
}
307+
}
308+
309+
return coefficients
310+
}
311+
270312
const renominationFrame = 5 * time.Second
271313

272314
func (a *Agent) nominateRS(ctx context.Context, bcp, rs string, nodes [][]string) error {

pbm/prio/priority.go

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,9 @@ import (
99
)
1010

1111
const (
12-
defaultScore = 1.0
13-
scoreForPrimary = defaultScore / 2
14-
scoreForHidden = defaultScore * 2
12+
DefaultScore = 1.0
13+
scoreForPrimary = DefaultScore / 2
14+
scoreForHidden = DefaultScore * 2
1515
scoreForExcluded = 0
1616
)
1717

@@ -114,23 +114,23 @@ func CalcPriorityForNode(node *topo.NodeInfo) float64 {
114114
return scoreForHidden
115115
}
116116

117-
return defaultScore
117+
return DefaultScore
118118
}
119119

120120
// implicitPrioCalc provides priority calculation based on topology rules.
121121
// Instead of using explicitly specified priority numbers, topology rules are
122122
// applied for primary, secondary and hidden member.
123123
func implicitPrioCalc(a *topo.AgentStat, rule map[string]float64) float64 {
124124
if coeff, ok := rule[a.Node]; ok && rule != nil {
125-
return defaultScore * coeff
125+
return DefaultScore * coeff
126126
} else if a.State == defs.NodeStatePrimary {
127127
return scoreForPrimary
128128
} else if a.DelaySecs > 0 {
129129
return scoreForExcluded
130130
} else if a.Hidden {
131131
return scoreForHidden
132132
}
133-
return defaultScore
133+
return DefaultScore
134134
}
135135

136136
// explicitPrioCalc uses priority numbers from configuration to calculate
@@ -139,7 +139,7 @@ func implicitPrioCalc(a *topo.AgentStat, rule map[string]float64) float64 {
139139
func explicitPrioCalc(a *topo.AgentStat, rule map[string]float64) float64 {
140140
sc, ok := rule[a.Node]
141141
if !ok || sc < 0 {
142-
return defaultScore
142+
return DefaultScore
143143
}
144144

145145
return sc

pbm/prio/priority_test.go

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -396,8 +396,8 @@ func TestCalcPriorityForNode(t *testing.T) {
396396
}
397397

398398
p := CalcPriorityForNode(nodeInfo)
399-
if p != defaultScore {
400-
t.Errorf("wrong priority for secondary: want=%v, got=%v", defaultScore, p)
399+
if p != DefaultScore {
400+
t.Errorf("wrong priority for secondary: want=%v, got=%v", DefaultScore, p)
401401
}
402402
})
403403

@@ -470,8 +470,8 @@ func TestImplicitPrioCalc(t *testing.T) {
470470

471471
p := implicitPrioCalc(agentStat, nil)
472472

473-
if p != defaultScore {
474-
t.Errorf("wrong priority for secondary: want=%v, got=%v", defaultScore, p)
473+
if p != DefaultScore {
474+
t.Errorf("wrong priority for secondary: want=%v, got=%v", DefaultScore, p)
475475
}
476476
})
477477

0 commit comments

Comments
 (0)