orchestrator

package module
v0.2.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Aug 22, 2026 License: Apache-2.0 Imports: 24 Imported by: 0

README

nexgate/orchestrator

the orchestrator module, member of GSF-nexgate ZUGFeRD family.


The orchestrator module is the central control unit and main entry point for Go applications and microservices using NexGate. It manages the high-level invoice generation lifecycle, transforms incoming JSON payloads or RPC network requests into internal domain models, resolves multi-tenant configurations, stages binary assets, and delegates processing to specialized writer engines.


Core Responsibilities

  • Configuration Management: Initializes system parameters (system.yaml) and tenant settings (seller.yaml).
  • Payload Validation & Preprocessing: Transforms incoming JSON payloads into the strongly typed MasterZugFerd domain structure. For WebService requests, an automated Preprocessor transparently stages Base64-encoded files or remote HTTP URLs into isolated temporary workspaces.
  • Pipeline Execution: Coordinates rendering steps across engines (e.g., XML generation $\rightarrow$ PDF layout $\rightarrow$ ZUGFeRD PDF injection).
  • Engine Delegation: Uses api/writer factory logic to dynamically instantiate and invoke required engines (native vs. container).
  • P2P / WebService Exposure: Exposes high-performance JSON-RPC 2.0 endpoints over WebSockets for distributed or cross-language worker environments.

Module Directory Structure

orchestrator/
├── config/                  # Configuration loaders (system.yaml, seller.yaml, environment paths)
├── internal/
│   └── preprocessor/        # File staging, Base64 decoding, and URL hydration for RPC inputs
├── orchestrator.go          # Core Orchestrator struct, constructors, and RunJsonJob entry point
├── webservice.go            # WebSocket / JSON-RPC server setup (AsWebService)
├── webserviceHandler.go     # RPC method implementations (nexgate.process, nexgate.echo)
├── generateBase.go          # Pipeline step: Pure XML / PAR generation
├── generatePdf.go           # Pipeline step: Layout PDF generation via LibreOffice
├── generateZugferd.go       # Pipeline step: Hybrid ZUGFeRD / Factur-X assembly via Mustang
└── orchestrator_test.go     # Comprehensive integration test suite (local & service mode)


Architecture & Data Flow

The orchestrator abstracts the complex multi-step rendering process behind a clean, single-method API (RunJsonJob).

  +-----------------------------------+     +-----------------------------------+
  | In-Process Call: RunJsonJob()     |     | Remote JSON-RPC Call:             |
  +-----------------+-----------------+     | nexgate.process (via WebSocket)   |
                    |                       +-----------------+-----------------+
                    |                                         |
                    |                                         v
                    |                       +-----------------------------------+
                    |                       | Preprocessor & Asset Staging      |
                    |                       | (Decodes Base64 / Downloads URLs) |
                    |                       +-----------------+-----------------+
                    |                                         |
                    +--------------------+--------------------+
                                         |
                                         v
                     +---------------------------------------+
                     | 1. Parse JSON -> MasterZugFerd Struct |
                     +-------------------+-------------------+
                                         |
                                         v
                     +---------------------------------------+
                     | 2. Resolve Tenant & System Configs    |
                     +-------------------+-------------------+
                                         |
           +---------------------+---------------------+
           |                     |                     |
           v                     v                     v
 +--------------------+ +--------------------+ +--------------------+
| generateBase()     | | generatePdf()      | | generateZugferd()  |
| (XML Generation)   | | (LibreOffice PDF)  | | (Mustang Assembly) |
+----------+---------+ +----------+---------+ +----------+---------+
           |                      |                     |
           +----------------------+---------------------+
                                  |
                                  v
              +---------------------------------------+
              | 3. Finalize Output & Return OutputPath |
              +---------------------------------------+


WebService & RPC Integration

The orchestrator can be booted as a standalone WebService powered by nexutils/p2p/rpc (WebSocket JSON-RPC 2.0).

Starting the WebService

package main

import (
    "context"
    "time"
    "nexgate/orchestrator"
)

func main() {
    ctx := context.Background()
    envRoot := "/opt/nexgate-env"
    addr := "127.0.0.1:8080"
    heartbeat := 2 * time.Second

    // Boots the RPC Node listening for incoming WebSocket connections
    if err := orchestrator.AsWebService(ctx, envRoot, addr, heartbeat); err != nil {
        panic(err)
    }
}

Registered RPC Handlers

  • nexgate.process: Main processing endpoint. Accepts job specifications, stages files, runs the pipeline, and returns Base64-encoded output DTOs.
  • nexgate.echo: Diagnostic health check endpoint.

Connecting via RPC Client (with Custom Read/Write Limits)

Because binary files (PDFs, attachments) are transmitted over WebSocket, clients should configure the node's WriteReadLimit (default is 1 MB):

import "nexutils/p2p/rpc"

clientNode := rpc.NewNode(rpc.Options{
    Addr:              "127.0.0.1:8081",
    HeartbeatInterval: 2 * time.Second,
    WriteReadLimit:    10 * 1024 * 1024, // 10 MB limit for large document payloads
})

peer, err := clientNode.ConnectToPeer("127.0.0.1:8080")
if err != nil {
    log.Fatalf("Connection failed: %v", err)
}


