@@ -19,6 +19,7 @@ package archiver
1919
2020import (
2121 "os"
22+ "path/filepath"
2223 "strings"
2324
2425 pgbackrestApi "github.com/operasoftware/cnpg-plugin-pgbackrest/internal/pgbackrest/api"
@@ -75,3 +76,157 @@ var _ = Describe("pgbackrestWalArchiveOptions", func() {
7576 ))
7677 })
7778})
79+
80+ var _ = Describe ("GatherWALFilesToArchive" , func () {
81+ var tempPgData string
82+ var archiveStatusDir string
83+ var archiver * WALArchiver
84+
85+ BeforeEach (func (ctx SpecContext ) {
86+ var err error
87+
88+ tempPgData , err = os .MkdirTemp ("" , "pgdata-test-*" )
89+ Expect (err ).ToNot (HaveOccurred ())
90+
91+ // Archiver uses the env variable to determine directory root.
92+ os .Setenv ("PGDATA" , tempPgData )
93+
94+ archiveStatusDir = filepath .Join (tempPgData , "pg_wal" , "archive_status" )
95+ err = os .MkdirAll (archiveStatusDir , 0755 )
96+ Expect (err ).ToNot (HaveOccurred ())
97+
98+ tempEmptyWalArchivePath := filepath .Join (tempPgData , "empty-wal-archive" )
99+ _ , err = os .Create (tempEmptyWalArchivePath )
100+ Expect (err ).ToNot (HaveOccurred ())
101+
102+ archiver , err = New (ctx , nil , filepath .Join (tempPgData , "spool" ), tempPgData , tempEmptyWalArchivePath )
103+ Expect (err ).ToNot (HaveOccurred ())
104+ })
105+
106+ AfterEach (func () {
107+ // Clean up temp directory
108+ if tempPgData != "" {
109+ os .RemoveAll (tempPgData )
110+ }
111+ os .Unsetenv ("PGDATA" )
112+ })
113+
114+ // Helper function to create .ready files
115+ createReadyFile := func (walName string ) {
116+ path := filepath .Join (archiveStatusDir , walName + ".ready" )
117+ err := os .WriteFile (path , []byte {}, 0644 )
118+ Expect (err ).ToNot (HaveOccurred ())
119+ }
120+
121+ Context ("when parallel=1" , func () {
122+ It ("should gather only the requested file" , func (ctx SpecContext ) {
123+ // Create .ready files for multiple WAL files
124+ createReadyFile ("000000010000000000000001" )
125+ createReadyFile ("000000010000000000000002" )
126+ createReadyFile ("000000010000000000000003" )
127+
128+ walList := archiver .GatherWALFilesToArchive (ctx , "pg_wal/000000010000000000000001" , 1 )
129+
130+ Expect (walList ).To (HaveLen (1 ))
131+ Expect (walList [0 ]).To (Equal ("pg_wal/000000010000000000000001" ))
132+ })
133+
134+ It ("should handle when no other .ready files exist" , func (ctx SpecContext ) {
135+ // Only create the requested file
136+ createReadyFile ("000000010000000000000001" )
137+
138+ walList := archiver .GatherWALFilesToArchive (ctx , "pg_wal/000000010000000000000001" , 1 )
139+
140+ Expect (walList ).To (HaveLen (1 ))
141+ Expect (walList [0 ]).To (Equal ("pg_wal/000000010000000000000001" ))
142+ })
143+ })
144+
145+ Context ("when parallel>1" , func () {
146+ It ("should gather multiple files when parallel=4" , func (ctx SpecContext ) {
147+ // Create .ready files for multiple WAL files
148+ createReadyFile ("000000010000000000000001" )
149+ createReadyFile ("000000010000000000000002" )
150+ createReadyFile ("000000010000000000000003" )
151+ createReadyFile ("000000010000000000000004" )
152+
153+ walList := archiver .GatherWALFilesToArchive (ctx , "pg_wal/000000010000000000000001" , 4 )
154+
155+ Expect (walList ).To (HaveLen (4 ))
156+ Expect (walList [0 ]).To (Equal ("pg_wal/000000010000000000000001" ))
157+ })
158+
159+ It ("should not exceed parallel limit even when more files are ready" , func (ctx SpecContext ) {
160+ // Create many .ready files
161+ for i := 1 ; i <= 10 ; i ++ {
162+ createReadyFile ("00000001000000000000000" + string (rune ('0' + i )))
163+ }
164+
165+ walList := archiver .GatherWALFilesToArchive (ctx , "pg_wal/000000010000000000000001" , 3 )
166+
167+ Expect (walList ).To (HaveLen (3 ))
168+ })
169+
170+ It ("should handle when fewer files exist than parallel limit" , func (ctx SpecContext ) {
171+ // Create only 2 .ready files but request parallel=5
172+ createReadyFile ("000000010000000000000001" )
173+ createReadyFile ("000000010000000000000002" )
174+
175+ walList := archiver .GatherWALFilesToArchive (ctx , "pg_wal/000000010000000000000001" , 5 )
176+
177+ // Should only get the files that exist
178+ Expect (walList ).To (HaveLen (2 ))
179+ Expect (walList [0 ]).To (Equal ("pg_wal/000000010000000000000001" ))
180+ })
181+ })
182+
183+ Context ("edge cases" , func () {
184+ It ("should handle empty archive_status directory" , func (ctx SpecContext ) {
185+ // Don't create any .ready files
186+
187+ walList := archiver .GatherWALFilesToArchive (ctx , "pg_wal/000000010000000000000001" , 3 )
188+
189+ // Should still return the requested file
190+ Expect (walList ).To (HaveLen (1 ))
191+ Expect (walList [0 ]).To (Equal ("pg_wal/000000010000000000000001" ))
192+ })
193+
194+ })
195+
196+ Context ("other files in directory" , func () {
197+ It ("should ignore non-.ready files in archive_status" , func (ctx SpecContext ) {
198+ // Create .ready files
199+ createReadyFile ("000000010000000000000001" )
200+ createReadyFile ("000000010000000000000002" )
201+
202+ // Create .done files (should be ignored)
203+ donePath := filepath .Join (archiveStatusDir , "000000010000000000000003.done" )
204+ err := os .WriteFile (donePath , []byte {}, 0644 )
205+ Expect (err ).ToNot (HaveOccurred ())
206+
207+ // Create a random file (should be ignored)
208+ randomPath := filepath .Join (archiveStatusDir , "random.txt" )
209+ err = os .WriteFile (randomPath , []byte {}, 0644 )
210+ Expect (err ).ToNot (HaveOccurred ())
211+
212+ walList := archiver .GatherWALFilesToArchive (ctx , "pg_wal/000000010000000000000001" , 5 )
213+
214+ // Should only get .ready files, not .done or other files
215+ Expect (len (walList )).To (BeNumerically ("<=" , 2 ))
216+ for _ , wal := range walList {
217+ Expect (wal ).NotTo (ContainSubstring ("000000010000000000000003" ))
218+ Expect (wal ).NotTo (ContainSubstring ("random" ))
219+ }
220+ })
221+ It ("should handle timeline history files" , func (ctx SpecContext ) {
222+ // Create timeline history file
223+ createReadyFile ("00000002.history" )
224+ createReadyFile ("000000010000000000000001" )
225+
226+ walList := archiver .GatherWALFilesToArchive (ctx , "pg_wal/00000002.history" , 2 )
227+
228+ Expect (walList ).To (HaveLen (2 ))
229+ Expect (walList [0 ]).To (Equal ("pg_wal/00000002.history" ))
230+ })
231+ })
232+ })
0 commit comments