diff --git a/maroto.go b/maroto.go index 8b0dd6b9..fd9af756 100644 --- a/maroto.go +++ b/maroto.go @@ -3,6 +3,7 @@ package maroto import ( "errors" + "github.com/f-amaral/go-async/pool" "github.com/johnfercher/maroto/v2/pkg/consts/generation" "github.com/johnfercher/maroto/v2/internal/cache" @@ -15,8 +16,6 @@ import ( "github.com/johnfercher/go-tree/node" - "github.com/f-amaral/go-async/async" - "github.com/f-amaral/go-async/pool" "github.com/johnfercher/maroto/v2/pkg/components/col" "github.com/johnfercher/maroto/v2/pkg/components/page" "github.com/johnfercher/maroto/v2/pkg/components/row" @@ -38,9 +37,6 @@ type Maroto struct { headerHeight float64 footerHeight float64 currentHeight float64 - - // Processing - pool async.Processor[[]core.Page, []byte] } // GetCurrentConfig is responsible for returning the current settings from the file @@ -68,12 +64,6 @@ func New(cfgs ...*entity.Config) core.Maroto { config: cfg, } - if cfg.GenerationMode == generation.Concurrent { - p := pool.NewPool[[]core.Page, []byte](cfg.ChunkWorkers, m.processPage, - pool.WithSortingOutput[[]core.Page, []byte]()) - m.pool = p - } - return m } @@ -289,6 +279,9 @@ func (m *Maroto) generate() (core.Document, error) { } func (m *Maroto) generateConcurrently() (core.Document, error) { + p := pool.NewPool[[]core.Page, []byte](m.config.ChunkWorkers, m.processPage, + pool.WithSortingOutput[[]core.Page, []byte]()) + defer p.Close() chunks := len(m.pages) / m.config.ChunkWorkers if chunks == 0 { chunks = 1 @@ -304,7 +297,7 @@ func (m *Maroto) generateConcurrently() (core.Document, error) { pageGroups = append(pageGroups, m.pages[i:end]) } - processed := m.pool.Process(pageGroups) + processed := p.Process(pageGroups) if processed.HasError { return nil, errors.New("an error has occurred while trying to generate PDFs concurrently") } diff --git a/maroto_test.go b/maroto_test.go index 1ebf3abc..e1307111 100644 --- a/maroto_test.go +++ b/maroto_test.go @@ -2,7 +2,9 @@ package maroto_test import ( "fmt" + "runtime" "testing" + "time" "github.com/johnfercher/maroto/v2/pkg/components/code" "github.com/johnfercher/maroto/v2/pkg/components/text" @@ -369,6 +371,31 @@ func TestMaroto_Generate(t *testing.T) { // Assert test.New(t).Assert(sut.GetStructure()).Equals("maroto_concurrent.json") }) + t.Run("goroutines do not leak after multiple generate calls on concurrent mode", func(t *testing.T) { + // Arrange + cfg := config.NewBuilder(). + WithConcurrentMode(10). + Build() + + sut := maroto.New(cfg) + + // Act + for i := 0; i < 30; i++ { + sut.AddRow(10, col.New(12)) + } + initialGoroutines := runtime.NumGoroutine() + _, err1 := sut.Generate() + _, err2 := sut.Generate() + _, err3 := sut.Generate() + time.Sleep(100 * time.Millisecond) + finalGoroutines := runtime.NumGoroutine() + + // Assert + assert.Nil(t, err1) + assert.Nil(t, err2) + assert.Nil(t, err3) + assert.Equal(t, initialGoroutines, finalGoroutines) + }) t.Run("page number", func(t *testing.T) { // Arrange cfg := config.NewBuilder().