mirror of
https://github.com/cloudnative-pg/plugin-barman-cloud.git
synced 2026-01-11 21:23:12 +01:00
feat(wal): parallel WAL archiving (#262)
This patch allows the plugin to archive WAL files in parallel. Fix: #260 Fix: #266 Signed-off-by: MichaluxPL <68371308+MichaluxPL@users.noreply.github.com> Signed-off-by: Leonardo Cecchi <leonardo.cecchi@enterprisedb.com> Signed-off-by: Francesco Canovai <francesco.canovai@enterprisedb.com> Co-authored-by: Leonardo Cecchi <leonardo.cecchi@enterprisedb.com> Co-authored-by: Francesco Canovai <francesco.canovai@enterprisedb.com>
This commit is contained in:
parent
ed1feaaddc
commit
88fd3e504f
@ -21,6 +21,7 @@ spec:
|
|||||||
key: ACCESS_SECRET_KEY
|
key: ACCESS_SECRET_KEY
|
||||||
wal:
|
wal:
|
||||||
compression: gzip
|
compression: gzip
|
||||||
|
maxParallel: 8
|
||||||
data:
|
data:
|
||||||
additionalCommandArgs:
|
additionalCommandArgs:
|
||||||
- "--min-chunk-size=5MB"
|
- "--min-chunk-size=5MB"
|
||||||
|
|||||||
@ -14,6 +14,7 @@ import (
|
|||||||
barmanRestorer "github.com/cloudnative-pg/barman-cloud/pkg/restorer"
|
barmanRestorer "github.com/cloudnative-pg/barman-cloud/pkg/restorer"
|
||||||
cnpgv1 "github.com/cloudnative-pg/cloudnative-pg/api/v1"
|
cnpgv1 "github.com/cloudnative-pg/cloudnative-pg/api/v1"
|
||||||
"github.com/cloudnative-pg/cnpg-i/pkg/wal"
|
"github.com/cloudnative-pg/cnpg-i/pkg/wal"
|
||||||
|
walUtils "github.com/cloudnative-pg/machinery/pkg/fileutils/wals"
|
||||||
"github.com/cloudnative-pg/machinery/pkg/log"
|
"github.com/cloudnative-pg/machinery/pkg/log"
|
||||||
apierrors "k8s.io/apimachinery/pkg/api/errors"
|
apierrors "k8s.io/apimachinery/pkg/api/errors"
|
||||||
"k8s.io/apimachinery/pkg/types"
|
"k8s.io/apimachinery/pkg/types"
|
||||||
@ -24,6 +25,34 @@ import (
|
|||||||
"github.com/cloudnative-pg/plugin-barman-cloud/internal/cnpgi/operator/config"
|
"github.com/cloudnative-pg/plugin-barman-cloud/internal/cnpgi/operator/config"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// ErrMissingPermissions is raised when the sidecar has no
|
||||||
|
// permission to download the credentials needed to reach
|
||||||
|
// the object storage.
|
||||||
|
// This will be fixed by the reconciliation loop in the
|
||||||
|
// operator plugin.
|
||||||
|
var ErrMissingPermissions = fmt.Errorf("no permission to download the backup credentials, retrying")
|
||||||
|
|
||||||
|
// SpoolManagementError is raised when a spool management
|
||||||
|
// error has been detected
|
||||||
|
type SpoolManagementError struct {
|
||||||
|
walName string
|
||||||
|
err error
|
||||||
|
}
|
||||||
|
|
||||||
|
// Error implements the error interface
|
||||||
|
func (e *SpoolManagementError) Error() string {
|
||||||
|
return fmt.Sprintf(
|
||||||
|
"while testing the existence of the WAL file (%s) in the spool directory: %v",
|
||||||
|
e.walName,
|
||||||
|
e.err.Error(),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Unwrap implements the error interface
|
||||||
|
func (e *SpoolManagementError) Unwrap() error {
|
||||||
|
return e.err
|
||||||
|
}
|
||||||
|
|
||||||
// WALServiceImplementation is the implementation of the WAL Service
|
// WALServiceImplementation is the implementation of the WAL Service
|
||||||
type WALServiceImplementation struct {
|
type WALServiceImplementation struct {
|
||||||
wal.UnimplementedWALServer
|
wal.UnimplementedWALServer
|
||||||
@ -67,6 +96,10 @@ func (w WALServiceImplementation) Archive(
|
|||||||
contextLogger := log.FromContext(ctx)
|
contextLogger := log.FromContext(ctx)
|
||||||
contextLogger.Debug("starting wal archive")
|
contextLogger.Debug("starting wal archive")
|
||||||
|
|
||||||
|
baseWalName := path.Base(request.GetSourceFileName())
|
||||||
|
|
||||||
|
// Step 1: parse the configuration and get the environment variables needed
|
||||||
|
// for barman-cloud-wal-archive
|
||||||
configuration, err := config.NewFromClusterJSON(request.ClusterDefinition)
|
configuration, err := config.NewFromClusterJSON(request.ClusterDefinition)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@ -87,7 +120,7 @@ func (w WALServiceImplementation) Archive(
|
|||||||
)
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if apierrors.IsForbidden(err) {
|
if apierrors.IsForbidden(err) {
|
||||||
return nil, errors.New("backup credentials don't yet have access permissions. Will retry reconciliation loop")
|
return nil, ErrMissingPermissions
|
||||||
}
|
}
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -103,12 +136,48 @@ func (w WALServiceImplementation) Archive(
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Step 2: check if this WAL file has not been already archived
|
||||||
|
var isDeletedFromSpool bool
|
||||||
|
isDeletedFromSpool, err = arch.DeleteFromSpool(baseWalName)
|
||||||
|
if err != nil {
|
||||||
|
return nil, &SpoolManagementError{
|
||||||
|
walName: baseWalName,
|
||||||
|
err: err,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if isDeletedFromSpool {
|
||||||
|
contextLogger.Info("WAL file already archived, skipping",
|
||||||
|
"walName", baseWalName)
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Step 3: gather the WAL files names to archive
|
||||||
options, err := arch.BarmanCloudWalArchiveOptions(ctx, &objectStore.Spec.Configuration, configuration.ServerName)
|
options, err := arch.BarmanCloudWalArchiveOptions(ctx, &objectStore.Spec.Configuration, configuration.ServerName)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
walList := arch.GatherWALFilesToArchive(ctx, request.GetSourceFileName(), 1)
|
|
||||||
result := arch.ArchiveList(ctx, walList, options)
|
maxParallel := 1
|
||||||
|
if objectStore.Spec.Configuration.Wal != nil && objectStore.Spec.Configuration.Wal.MaxParallel > 0 {
|
||||||
|
maxParallel = objectStore.Spec.Configuration.Wal.MaxParallel
|
||||||
|
}
|
||||||
|
|
||||||
|
maxResults := maxParallel - 1
|
||||||
|
walFilesList := walUtils.GatherReadyWALFiles(
|
||||||
|
ctx,
|
||||||
|
walUtils.GatherReadyWALFilesConfig{
|
||||||
|
MaxResults: maxResults,
|
||||||
|
SkipWALs: []string{baseWalName},
|
||||||
|
PgDataPath: w.PGDataPath,
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
|
// Ensure the requested WAL file is always the first one being
|
||||||
|
// archived
|
||||||
|
walFilesList.Ready = append([]string{request.GetSourceFileName()}, walFilesList.Ready...)
|
||||||
|
contextLogger.Debug("WAL files to archive", "walFilesListReady", walFilesList.Ready)
|
||||||
|
|
||||||
|
result := arch.ArchiveList(ctx, walFilesList.ReadyItemsToSlice(), options)
|
||||||
for _, archiverResult := range result {
|
for _, archiverResult := range result {
|
||||||
if archiverResult.Err != nil {
|
if archiverResult.Err != nil {
|
||||||
return nil, archiverResult.Err
|
return nil, archiverResult.Err
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user