@@ -27,6 +27,20 @@ func (b *BinlogSyncer) StartBackup(backupDir string, p mysql.Position, timeout t
27
27
}
28
28
}
29
29
30
+ func (b * BinlogSyncer ) StartBackupGTID (backupDir string , gset mysql.GTIDSet , timeout time.Duration ) error {
31
+ err := os .MkdirAll (backupDir , 0o755 )
32
+ if err != nil {
33
+ return errors .Trace (err )
34
+ }
35
+ if b .cfg .SynchronousEventHandler == nil {
36
+ return b .StartBackupWithHandlerAndGTID (gset , timeout , func (filename string ) (io.WriteCloser , error ) {
37
+ return os .OpenFile (path .Join (backupDir , filename ), os .O_CREATE | os .O_WRONLY , 0o644 )
38
+ })
39
+ } else {
40
+ return b .StartSynchronousBackupWithGTID (gset , timeout )
41
+ }
42
+ }
43
+
30
44
// StartBackupWithHandler starts the backup process for the binary log using the specified position and handler.
31
45
// The process will continue until the timeout is reached or an error occurs.
32
46
// This method should not be used together with SynchronousEventHandler.
@@ -54,52 +68,72 @@ func (b *BinlogSyncer) StartBackupWithHandler(p mysql.Position, timeout time.Dur
54
68
backupHandler := & BackupEventHandler {
55
69
handler : handler ,
56
70
}
57
-
58
71
s , err := b .StartSync (p )
59
72
if err != nil {
60
73
return errors .Trace (err )
61
74
}
75
+ return processWithHandler (b , s , backupHandler , timeout )
76
+ }
62
77
63
- defer func () {
64
- if backupHandler .w != nil {
65
- closeErr := backupHandler .w .Close ()
66
- if retErr == nil {
67
- retErr = closeErr
68
- }
69
- }
70
- }()
78
+ // StartBackupWithHandlerAndGTID starts the backup process for the binary log using the specified GTID set and handler.
79
+ // - gset: The GTID set from which to begin the backup.
80
+ // - timeout: The maximum duration to wait for new binlog events before stopping the backup process.
81
+ // If set to 0, a default very long timeout (30 days) is used instead.
82
+ // - handler: A function that takes a binlog filename and returns an WriteCloser for writing raw events to.
83
+ func (b * BinlogSyncer ) StartBackupWithHandlerAndGTID (gset mysql.GTIDSet , timeout time.Duration ,
84
+ handler func (binlogFilename string ) (io.WriteCloser , error ),
85
+ ) (retErr error ) {
86
+ if timeout == 0 {
87
+ // a very long timeout here
88
+ timeout = 30 * 3600 * 24 * time .Second
89
+ }
90
+ if b .cfg .SynchronousEventHandler != nil {
91
+ return errors .New ("StartBackupWithHandlerAndGTID cannot be used when SynchronousEventHandler is set. Use StartSynchronousBackupWithGTID instead." )
92
+ }
71
93
72
- ctx , cancel := context . WithTimeout ( context . Background (), timeout )
73
- defer cancel ( )
94
+ // Force use raw mode
95
+ b . parser . SetRawMode ( true )
74
96
75
- for {
76
- select {
77
- case <- ctx .Done ():
78
- return nil
79
- case <- b .ctx .Done ():
80
- return nil
81
- case err := <- s .ech :
82
- return errors .Trace (err )
83
- case e := <- s .ch :
84
- err = backupHandler .HandleEvent (e )
85
- if err != nil {
86
- return errors .Trace (err )
87
- }
88
- }
97
+ // Set up the backup event handler
98
+ backupHandler := & BackupEventHandler {
99
+ handler : handler ,
100
+ }
101
+
102
+ s , err := b .StartSyncGTID (gset )
103
+ if err != nil {
104
+ return errors .Trace (err )
89
105
}
106
+ return processWithHandler (b , s , backupHandler , timeout )
90
107
}
91
108
92
109
// StartSynchronousBackup starts the backup process using the SynchronousEventHandler in the BinlogSyncerConfig.
93
110
func (b * BinlogSyncer ) StartSynchronousBackup (p mysql.Position , timeout time.Duration ) error {
94
111
if b .cfg .SynchronousEventHandler == nil {
95
112
return errors .New ("SynchronousEventHandler must be set in BinlogSyncerConfig to use StartSynchronousBackup" )
96
113
}
97
-
98
114
s , err := b .StartSync (p )
99
115
if err != nil {
100
116
return errors .Trace (err )
101
117
}
102
118
119
+ return process (b , s , timeout )
120
+ }
121
+
122
+ // StartSynchronousBackupWithGTID starts the backup process using the SynchronousEventHandler in the BinlogSyncerConfig with a specified GTID set.
123
+ func (b * BinlogSyncer ) StartSynchronousBackupWithGTID (gset mysql.GTIDSet , timeout time.Duration ) error {
124
+ if b .cfg .SynchronousEventHandler == nil {
125
+ return errors .New ("SynchronousEventHandler must be set in BinlogSyncerConfig to use StartSynchronousBackupWithGTID" )
126
+ }
127
+
128
+ s , err := b .StartSyncGTID (gset )
129
+ if err != nil {
130
+ return errors .Trace (err )
131
+ }
132
+
133
+ return process (b , s , timeout )
134
+ }
135
+
136
+ func process (b * BinlogSyncer , s * BinlogStreamer , timeout time.Duration ) error {
103
137
var ctx context.Context
104
138
var cancel context.CancelFunc
105
139
@@ -123,6 +157,35 @@ func (b *BinlogSyncer) StartSynchronousBackup(p mysql.Position, timeout time.Dur
123
157
}
124
158
}
125
159
160
+ func processWithHandler (b * BinlogSyncer , s * BinlogStreamer , backupHandler * BackupEventHandler , timeout time.Duration ) (retErr error ) {
161
+ defer func () {
162
+ if backupHandler .w != nil {
163
+ closeErr := backupHandler .w .Close ()
164
+ if retErr == nil {
165
+ retErr = closeErr
166
+ }
167
+ }
168
+ }()
169
+ ctx , cancel := context .WithTimeout (context .Background (), timeout )
170
+ defer cancel ()
171
+
172
+ for {
173
+ select {
174
+ case <- ctx .Done ():
175
+ return nil
176
+ case <- b .ctx .Done ():
177
+ return nil
178
+ case err := <- s .ech :
179
+ return errors .Trace (err )
180
+ case e := <- s .ch :
181
+ err := backupHandler .HandleEvent (e )
182
+ if err != nil {
183
+ return errors .Trace (err )
184
+ }
185
+ }
186
+ }
187
+ }
188
+
126
189
// BackupEventHandler handles writing events for backup
127
190
type BackupEventHandler struct {
128
191
handler func (binlogFilename string ) (io.WriteCloser , error )
0 commit comments