55 "fmt"
66 "io"
77
8+ ds "github.com/ipfs/go-datastore"
89 badger4 "github.com/ipfs/go-ds-badger4"
910)
1011
@@ -16,28 +17,51 @@ func (s *DefaultStore) Backup(ctx context.Context, writer io.Writer, since uint6
1617 return 0 , err
1718 }
1819
19- // Try to leverage a native backup implementation if the underlying datastore exposes one.
20- type backupable interface {
21- Backup (io.Writer , uint64 ) (uint64 , error )
22- }
23- if dsBackup , ok := s .db .(backupable ); ok {
24- version , err := dsBackup .Backup (writer , since )
25- if err != nil {
26- return 0 , fmt .Errorf ("datastore backup failed: %w" , err )
27- }
28- return version , nil
29- }
30-
31- // Default Badger datastore used across ev-node.
32- badgerDatastore , ok := s .db .(* badger4.Datastore )
20+ visited := make (map [ds.Datastore ]struct {})
21+ current , ok := any (s .db ).(ds.Datastore )
3322 if ! ok {
3423 return 0 , fmt .Errorf ("backup is not supported by the configured datastore" )
3524 }
3625
37- // `badger.DB.Backup` internally orchestrates a consistent snapshot without pausing writes.
38- version , err := badgerDatastore .DB .Backup (writer , since )
39- if err != nil {
40- return 0 , fmt .Errorf ("badger backup failed: %w" , err )
26+ for {
27+ // Try to leverage a native backup implementation if the underlying datastore exposes one.
28+ type backupable interface {
29+ Backup (io.Writer , uint64 ) (uint64 , error )
30+ }
31+ if dsBackup , ok := current .(backupable ); ok {
32+ version , err := dsBackup .Backup (writer , since )
33+ if err != nil {
34+ return 0 , fmt .Errorf ("datastore backup failed: %w" , err )
35+ }
36+ return version , nil
37+ }
38+
39+ // Default Badger datastore used across ev-node.
40+ if badgerDatastore , ok := current .(* badger4.Datastore ); ok {
41+ // `badger.DB.Backup` internally orchestrates a consistent snapshot without pausing writes.
42+ version , err := badgerDatastore .DB .Backup (writer , since )
43+ if err != nil {
44+ return 0 , fmt .Errorf ("badger backup failed: %w" , err )
45+ }
46+ return version , nil
47+ }
48+
49+ // Attempt to unwrap shimmed datastores (e.g., prefix or mutex wrappers) to reach the backing store.
50+ if _ , seen := visited [current ]; seen {
51+ break
52+ }
53+ visited [current ] = struct {}{}
54+
55+ shim , ok := current .(ds.Shim )
56+ if ! ok {
57+ break
58+ }
59+ children := shim .Children ()
60+ if len (children ) == 0 {
61+ break
62+ }
63+ current = children [0 ]
4164 }
42- return version , nil
65+
66+ return 0 , fmt .Errorf ("backup is not supported by the configured datastore" )
4367}
0 commit comments