mirror of
https://github.com/gotenberg/gotenberg.git
synced 2026-08-16 12:22:17 +01:00
feat(exiftool): refactor read write metadata
This commit is contained in:
@@ -3,6 +3,7 @@ package pdfengines
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"sync"
|
||||
|
||||
"go.uber.org/multierr"
|
||||
"go.uber.org/zap"
|
||||
@@ -70,36 +71,49 @@ func (multi *multiPdfEngines) Convert(ctx context.Context, logger *zap.Logger, f
|
||||
return fmt.Errorf("convert PDF to '%+v' with multi PDF engines: %w", formats, err)
|
||||
}
|
||||
|
||||
func (multi *multiPdfEngines) ReadMetadata(ctx context.Context, logger *zap.Logger, inputPaths string, metadata map[string]interface{}) error {
|
||||
type readMetadataResult struct {
|
||||
metadata map[string]interface{}
|
||||
err error
|
||||
}
|
||||
|
||||
func (multi *multiPdfEngines) ReadMetadata(ctx context.Context, logger *zap.Logger, inputPath string) (map[string]interface{}, error) {
|
||||
var err error
|
||||
errChan := make(chan error, 1)
|
||||
var mu sync.Mutex // to safely append errors.
|
||||
|
||||
resultChan := make(chan readMetadataResult, len(multi.engines))
|
||||
|
||||
for _, engine := range multi.engines {
|
||||
go func(engine gotenberg.PdfEngine) {
|
||||
errChan <- engine.ReadMetadata(ctx, logger, inputPaths, metadata)
|
||||
metadata, err := engine.ReadMetadata(ctx, logger, inputPath)
|
||||
resultChan <- readMetadataResult{metadata: metadata, err: err}
|
||||
}(engine)
|
||||
}
|
||||
|
||||
for range multi.engines {
|
||||
select {
|
||||
case readMetadataErr := <-errChan:
|
||||
errored := multierr.AppendInto(&err, readMetadataErr)
|
||||
if !errored {
|
||||
return nil
|
||||
case result := <-resultChan:
|
||||
if result.err != nil {
|
||||
mu.Lock()
|
||||
err = multierr.Append(err, result.err)
|
||||
mu.Unlock()
|
||||
} else {
|
||||
return result.metadata, nil
|
||||
}
|
||||
case <-ctx.Done():
|
||||
return ctx.Err()
|
||||
return nil, ctx.Err()
|
||||
}
|
||||
}
|
||||
|
||||
return fmt.Errorf("read PDF metadata with multi PDF engines: %w", err)
|
||||
return nil, fmt.Errorf("read PDF metadata with multi PDF engines: %w", err)
|
||||
}
|
||||
|
||||
func (multi *multiPdfEngines) WriteMetadata(ctx context.Context, logger *zap.Logger, inputPaths string, newMetadata map[string]interface{}) error {
|
||||
func (multi *multiPdfEngines) WriteMetadata(ctx context.Context, logger *zap.Logger, metadata map[string]interface{}, inputPath string) error {
|
||||
var err error
|
||||
errChan := make(chan error, 1)
|
||||
|
||||
for _, engine := range multi.engines {
|
||||
go func(engine gotenberg.PdfEngine) {
|
||||
errChan <- engine.WriteMetadata(ctx, logger, inputPaths, newMetadata)
|
||||
errChan <- engine.WriteMetadata(ctx, logger, metadata, inputPath)
|
||||
}(engine)
|
||||
|
||||
select {
|
||||
|
||||
@@ -189,8 +189,8 @@ func TestMultiPdfEngines_ReadMetadata(t *testing.T) {
|
||||
scenario: "nominal behavior",
|
||||
engine: newMultiPdfEngines(
|
||||
&gotenberg.PdfEngineMock{
|
||||
ReadMetadataMock: func(ctx context.Context, logger *zap.Logger, inputPath string, metadata map[string]interface{}) error {
|
||||
return nil
|
||||
ReadMetadataMock: func(ctx context.Context, logger *zap.Logger, inputPath string) (map[string]interface{}, error) {
|
||||
return make(map[string]interface{}), nil
|
||||
},
|
||||
},
|
||||
),
|
||||
@@ -200,13 +200,13 @@ func TestMultiPdfEngines_ReadMetadata(t *testing.T) {
|
||||
scenario: "at least one engine does not return an error",
|
||||
engine: newMultiPdfEngines(
|
||||
&gotenberg.PdfEngineMock{
|
||||
ReadMetadataMock: func(ctx context.Context, logger *zap.Logger, inputPath string, metadata map[string]interface{}) error {
|
||||
return errors.New("foo")
|
||||
ReadMetadataMock: func(ctx context.Context, logger *zap.Logger, inputPath string) (map[string]interface{}, error) {
|
||||
return nil, errors.New("foo")
|
||||
},
|
||||
},
|
||||
&gotenberg.PdfEngineMock{
|
||||
ReadMetadataMock: func(ctx context.Context, logger *zap.Logger, inputPath string, metadata map[string]interface{}) error {
|
||||
return nil
|
||||
ReadMetadataMock: func(ctx context.Context, logger *zap.Logger, inputPath string) (map[string]interface{}, error) {
|
||||
return make(map[string]interface{}), nil
|
||||
},
|
||||
},
|
||||
),
|
||||
@@ -216,13 +216,13 @@ func TestMultiPdfEngines_ReadMetadata(t *testing.T) {
|
||||
scenario: "all engines return an error",
|
||||
engine: newMultiPdfEngines(
|
||||
&gotenberg.PdfEngineMock{
|
||||
ReadMetadataMock: func(ctx context.Context, logger *zap.Logger, inputPath string, metadata map[string]interface{}) error {
|
||||
return errors.New("foo")
|
||||
ReadMetadataMock: func(ctx context.Context, logger *zap.Logger, inputPath string) (map[string]interface{}, error) {
|
||||
return nil, errors.New("foo")
|
||||
},
|
||||
},
|
||||
&gotenberg.PdfEngineMock{
|
||||
ReadMetadataMock: func(ctx context.Context, logger *zap.Logger, inputPath string, metadata map[string]interface{}) error {
|
||||
return errors.New("foo")
|
||||
ReadMetadataMock: func(ctx context.Context, logger *zap.Logger, inputPath string) (map[string]interface{}, error) {
|
||||
return nil, errors.New("foo")
|
||||
},
|
||||
},
|
||||
),
|
||||
@@ -233,8 +233,8 @@ func TestMultiPdfEngines_ReadMetadata(t *testing.T) {
|
||||
scenario: "context expired",
|
||||
engine: newMultiPdfEngines(
|
||||
&gotenberg.PdfEngineMock{
|
||||
ReadMetadataMock: func(ctx context.Context, logger *zap.Logger, inputPath string, metadata map[string]interface{}) error {
|
||||
return nil
|
||||
ReadMetadataMock: func(ctx context.Context, logger *zap.Logger, inputPath string) (map[string]interface{}, error) {
|
||||
return make(map[string]interface{}), nil
|
||||
},
|
||||
},
|
||||
),
|
||||
@@ -248,7 +248,7 @@ func TestMultiPdfEngines_ReadMetadata(t *testing.T) {
|
||||
},
|
||||
} {
|
||||
t.Run(tc.scenario, func(t *testing.T) {
|
||||
err := tc.engine.ReadMetadata(tc.ctx, zap.NewNop(), "", nil)
|
||||
_, err := tc.engine.ReadMetadata(tc.ctx, zap.NewNop(), "")
|
||||
|
||||
if !tc.expectError && err != nil {
|
||||
t.Fatalf("expected no error but got: %v", err)
|
||||
@@ -272,7 +272,7 @@ func TestMultiPdfEngines_WriteMetadata(t *testing.T) {
|
||||
scenario: "nominal behavior",
|
||||
engine: newMultiPdfEngines(
|
||||
&gotenberg.PdfEngineMock{
|
||||
WriteMetadataMock: func(ctx context.Context, logger *zap.Logger, inputPath string, newMetadata map[string]interface{}) error {
|
||||
WriteMetadataMock: func(ctx context.Context, logger *zap.Logger, metadata map[string]interface{}, inputPath string) error {
|
||||
return nil
|
||||
},
|
||||
},
|
||||
@@ -283,12 +283,12 @@ func TestMultiPdfEngines_WriteMetadata(t *testing.T) {
|
||||
scenario: "at least one engine does not return an error",
|
||||
engine: newMultiPdfEngines(
|
||||
&gotenberg.PdfEngineMock{
|
||||
WriteMetadataMock: func(ctx context.Context, logger *zap.Logger, inputPath string, newMetadata map[string]interface{}) error {
|
||||
WriteMetadataMock: func(ctx context.Context, logger *zap.Logger, metadata map[string]interface{}, inputPath string) error {
|
||||
return errors.New("foo")
|
||||
},
|
||||
},
|
||||
&gotenberg.PdfEngineMock{
|
||||
WriteMetadataMock: func(ctx context.Context, logger *zap.Logger, inputPath string, newMetadata map[string]interface{}) error {
|
||||
WriteMetadataMock: func(ctx context.Context, logger *zap.Logger, metadata map[string]interface{}, inputPath string) error {
|
||||
return nil
|
||||
},
|
||||
},
|
||||
@@ -299,12 +299,12 @@ func TestMultiPdfEngines_WriteMetadata(t *testing.T) {
|
||||
scenario: "all engines return an error",
|
||||
engine: newMultiPdfEngines(
|
||||
&gotenberg.PdfEngineMock{
|
||||
WriteMetadataMock: func(ctx context.Context, logger *zap.Logger, inputPath string, newMetadata map[string]interface{}) error {
|
||||
WriteMetadataMock: func(ctx context.Context, logger *zap.Logger, metadata map[string]interface{}, inputPath string) error {
|
||||
return errors.New("foo")
|
||||
},
|
||||
},
|
||||
&gotenberg.PdfEngineMock{
|
||||
WriteMetadataMock: func(ctx context.Context, logger *zap.Logger, inputPath string, newMetadata map[string]interface{}) error {
|
||||
WriteMetadataMock: func(ctx context.Context, logger *zap.Logger, metadata map[string]interface{}, inputPath string) error {
|
||||
return errors.New("foo")
|
||||
},
|
||||
},
|
||||
@@ -316,7 +316,7 @@ func TestMultiPdfEngines_WriteMetadata(t *testing.T) {
|
||||
scenario: "context expired",
|
||||
engine: newMultiPdfEngines(
|
||||
&gotenberg.PdfEngineMock{
|
||||
WriteMetadataMock: func(ctx context.Context, logger *zap.Logger, inputPath string, newMetadata map[string]interface{}) error {
|
||||
WriteMetadataMock: func(ctx context.Context, logger *zap.Logger, metadata map[string]interface{}, inputPath string) error {
|
||||
return nil
|
||||
},
|
||||
},
|
||||
@@ -331,7 +331,7 @@ func TestMultiPdfEngines_WriteMetadata(t *testing.T) {
|
||||
},
|
||||
} {
|
||||
t.Run(tc.scenario, func(t *testing.T) {
|
||||
err := tc.engine.WriteMetadata(tc.ctx, zap.NewNop(), "", nil)
|
||||
err := tc.engine.WriteMetadata(tc.ctx, zap.NewNop(), nil, "")
|
||||
|
||||
if !tc.expectError && err != nil {
|
||||
t.Fatalf("expected no error but got: %v", err)
|
||||
|
||||
Reference in New Issue
Block a user