mirror of
https://github.com/gotenberg/gotenberg.git
synced 2026-08-15 11:52:14 +01:00
124 lines
2.6 KiB
Go
124 lines
2.6 KiB
Go
package prinery
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
|
|
"github.com/thecodingmachine/gotenberg/internal/pkg/print"
|
|
"github.com/thecodingmachine/gotenberg/internal/pkg/process"
|
|
"github.com/thecodingmachine/gotenberg/internal/pkg/xerror"
|
|
"github.com/thecodingmachine/gotenberg/internal/pkg/xlog"
|
|
)
|
|
|
|
type request struct {
|
|
ctx context.Context
|
|
logger xlog.Logger
|
|
print print.Print
|
|
dest string
|
|
result chan error
|
|
}
|
|
|
|
type worker struct {
|
|
work chan request
|
|
proc process.Process
|
|
}
|
|
|
|
func (w *worker) do(done chan *worker) {
|
|
for {
|
|
req := <-w.work
|
|
req.result <- req.print.Print(req.ctx, req.dest, w.proc)
|
|
done <- w
|
|
}
|
|
}
|
|
|
|
type Prinery struct {
|
|
logger xlog.Logger
|
|
manager process.Manager
|
|
work chan request
|
|
pool chan *worker
|
|
done chan *worker
|
|
}
|
|
|
|
func New(logger xlog.Logger, manager process.Manager, key process.Key) (*Prinery, error) {
|
|
const op string = "prinery.New"
|
|
processes := manager.Processes(key)
|
|
nWorkers := len(processes)
|
|
if nWorkers == 0 {
|
|
err := fmt.Errorf("no processes found for key '%s'", string(key))
|
|
return nil, xerror.New(op, err)
|
|
}
|
|
logger.DebugfOp(op, "found '%d' processes for key '%s'", nWorkers, string(key))
|
|
work := make(chan request, 1)
|
|
pool := make(chan *worker, nWorkers)
|
|
done := make(chan *worker, nWorkers)
|
|
for _, p := range processes {
|
|
w := &worker{
|
|
work: work,
|
|
proc: p,
|
|
}
|
|
pool <- w
|
|
go w.do(done)
|
|
}
|
|
return &Prinery{
|
|
logger: logger,
|
|
manager: manager,
|
|
work: work,
|
|
pool: pool,
|
|
done: done,
|
|
}, nil
|
|
}
|
|
|
|
func (p *Prinery) PrintRequest(ctx context.Context, logger xlog.Logger, prnt print.Print, dest string) error {
|
|
const op string = "prinery.Prinery.PrintRequest"
|
|
req := request{
|
|
ctx: ctx,
|
|
logger: logger,
|
|
print: prnt,
|
|
dest: dest,
|
|
result: make(chan error),
|
|
}
|
|
p.dispatch(req)
|
|
err := <-req.result
|
|
if err != nil {
|
|
return xerror.New(op, err)
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (p *Prinery) Start() {
|
|
for {
|
|
select {
|
|
case req := <-p.work:
|
|
p.dispatch(req)
|
|
case w := <-p.done:
|
|
p.completed(w)
|
|
}
|
|
}
|
|
}
|
|
|
|
func (p *Prinery) dispatch(req request) {
|
|
const op string = "prinery.Prinery.dispatch"
|
|
select {
|
|
case w := <-p.pool:
|
|
w.work <- req
|
|
case <-req.ctx.Done():
|
|
req.result <- xerror.New(op, req.ctx.Err())
|
|
}
|
|
}
|
|
|
|
func (p *Prinery) completed(w *worker) {
|
|
const op string = "prinery.Prinerty.completed"
|
|
go func() {
|
|
// check process viability.
|
|
isViable := p.manager.IsViable(w.proc)
|
|
// check process memory usage.
|
|
// TODO handle error.
|
|
memory, _ := p.manager.Memory(w.proc)
|
|
p.logger.DebugfOp(op, "%s: isViable = %t, memory = %d", w.proc.ID(), isViable, memory)
|
|
// TODO manage viability and memory usage.
|
|
// pushing back the worker.
|
|
p.pool <- w
|
|
}()
|
|
|
|
}
|