Job Payload Specification (invoice.json)

The orchestrator consumes JSON payloads. Over direct RunJsonJob calls, file properties expect local file paths. Over nexgate.process RPC calls, file properties accept Inline Base64 Data Objects or HTTP URLs, which the Preprocessor automatically materializes.


Payload Structure Overview

Section Mandatory? Description
mandant.seller No Overrides target tenant folder (e.g., "testSeller" $\rightarrow$ env/sellers/testSeller).
options.queue No Target pipeline queue ("pdf", "facturx", "base"). Defaults to "zugferd".
options.template No Path, URL, or Base64 object for a custom LibreOffice template (.ott).
options.attachments No Array of file paths, Base64 objects, or URLs to embed into the ZUGFeRD PDF.
invoice.currency Yes ISO 4217 currency code (e.g., "EUR").
invoice.buyer Yes Buyer address and metadata.
invoice.items Yes Array of line items (quantity, net price, tax rates).
invoice.vats Yes Grouped VAT totals required for tax compliance.
invoice.totals Yes Calculated totals (line_total_amount, tax_total_amount, grand_total_amount).

Payload Examples

In-Process / File-Path Payload (min-invoice.json)

Used for direct orch.RunJsonJob() execution on local filesystems:

{
  "invoice": {
    "currency": "EUR",
    "invoice_id": "RE-0814-min",
    "issue_date": "20260105",
    "service_date": "20260104",
    "buyer": {
      "id": "471115",
      "name1": "Franz Fröhlich AG",
      "street": "Musterstrasse 64",
      "zip": "01221",
      "city": "Musterdorf",
      "country": "Deutschland"
    },
    "items": [
      {
        "pos": 1,
        "description": "Go Entwicklungsservice",
        "quantity": 10.5,
        "unit": "Stunde",
        "net_price": 95.00,
        "line_total": 997.5,
        "tax_rate": 19
      }
    ],
    "vats": [
      {
        "pos": 1,
        "id": "S",
        "description": "USt",
        "vat_base": 997.50,
        "vat_amount": 189.53,
        "tax_rate": 19
      }
    ],
    "totals": {
      "line_total_amount": 997.50,
      "tax_total_amount": 189.53,
      "grand_total_amount": 1187.03
    }
  }
}

RPC / Base64-Inline Payload (max-rpc-invoice.json)

Used for nexgate.process RPC calls where client files are transmitted in-payload:

{
  "mandant": {
    "seller": "testSeller"
  },
  "options": {
    "queue": "combine",
    "pdf": {
      "name": "test_combine_invoice.pdf",
      "data": "JVBERi0xLj...=="
    },
    "factur-x": {
      "name": "test_combine_invoice.xml",
      "data": "PD94bWwgdmVyc2lvbj0iMS4wI...=="
    },
    "attachments": [
      {
        "name": "test_attachment.png",
        "data": "iVBORw0KGgoAAAANSUhEUg...=="
      }
    ]
  },
  "invoice": {
    "currency": "EUR",
    "invoice_id": "RE-0815-combine-mit",
    "buyer": { ... },
    "items": [ ... ],
    "vats": [ ... ],
    "totals": { ... }
  }
}


API Entry Points

// 1. Initialize Orchestrator with default environment resolution
orch, err := orchestrator.NewDefault()

// 2. Execute a complete invoice rendering pipeline in-process
result, err := orch.RunJsonJob(jsonBytes)

// 3. Alternatively, launch as a non-blocking WebSocket service
err = orchestrator.AsWebService(ctx, envRoot, "127.0.0.1:8080", 2*time.Second)


Integration & WebService Testing

The orchestrator contains a comprehensive integration test suite verifying both in-process engine pipelines and networked WebService execution.

Test File Engine / Target Description
orchestrator_test-suite_native_test.go NATIVE Direct execution without containers or network overhead.
orchestrator_suite_test.go NATIVE & CONTAINER Full integration suite with Docker/Podman container isolation.
orchestrator_webservice_test.go WEBSERVICE Spawns background RPC server, transmits Base64 payloads over WebSockets, and verifies staged PDF execution.

If you do not have Docker or Podman installed—or simply want a lightweight, fast local test run—use the native test suite.

go test -v -tags=native ./...

2. Full Integration Testing

To run the full suite including containerized provider tests (requires Docker or Podman):

go test -v ./...

Documentation

Index

Constants

View Source
const EnvRootKey = "NEXGATE_ENVROOT"

Variables

This section is empty.

Functions

func AsWebService added in v0.2.0

func AsWebService(ctx context.Context, envRoot, addr string, heartbeatInterval time.Duration) error

Types

type Orchestrator

type Orchestrator struct {
	ZugferdMaster *invoice.ZUGFeRDmaster
	// contains filtered or unexported fields
}

func New

func New(envRoot string) (*Orchestrator, error)

func NewDefault

func NewDefault() (*Orchestrator, error)

func (*Orchestrator) RunJsonJob

func (o *Orchestrator) RunJsonJob(json []byte) (renderOutput *writer.RenderOutput, err error)

Directories

Path Synopsis
internal

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL