mirror of
https://github.com/gotenberg/gotenberg.git
synced 2026-08-18 21:22:15 +01:00
feat: handling more ErrMaximumQueueSizeExceeded scenarios
This commit is contained in:
4
Makefile
4
Makefile
@@ -35,6 +35,7 @@ API_ROOT_PATH=/
|
|||||||
API_TRACE_HEADER=Gotenberg-Trace
|
API_TRACE_HEADER=Gotenberg-Trace
|
||||||
API_DISABLE_HEALTH_CHECK_LOGGING=false
|
API_DISABLE_HEALTH_CHECK_LOGGING=false
|
||||||
CHROMIUM_RESTART_AFTER=0
|
CHROMIUM_RESTART_AFTER=0
|
||||||
|
CHROMIUM_MAX_QUEUE_SIZE=0
|
||||||
CHROMIUM_AUTO_START=false
|
CHROMIUM_AUTO_START=false
|
||||||
CHROMIUM_START_TIMEOUT=20s
|
CHROMIUM_START_TIMEOUT=20s
|
||||||
CHROMIUM_INCOGNITO=false
|
CHROMIUM_INCOGNITO=false
|
||||||
@@ -51,6 +52,7 @@ CHROMIUM_CLEAR_COOKIES=false
|
|||||||
CHROMIUM_DISABLE_JAVASCRIPT=false
|
CHROMIUM_DISABLE_JAVASCRIPT=false
|
||||||
CHROMIUM_DISABLE_ROUTES=false
|
CHROMIUM_DISABLE_ROUTES=false
|
||||||
LIBREOFFICE_RESTART_AFTER=10
|
LIBREOFFICE_RESTART_AFTER=10
|
||||||
|
LIBREOFFICE_MAX_QUEUE_SIZE=0
|
||||||
LIBREOFFICE_AUTO_START=false
|
LIBREOFFICE_AUTO_START=false
|
||||||
LIBREOFFICE_START_TIMEOUT=20s
|
LIBREOFFICE_START_TIMEOUT=20s
|
||||||
LIBREOFFICE_DISABLE_ROUTES=false
|
LIBREOFFICE_DISABLE_ROUTES=false
|
||||||
@@ -89,6 +91,7 @@ run: ## Start a Gotenberg container
|
|||||||
--api-disable-health-check-logging=$(API_DISABLE_HEALTH_CHECK_LOGGING) \
|
--api-disable-health-check-logging=$(API_DISABLE_HEALTH_CHECK_LOGGING) \
|
||||||
--chromium-restart-after=$(CHROMIUM_RESTART_AFTER) \
|
--chromium-restart-after=$(CHROMIUM_RESTART_AFTER) \
|
||||||
--chromium-auto-start=$(CHROMIUM_AUTO_START) \
|
--chromium-auto-start=$(CHROMIUM_AUTO_START) \
|
||||||
|
--chromium-max-queue-size=$(CHROMIUM_MAX_QUEUE_SIZE) \
|
||||||
--chromium-start-timeout=$(CHROMIUM_START_TIMEOUT) \
|
--chromium-start-timeout=$(CHROMIUM_START_TIMEOUT) \
|
||||||
--chromium-incognito=$(CHROMIUM_INCOGNITO) \
|
--chromium-incognito=$(CHROMIUM_INCOGNITO) \
|
||||||
--chromium-allow-insecure-localhost=$(CHROMIUM_ALLOW_INSECURE_LOCALHOST) \
|
--chromium-allow-insecure-localhost=$(CHROMIUM_ALLOW_INSECURE_LOCALHOST) \
|
||||||
@@ -104,6 +107,7 @@ run: ## Start a Gotenberg container
|
|||||||
--chromium-disable-javascript=$(CHROMIUM_DISABLE_JAVASCRIPT) \
|
--chromium-disable-javascript=$(CHROMIUM_DISABLE_JAVASCRIPT) \
|
||||||
--chromium-disable-routes=$(CHROMIUM_DISABLE_ROUTES) \
|
--chromium-disable-routes=$(CHROMIUM_DISABLE_ROUTES) \
|
||||||
--libreoffice-restart-after=$(LIBREOFFICE_RESTART_AFTER) \
|
--libreoffice-restart-after=$(LIBREOFFICE_RESTART_AFTER) \
|
||||||
|
--libreoffice-max-queue-size=$(LIBREOFFICE_MAX_QUEUE_SIZE) \
|
||||||
--libreoffice-auto-start=$(LIBREOFFICE_AUTO_START) \
|
--libreoffice-auto-start=$(LIBREOFFICE_AUTO_START) \
|
||||||
--libreoffice-start-timeout=$(LIBREOFFICE_START_TIMEOUT) \
|
--libreoffice-start-timeout=$(LIBREOFFICE_START_TIMEOUT) \
|
||||||
--libreoffice-disable-routes=$(LIBREOFFICE_DISABLE_ROUTES) \
|
--libreoffice-disable-routes=$(LIBREOFFICE_DISABLE_ROUTES) \
|
||||||
|
|||||||
@@ -88,7 +88,7 @@ type processSupervisor struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// NewProcessSupervisor initializes a new [ProcessSupervisor].
|
// NewProcessSupervisor initializes a new [ProcessSupervisor].
|
||||||
func NewProcessSupervisor(logger *zap.Logger, process Process, maxReqLimit int64, maxQueueSize int64) ProcessSupervisor {
|
func NewProcessSupervisor(logger *zap.Logger, process Process, maxReqLimit, maxQueueSize int64) ProcessSupervisor {
|
||||||
b := &processSupervisor{
|
b := &processSupervisor{
|
||||||
logger: logger,
|
logger: logger,
|
||||||
process: process,
|
process: process,
|
||||||
|
|||||||
@@ -280,6 +280,7 @@ func (mod *Chromium) Descriptor() gotenberg.ModuleDescriptor {
|
|||||||
FlagSet: func() *flag.FlagSet {
|
FlagSet: func() *flag.FlagSet {
|
||||||
fs := flag.NewFlagSet("chromium", flag.ExitOnError)
|
fs := flag.NewFlagSet("chromium", flag.ExitOnError)
|
||||||
fs.Int64("chromium-restart-after", 0, "Number of conversions after which Chromium will automatically restart. Set to 0 to disable this feature")
|
fs.Int64("chromium-restart-after", 0, "Number of conversions after which Chromium will automatically restart. Set to 0 to disable this feature")
|
||||||
|
fs.Int64("chromium-max-queue-size", 0, "Maximum request queue size for chromium. Set to 0 to disable this feature")
|
||||||
fs.Bool("chromium-auto-start", false, "Automatically launch Chromium upon initialization if set to true; otherwise, Chromium will start at the time of the first conversion")
|
fs.Bool("chromium-auto-start", false, "Automatically launch Chromium upon initialization if set to true; otherwise, Chromium will start at the time of the first conversion")
|
||||||
fs.Duration("chromium-start-timeout", time.Duration(20)*time.Second, "Maximum duration to wait for Chromium to start or restart")
|
fs.Duration("chromium-start-timeout", time.Duration(20)*time.Second, "Maximum duration to wait for Chromium to start or restart")
|
||||||
fs.Bool("chromium-incognito", false, "Start Chromium with incognito mode")
|
fs.Bool("chromium-incognito", false, "Start Chromium with incognito mode")
|
||||||
@@ -295,7 +296,6 @@ func (mod *Chromium) Descriptor() gotenberg.ModuleDescriptor {
|
|||||||
fs.Bool("chromium-clear-cookies", false, "Clear Chromium cookies between each conversion")
|
fs.Bool("chromium-clear-cookies", false, "Clear Chromium cookies between each conversion")
|
||||||
fs.Bool("chromium-disable-javascript", false, "Disable JavaScript")
|
fs.Bool("chromium-disable-javascript", false, "Disable JavaScript")
|
||||||
fs.Bool("chromium-disable-routes", false, "Disable the routes")
|
fs.Bool("chromium-disable-routes", false, "Disable the routes")
|
||||||
fs.Int64("chromium-max-queue-size", 0, "Maximum request queue size for chromium. Set to 0 to disable this feature")
|
|
||||||
|
|
||||||
return fs
|
return fs
|
||||||
}(),
|
}(),
|
||||||
|
|||||||
@@ -512,7 +512,7 @@ func convertUrl(ctx *api.Context, chromium Api, engine gotenberg.PdfEngine, url
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
if errors.Is(err, ErrOmitBackgroundWithoutPrintBackground) {
|
if errors.Is(err, ErrOmitBackgroundWithoutPrintBackground) {
|
||||||
return api.WrapError(
|
return api.WrapError(
|
||||||
err,
|
fmt.Errorf("convert to PDF: %w", err),
|
||||||
api.NewSentinelHttpError(
|
api.NewSentinelHttpError(
|
||||||
http.StatusBadRequest,
|
http.StatusBadRequest,
|
||||||
"omitBackground requires printBackground set to true",
|
"omitBackground requires printBackground set to true",
|
||||||
@@ -540,16 +540,6 @@ func convertUrl(ctx *api.Context, chromium Api, engine gotenberg.PdfEngine, url
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
if errors.Is(err, gotenberg.ErrMaximumQueueSizeExceeded) {
|
|
||||||
return api.WrapError(
|
|
||||||
fmt.Errorf("convert to PDF: %w", err),
|
|
||||||
api.NewSentinelHttpError(
|
|
||||||
http.StatusTooManyRequests,
|
|
||||||
"The maximum queue size has been reached",
|
|
||||||
),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
return fmt.Errorf("convert to PDF: %w", err)
|
return fmt.Errorf("convert to PDF: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -563,6 +553,16 @@ func convertUrl(ctx *api.Context, chromium Api, engine gotenberg.PdfEngine, url
|
|||||||
|
|
||||||
err = engine.Convert(ctx, ctx.Log(), pdfFormats, convertInputPath, convertOutputPath)
|
err = engine.Convert(ctx, ctx.Log(), pdfFormats, convertInputPath, convertOutputPath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
if errors.Is(err, gotenberg.ErrMaximumQueueSizeExceeded) {
|
||||||
|
return api.WrapError(
|
||||||
|
fmt.Errorf("convert PDF: %w", err),
|
||||||
|
api.NewSentinelHttpError(
|
||||||
|
http.StatusTooManyRequests,
|
||||||
|
"The maximum queue size has been reached",
|
||||||
|
),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
if errors.Is(err, gotenberg.ErrPdfFormatNotSupported) {
|
if errors.Is(err, gotenberg.ErrPdfFormatNotSupported) {
|
||||||
return api.WrapError(
|
return api.WrapError(
|
||||||
fmt.Errorf("convert PDF: %w", err),
|
fmt.Errorf("convert PDF: %w", err),
|
||||||
@@ -611,6 +611,16 @@ func handleChromiumError(err error, url string, options Options) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if errors.Is(err, gotenberg.ErrMaximumQueueSizeExceeded) {
|
||||||
|
return api.WrapError(
|
||||||
|
err,
|
||||||
|
api.NewSentinelHttpError(
|
||||||
|
http.StatusTooManyRequests,
|
||||||
|
"The maximum queue size has been reached",
|
||||||
|
),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
if errors.Is(err, ErrUrlNotAuthorized) {
|
if errors.Is(err, ErrUrlNotAuthorized) {
|
||||||
return api.WrapError(
|
return api.WrapError(
|
||||||
err,
|
err,
|
||||||
|
|||||||
@@ -1230,6 +1230,18 @@ func TestConvertUrl(t *testing.T) {
|
|||||||
expectHttpStatus int
|
expectHttpStatus int
|
||||||
expectOutputPathsCount int
|
expectOutputPathsCount int
|
||||||
}{
|
}{
|
||||||
|
{
|
||||||
|
scenario: "ErrMaximumQueueSizeExceeded",
|
||||||
|
ctx: &api.ContextMock{Context: new(api.Context)},
|
||||||
|
api: &ApiMock{PdfMock: func(ctx context.Context, logger *zap.Logger, url, outputPath string, options PdfOptions) error {
|
||||||
|
return gotenberg.ErrMaximumQueueSizeExceeded
|
||||||
|
}},
|
||||||
|
options: DefaultPdfOptions(),
|
||||||
|
expectError: true,
|
||||||
|
expectHttpError: true,
|
||||||
|
expectHttpStatus: http.StatusTooManyRequests,
|
||||||
|
expectOutputPathsCount: 0,
|
||||||
|
},
|
||||||
{
|
{
|
||||||
scenario: "ErrUrlNotAuthorized",
|
scenario: "ErrUrlNotAuthorized",
|
||||||
ctx: &api.ContextMock{Context: new(api.Context)},
|
ctx: &api.ContextMock{Context: new(api.Context)},
|
||||||
@@ -1341,6 +1353,22 @@ func TestConvertUrl(t *testing.T) {
|
|||||||
expectHttpError: false,
|
expectHttpError: false,
|
||||||
expectOutputPathsCount: 0,
|
expectOutputPathsCount: 0,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
scenario: "ErrMaximumQueueSizeExceeded (PDF engine)",
|
||||||
|
ctx: &api.ContextMock{Context: new(api.Context)},
|
||||||
|
api: &ApiMock{PdfMock: func(ctx context.Context, logger *zap.Logger, url, outputPath string, options PdfOptions) error {
|
||||||
|
return nil
|
||||||
|
}},
|
||||||
|
engine: &gotenberg.PdfEngineMock{ConvertMock: func(ctx context.Context, logger *zap.Logger, formats gotenberg.PdfFormats, inputPath, outputPath string) error {
|
||||||
|
return gotenberg.ErrMaximumQueueSizeExceeded
|
||||||
|
}},
|
||||||
|
pdfFormats: gotenberg.PdfFormats{PdfA: "foo"},
|
||||||
|
options: DefaultPdfOptions(),
|
||||||
|
expectError: true,
|
||||||
|
expectHttpError: true,
|
||||||
|
expectHttpStatus: http.StatusTooManyRequests,
|
||||||
|
expectOutputPathsCount: 0,
|
||||||
|
},
|
||||||
{
|
{
|
||||||
scenario: "ErrPdfFormatNotSupported",
|
scenario: "ErrPdfFormatNotSupported",
|
||||||
ctx: &api.ContextMock{Context: new(api.Context)},
|
ctx: &api.ContextMock{Context: new(api.Context)},
|
||||||
@@ -1462,6 +1490,18 @@ func TestScreenshotUrl(t *testing.T) {
|
|||||||
expectHttpStatus int
|
expectHttpStatus int
|
||||||
expectOutputPathsCount int
|
expectOutputPathsCount int
|
||||||
}{
|
}{
|
||||||
|
{
|
||||||
|
scenario: "ErrMaximumQueueSizeExceeded",
|
||||||
|
ctx: &api.ContextMock{Context: new(api.Context)},
|
||||||
|
api: &ApiMock{ScreenshotMock: func(ctx context.Context, logger *zap.Logger, url, outputPath string, options ScreenshotOptions) error {
|
||||||
|
return gotenberg.ErrMaximumQueueSizeExceeded
|
||||||
|
}},
|
||||||
|
options: DefaultScreenshotOptions(),
|
||||||
|
expectError: true,
|
||||||
|
expectHttpError: true,
|
||||||
|
expectHttpStatus: http.StatusTooManyRequests,
|
||||||
|
expectOutputPathsCount: 0,
|
||||||
|
},
|
||||||
{
|
{
|
||||||
scenario: "ErrUrlNotAuthorized",
|
scenario: "ErrUrlNotAuthorized",
|
||||||
ctx: &api.ContextMock{Context: new(api.Context)},
|
ctx: &api.ContextMock{Context: new(api.Context)},
|
||||||
|
|||||||
@@ -107,11 +107,21 @@ func convertRoute(libreOffice libreofficeapi.Uno, engine gotenberg.PdfEngine) ap
|
|||||||
|
|
||||||
err = engine.Merge(ctx, ctx.Log(), outputPaths, outputPath)
|
err = engine.Merge(ctx, ctx.Log(), outputPaths, outputPath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
if errors.Is(err, gotenberg.ErrMaximumQueueSizeExceeded) {
|
||||||
|
return api.WrapError(
|
||||||
|
fmt.Errorf("merge PDFs: %w", err),
|
||||||
|
api.NewSentinelHttpError(
|
||||||
|
http.StatusTooManyRequests,
|
||||||
|
"The maximum queue size has been reached",
|
||||||
|
),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
return fmt.Errorf("merge PDFs: %w", err)
|
return fmt.Errorf("merge PDFs: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Now, let's check if the client want to convert this result
|
// Now, let's check if the client want to convert this
|
||||||
// PDF to specific PDF formats.
|
// resulting PDF to specific PDF formats.
|
||||||
zeroValued := gotenberg.PdfFormats{}
|
zeroValued := gotenberg.PdfFormats{}
|
||||||
if !nativePdfFormats && pdfFormats != zeroValued {
|
if !nativePdfFormats && pdfFormats != zeroValued {
|
||||||
convertInputPath := outputPath
|
convertInputPath := outputPath
|
||||||
@@ -119,6 +129,16 @@ func convertRoute(libreOffice libreofficeapi.Uno, engine gotenberg.PdfEngine) ap
|
|||||||
|
|
||||||
err = engine.Convert(ctx, ctx.Log(), pdfFormats, convertInputPath, convertOutputPath)
|
err = engine.Convert(ctx, ctx.Log(), pdfFormats, convertInputPath, convertOutputPath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
if errors.Is(err, gotenberg.ErrMaximumQueueSizeExceeded) {
|
||||||
|
return api.WrapError(
|
||||||
|
fmt.Errorf("convert PDF: %w", err),
|
||||||
|
api.NewSentinelHttpError(
|
||||||
|
http.StatusTooManyRequests,
|
||||||
|
"The maximum queue size has been reached",
|
||||||
|
),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
if errors.Is(err, gotenberg.ErrPdfFormatNotSupported) {
|
if errors.Is(err, gotenberg.ErrPdfFormatNotSupported) {
|
||||||
return api.WrapError(
|
return api.WrapError(
|
||||||
fmt.Errorf("convert PDF: %w", err),
|
fmt.Errorf("convert PDF: %w", err),
|
||||||
@@ -160,6 +180,16 @@ func convertRoute(libreOffice libreofficeapi.Uno, engine gotenberg.PdfEngine) ap
|
|||||||
|
|
||||||
err = engine.Convert(ctx, ctx.Log(), pdfFormats, convertInputPath, convertOutputPaths[i])
|
err = engine.Convert(ctx, ctx.Log(), pdfFormats, convertInputPath, convertOutputPaths[i])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
if errors.Is(err, gotenberg.ErrMaximumQueueSizeExceeded) {
|
||||||
|
return api.WrapError(
|
||||||
|
fmt.Errorf("convert PDF: %w", err),
|
||||||
|
api.NewSentinelHttpError(
|
||||||
|
http.StatusTooManyRequests,
|
||||||
|
"The maximum queue size has been reached",
|
||||||
|
),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
if errors.Is(err, gotenberg.ErrPdfFormatNotSupported) {
|
if errors.Is(err, gotenberg.ErrPdfFormatNotSupported) {
|
||||||
return api.WrapError(
|
return api.WrapError(
|
||||||
fmt.Errorf("convert PDF: %w", err),
|
fmt.Errorf("convert PDF: %w", err),
|
||||||
|
|||||||
@@ -39,6 +39,28 @@ func TestConvertRoute(t *testing.T) {
|
|||||||
expectHttpStatus: http.StatusBadRequest,
|
expectHttpStatus: http.StatusBadRequest,
|
||||||
expectOutputPathsCount: 0,
|
expectOutputPathsCount: 0,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
scenario: "ErrMaximumQueueSizeExceeded",
|
||||||
|
ctx: func() *api.ContextMock {
|
||||||
|
ctx := &api.ContextMock{Context: new(api.Context)}
|
||||||
|
ctx.SetFiles(map[string]string{
|
||||||
|
"document.docx": "/document.docx",
|
||||||
|
})
|
||||||
|
return ctx
|
||||||
|
}(),
|
||||||
|
libreOffice: &libreofficeapi.ApiMock{
|
||||||
|
PdfMock: func(ctx context.Context, logger *zap.Logger, inputPath, outputPath string, options libreofficeapi.Options) error {
|
||||||
|
return gotenberg.ErrMaximumQueueSizeExceeded
|
||||||
|
},
|
||||||
|
ExtensionsMock: func() []string {
|
||||||
|
return []string{".docx"}
|
||||||
|
},
|
||||||
|
},
|
||||||
|
expectError: true,
|
||||||
|
expectHttpError: true,
|
||||||
|
expectHttpStatus: http.StatusTooManyRequests,
|
||||||
|
expectOutputPathsCount: 0,
|
||||||
|
},
|
||||||
{
|
{
|
||||||
scenario: "ErrPdfFormatNotSupported (nativePdfFormats)",
|
scenario: "ErrPdfFormatNotSupported (nativePdfFormats)",
|
||||||
ctx: func() *api.ContextMock {
|
ctx: func() *api.ContextMock {
|
||||||
@@ -109,6 +131,41 @@ func TestConvertRoute(t *testing.T) {
|
|||||||
expectHttpError: false,
|
expectHttpError: false,
|
||||||
expectOutputPathsCount: 0,
|
expectOutputPathsCount: 0,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
scenario: "ErrMaximumQueueSizeExceeded (single file)",
|
||||||
|
ctx: func() *api.ContextMock {
|
||||||
|
ctx := &api.ContextMock{Context: new(api.Context)}
|
||||||
|
ctx.SetFiles(map[string]string{
|
||||||
|
"document.docx": "/document.docx",
|
||||||
|
})
|
||||||
|
ctx.SetValues(map[string][]string{
|
||||||
|
"pdfa": {
|
||||||
|
gotenberg.PdfA1b,
|
||||||
|
},
|
||||||
|
"nativePdfFormats": {
|
||||||
|
"false",
|
||||||
|
},
|
||||||
|
})
|
||||||
|
return ctx
|
||||||
|
}(),
|
||||||
|
libreOffice: &libreofficeapi.ApiMock{
|
||||||
|
PdfMock: func(ctx context.Context, logger *zap.Logger, inputPath, outputPath string, options libreofficeapi.Options) error {
|
||||||
|
return nil
|
||||||
|
},
|
||||||
|
ExtensionsMock: func() []string {
|
||||||
|
return []string{".docx"}
|
||||||
|
},
|
||||||
|
},
|
||||||
|
engine: &gotenberg.PdfEngineMock{
|
||||||
|
ConvertMock: func(ctx context.Context, logger *zap.Logger, formats gotenberg.PdfFormats, inputPath, outputPath string) error {
|
||||||
|
return gotenberg.ErrMaximumQueueSizeExceeded
|
||||||
|
},
|
||||||
|
},
|
||||||
|
expectError: true,
|
||||||
|
expectHttpError: true,
|
||||||
|
expectHttpStatus: http.StatusTooManyRequests,
|
||||||
|
expectOutputPathsCount: 0,
|
||||||
|
},
|
||||||
{
|
{
|
||||||
scenario: "ErrPdfFormatNotSupported (single file)",
|
scenario: "ErrPdfFormatNotSupported (single file)",
|
||||||
ctx: func() *api.ContextMock {
|
ctx: func() *api.ContextMock {
|
||||||
@@ -321,6 +378,39 @@ func TestConvertRoute(t *testing.T) {
|
|||||||
expectOutputPathsCount: 2,
|
expectOutputPathsCount: 2,
|
||||||
expectOutpoutPaths: []string{"/document.docx.pdf", "/document2.docx.pdf"},
|
expectOutpoutPaths: []string{"/document.docx.pdf", "/document2.docx.pdf"},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
scenario: "ErrMaximumQueueSizeExceeded (merge)",
|
||||||
|
ctx: func() *api.ContextMock {
|
||||||
|
ctx := &api.ContextMock{Context: new(api.Context)}
|
||||||
|
ctx.SetFiles(map[string]string{
|
||||||
|
"document.docx": "/document.docx",
|
||||||
|
"document2.docx": "/document2.docx",
|
||||||
|
})
|
||||||
|
ctx.SetValues(map[string][]string{
|
||||||
|
"merge": {
|
||||||
|
"true",
|
||||||
|
},
|
||||||
|
})
|
||||||
|
return ctx
|
||||||
|
}(),
|
||||||
|
libreOffice: &libreofficeapi.ApiMock{
|
||||||
|
PdfMock: func(ctx context.Context, logger *zap.Logger, inputPath, outputPath string, options libreofficeapi.Options) error {
|
||||||
|
return nil
|
||||||
|
},
|
||||||
|
ExtensionsMock: func() []string {
|
||||||
|
return []string{".docx"}
|
||||||
|
},
|
||||||
|
},
|
||||||
|
engine: &gotenberg.PdfEngineMock{
|
||||||
|
MergeMock: func(ctx context.Context, logger *zap.Logger, inputPaths []string, outputPath string) error {
|
||||||
|
return gotenberg.ErrMaximumQueueSizeExceeded
|
||||||
|
},
|
||||||
|
},
|
||||||
|
expectError: true,
|
||||||
|
expectHttpError: true,
|
||||||
|
expectHttpStatus: http.StatusTooManyRequests,
|
||||||
|
expectOutputPathsCount: 0,
|
||||||
|
},
|
||||||
{
|
{
|
||||||
scenario: "merge error",
|
scenario: "merge error",
|
||||||
ctx: func() *api.ContextMock {
|
ctx: func() *api.ContextMock {
|
||||||
@@ -353,6 +443,48 @@ func TestConvertRoute(t *testing.T) {
|
|||||||
expectHttpError: false,
|
expectHttpError: false,
|
||||||
expectOutputPathsCount: 0,
|
expectOutputPathsCount: 0,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
scenario: "ErrMaximumQueueSizeExceeded (convert post-merge)",
|
||||||
|
ctx: func() *api.ContextMock {
|
||||||
|
ctx := &api.ContextMock{Context: new(api.Context)}
|
||||||
|
ctx.SetFiles(map[string]string{
|
||||||
|
"document.docx": "/document.docx",
|
||||||
|
"document2.docx": "/document2.docx",
|
||||||
|
})
|
||||||
|
ctx.SetValues(map[string][]string{
|
||||||
|
"merge": {
|
||||||
|
"true",
|
||||||
|
},
|
||||||
|
"pdfa": {
|
||||||
|
gotenberg.PdfA1b,
|
||||||
|
},
|
||||||
|
"nativePdfFormats": {
|
||||||
|
"false",
|
||||||
|
},
|
||||||
|
})
|
||||||
|
return ctx
|
||||||
|
}(),
|
||||||
|
libreOffice: &libreofficeapi.ApiMock{
|
||||||
|
PdfMock: func(ctx context.Context, logger *zap.Logger, inputPath, outputPath string, options libreofficeapi.Options) error {
|
||||||
|
return nil
|
||||||
|
},
|
||||||
|
ExtensionsMock: func() []string {
|
||||||
|
return []string{".docx"}
|
||||||
|
},
|
||||||
|
},
|
||||||
|
engine: &gotenberg.PdfEngineMock{
|
||||||
|
MergeMock: func(ctx context.Context, logger *zap.Logger, inputPaths []string, outputPath string) error {
|
||||||
|
return nil
|
||||||
|
},
|
||||||
|
ConvertMock: func(ctx context.Context, logger *zap.Logger, formats gotenberg.PdfFormats, inputPath, outputPath string) error {
|
||||||
|
return gotenberg.ErrMaximumQueueSizeExceeded
|
||||||
|
},
|
||||||
|
},
|
||||||
|
expectError: true,
|
||||||
|
expectHttpError: true,
|
||||||
|
expectHttpStatus: http.StatusTooManyRequests,
|
||||||
|
expectOutputPathsCount: 0,
|
||||||
|
},
|
||||||
{
|
{
|
||||||
scenario: "ErrPdfFormatNotSupported (merge)",
|
scenario: "ErrPdfFormatNotSupported (merge)",
|
||||||
ctx: func() *api.ContextMock {
|
ctx: func() *api.ContextMock {
|
||||||
|
|||||||
@@ -47,6 +47,16 @@ func mergeRoute(engine gotenberg.PdfEngine) api.Route {
|
|||||||
|
|
||||||
err = engine.Merge(ctx, ctx.Log(), inputPaths, outputPath)
|
err = engine.Merge(ctx, ctx.Log(), inputPaths, outputPath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
if errors.Is(err, gotenberg.ErrMaximumQueueSizeExceeded) {
|
||||||
|
return api.WrapError(
|
||||||
|
fmt.Errorf("merge PDFs: %w", err),
|
||||||
|
api.NewSentinelHttpError(
|
||||||
|
http.StatusTooManyRequests,
|
||||||
|
"The maximum queue size has been reached",
|
||||||
|
),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
return fmt.Errorf("merge PDFs: %w", err)
|
return fmt.Errorf("merge PDFs: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -60,6 +70,16 @@ func mergeRoute(engine gotenberg.PdfEngine) api.Route {
|
|||||||
|
|
||||||
err = engine.Convert(ctx, ctx.Log(), pdfFormats, convertInputPath, convertOutputPath)
|
err = engine.Convert(ctx, ctx.Log(), pdfFormats, convertInputPath, convertOutputPath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
if errors.Is(err, gotenberg.ErrMaximumQueueSizeExceeded) {
|
||||||
|
return api.WrapError(
|
||||||
|
fmt.Errorf("convert PDF: %w", err),
|
||||||
|
api.NewSentinelHttpError(
|
||||||
|
http.StatusTooManyRequests,
|
||||||
|
"The maximum queue size has been reached",
|
||||||
|
),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
if errors.Is(err, gotenberg.ErrPdfFormatNotSupported) {
|
if errors.Is(err, gotenberg.ErrPdfFormatNotSupported) {
|
||||||
return api.WrapError(
|
return api.WrapError(
|
||||||
fmt.Errorf("convert PDF: %w", err),
|
fmt.Errorf("convert PDF: %w", err),
|
||||||
@@ -140,6 +160,16 @@ func convertRoute(engine gotenberg.PdfEngine) api.Route {
|
|||||||
|
|
||||||
err = engine.Convert(ctx, ctx.Log(), pdfFormats, inputPath, outputPaths[i])
|
err = engine.Convert(ctx, ctx.Log(), pdfFormats, inputPath, outputPaths[i])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
if errors.Is(err, gotenberg.ErrMaximumQueueSizeExceeded) {
|
||||||
|
return api.WrapError(
|
||||||
|
fmt.Errorf("convert PDF: %w", err),
|
||||||
|
api.NewSentinelHttpError(
|
||||||
|
http.StatusTooManyRequests,
|
||||||
|
"The maximum queue size has been reached",
|
||||||
|
),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
if errors.Is(err, gotenberg.ErrPdfFormatNotSupported) {
|
if errors.Is(err, gotenberg.ErrPdfFormatNotSupported) {
|
||||||
return api.WrapError(
|
return api.WrapError(
|
||||||
fmt.Errorf("convert PDF: %w", err),
|
fmt.Errorf("convert PDF: %w", err),
|
||||||
|
|||||||
@@ -31,6 +31,27 @@ func TestMergeHandler(t *testing.T) {
|
|||||||
expectHttpStatus: http.StatusBadRequest,
|
expectHttpStatus: http.StatusBadRequest,
|
||||||
expectOutputPathsCount: 0,
|
expectOutputPathsCount: 0,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
scenario: "ErrMaximumQueueSizeExceeded (merge)",
|
||||||
|
ctx: func() *api.ContextMock {
|
||||||
|
ctx := &api.ContextMock{Context: new(api.Context)}
|
||||||
|
ctx.SetFiles(map[string]string{
|
||||||
|
"file.pdf": "/file.pdf",
|
||||||
|
"file2.pdf": "/file2.pdf",
|
||||||
|
})
|
||||||
|
|
||||||
|
return ctx
|
||||||
|
}(),
|
||||||
|
engine: &gotenberg.PdfEngineMock{
|
||||||
|
MergeMock: func(ctx context.Context, logger *zap.Logger, inputPaths []string, outputPath string) error {
|
||||||
|
return gotenberg.ErrMaximumQueueSizeExceeded
|
||||||
|
},
|
||||||
|
},
|
||||||
|
expectError: true,
|
||||||
|
expectHttpError: true,
|
||||||
|
expectHttpStatus: http.StatusTooManyRequests,
|
||||||
|
expectOutputPathsCount: 0,
|
||||||
|
},
|
||||||
{
|
{
|
||||||
scenario: "error from PDF engine",
|
scenario: "error from PDF engine",
|
||||||
ctx: func() *api.ContextMock {
|
ctx: func() *api.ContextMock {
|
||||||
@@ -90,7 +111,7 @@ func TestMergeHandler(t *testing.T) {
|
|||||||
expectOutputPathsCount: 1,
|
expectOutputPathsCount: 1,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
scenario: "ErrPdfFormatNotSupported",
|
scenario: "ErrMaximumQueueSizeExceeded (convert)",
|
||||||
ctx: func() *api.ContextMock {
|
ctx: func() *api.ContextMock {
|
||||||
ctx := &api.ContextMock{Context: new(api.Context)}
|
ctx := &api.ContextMock{Context: new(api.Context)}
|
||||||
ctx.SetFiles(map[string]string{
|
ctx.SetFiles(map[string]string{
|
||||||
@@ -104,6 +125,34 @@ func TestMergeHandler(t *testing.T) {
|
|||||||
})
|
})
|
||||||
return ctx
|
return ctx
|
||||||
}(),
|
}(),
|
||||||
|
engine: &gotenberg.PdfEngineMock{
|
||||||
|
MergeMock: func(ctx context.Context, logger *zap.Logger, inputPaths []string, outputPath string) error {
|
||||||
|
return nil
|
||||||
|
},
|
||||||
|
ConvertMock: func(ctx context.Context, logger *zap.Logger, formats gotenberg.PdfFormats, inputPath, outputPath string) error {
|
||||||
|
return gotenberg.ErrMaximumQueueSizeExceeded
|
||||||
|
},
|
||||||
|
},
|
||||||
|
expectError: true,
|
||||||
|
expectHttpError: true,
|
||||||
|
expectHttpStatus: http.StatusTooManyRequests,
|
||||||
|
expectOutputPathsCount: 0,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
scenario: "ErrPdfFormatNotSupported",
|
||||||
|
ctx: func() *api.ContextMock {
|
||||||
|
ctx := &api.ContextMock{Context: new(api.Context)}
|
||||||
|
ctx.SetFiles(map[string]string{
|
||||||
|
"file.pdf": "/file.pdf",
|
||||||
|
"file2.pdf": "/file2.pdf",
|
||||||
|
})
|
||||||
|
ctx.SetValues(map[string][]string{
|
||||||
|
"pdfa": {
|
||||||
|
"foo",
|
||||||
|
},
|
||||||
|
})
|
||||||
|
return ctx
|
||||||
|
}(),
|
||||||
engine: &gotenberg.PdfEngineMock{
|
engine: &gotenberg.PdfEngineMock{
|
||||||
MergeMock: func(ctx context.Context, logger *zap.Logger, inputPaths []string, outputPath string) error {
|
MergeMock: func(ctx context.Context, logger *zap.Logger, inputPaths []string, outputPath string) error {
|
||||||
return nil
|
return nil
|
||||||
@@ -248,7 +297,7 @@ func TestConvertHandler(t *testing.T) {
|
|||||||
expectOutputPathsCount: 0,
|
expectOutputPathsCount: 0,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
scenario: "ErrPdfFormatNotSupported",
|
scenario: "ErrMaximumQueueSizeExceeded",
|
||||||
ctx: func() *api.ContextMock {
|
ctx: func() *api.ContextMock {
|
||||||
ctx := &api.ContextMock{Context: new(api.Context)}
|
ctx := &api.ContextMock{Context: new(api.Context)}
|
||||||
ctx.SetFiles(map[string]string{
|
ctx.SetFiles(map[string]string{
|
||||||
@@ -261,6 +310,30 @@ func TestConvertHandler(t *testing.T) {
|
|||||||
})
|
})
|
||||||
return ctx
|
return ctx
|
||||||
}(),
|
}(),
|
||||||
|
engine: &gotenberg.PdfEngineMock{
|
||||||
|
ConvertMock: func(ctx context.Context, logger *zap.Logger, formats gotenberg.PdfFormats, inputPath, outputPath string) error {
|
||||||
|
return gotenberg.ErrMaximumQueueSizeExceeded
|
||||||
|
},
|
||||||
|
},
|
||||||
|
expectError: true,
|
||||||
|
expectHttpError: true,
|
||||||
|
expectHttpStatus: http.StatusTooManyRequests,
|
||||||
|
expectOutputPathsCount: 0,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
scenario: "ErrPdfFormatNotSupported",
|
||||||
|
ctx: func() *api.ContextMock {
|
||||||
|
ctx := &api.ContextMock{Context: new(api.Context)}
|
||||||
|
ctx.SetFiles(map[string]string{
|
||||||
|
"file.pdf": "/file.pdf",
|
||||||
|
})
|
||||||
|
ctx.SetValues(map[string][]string{
|
||||||
|
"pdfa": {
|
||||||
|
"foo",
|
||||||
|
},
|
||||||
|
})
|
||||||
|
return ctx
|
||||||
|
}(),
|
||||||
engine: &gotenberg.PdfEngineMock{
|
engine: &gotenberg.PdfEngineMock{
|
||||||
ConvertMock: func(ctx context.Context, logger *zap.Logger, formats gotenberg.PdfFormats, inputPath, outputPath string) error {
|
ConvertMock: func(ctx context.Context, logger *zap.Logger, formats gotenberg.PdfFormats, inputPath, outputPath string) error {
|
||||||
return gotenberg.ErrPdfFormatNotSupported
|
return gotenberg.ErrPdfFormatNotSupported
|
||||||
|
|||||||
Reference in New Issue
Block a user