Worum es geht
Rendern kostet Rechenzeit. Damit viele gleichzeitige Anfragen eine Anwendung nicht lahmlegen, rendert CRMS in einem begrenzten Pool: einer festen Zahl von Threads mit einer kurzen Warteschlange davor. Dazu kommen Grenzen für Zeit und Größe und eine Sandbox: eine abgeschlossene Umgebung, in der die Vorlage läuft und aus der sie nichts erreicht.
Wo welcher Schritt läuft
sequenceDiagram
participant C as Client
participant A as CRMS (Aufrufer-Thread)
participant P as CRMS (Render-Pool)
participant DB as Datenbank
C->>A: Render-Anfrage
A->>DB: Aufrufer, Vorlage, Revision lesen
A->>A: Format, Modus, Payload, Anhänge prüfen
A->>P: Auftrag in den Pool
Note over P: Vorlage ausführen, Format erzeugen, bei FINAL siegeln
P-->>A: Bytes (oder Fehler, Zeitlimit)
A->>DB: bei FINAL ablegen, in der Transaktion des Aufrufers
A-->>C: Dokument
- Auf dem Thread des Aufrufers: Wer fragt, Sprache, Vorlage und Revision, alle Prüfungen. Die Datenbank liest CRMS hier, im Kontext der Anfrage.
- Im Pool: Vorlage ausführen und Format erzeugen, unter Zeitlimit und Ausgabegrenze. Bei
FINALdanach das Siegel. - Wieder auf dem Thread des Aufrufers: Ein endgültiges Dokument wird abgelegt, bevor die Bytes zurückgehen.
Die Grenzen
| Grenze | Variable | Standard | Was bei Überschreitung passiert |
|---|---|---|---|
| Render-Threads | CODAMAI_CRMS_RENDER_THREADS | Zahl der Prozessoren | – |
| Warteschlange | CODAMAI_CRMS_RENDER_QUEUE | 50 Aufträge | 503 render-capacity-exhausted, sofort |
| Zeitlimit | CODAMAI_CRMS_RENDER_TIMEOUT | 30 s | Auftrag wird abgebrochen, 504 render-timeout |
| größtes Dokument | CODAMAI_CRMS_RENDER_MAX_OUTPUT | 50 MiB | 422 render-output-too-large |
| größte Payload | CODAMAI_CRMS_PAYLOAD_MAX_BYTES | 5 MiB | 422 payload-rejected mit payload-too-large |
| Anzahl Anhänge | CODAMAI_CRMS_ATTACHMENTS_MAX_COUNT | 200 | 422 payload-rejected mit attachments-too-many |
| Größe aller Anhänge | CODAMAI_CRMS_ATTACHMENTS_MAX_BYTES | 50 MiB | 422 payload-rejected mit attachments-too-large |
Über REST ist zusätzlich der ganze Körper begrenzt, bevor CRMS ihn liest: Payload-Grenze plus 64 KiB für die übrigen Felder plus die Anhang-Grenze in Base64 (vier Drittel) plus 512 Bytes je erlaubtem Anhang. Die aktuellen Werte liefert GET /crms/capabilities unter limits. Wie du sie setzt, steht unter Umgebungsvariablen.
Die Ausgabegrenze gilt zweimal: für das Markup, das die Vorlage schreibt, und für die Bytes, die das Format erzeugt. Eine Schleife, die endlos Text schreibt, füllt also nie den Speicher.
Was beim Ausführen passieren kann
| Platz im Pool? | Fertig im Zeitlimit? | Ausgabe in der Grenze? | Ergebnis |
|---|---|---|---|
| nein | – | – | 503 render-capacity-exhausted: später noch einmal versuchen |
| ja | nein | – | 504 render-timeout: der Auftrag wird unterbrochen |
| ja | ja | nein | 422 render-output-too-large |
| ja | ja | ja | Dokument |
Wird der Aufrufer selbst unterbrochen, etwa weil seine Anfrage abgebrochen wurde, bricht CRMS auch den Auftrag ab: 503 render-interrupted. Ein Render läuft nie für niemanden weiter. Ein unerwarteter Fehler im Pool ist 500 render-failed. Die Einzelheiten stehen dann nur im Log.
Die Sandbox der Vorlage
Vorlagen schreiben auch Mandanten und Benutzer. Darum läuft FreeMarker, die Vorlagensprache, eingeschränkt:
| Was | So ist es in CRMS |
|---|---|
?new | erzeugt keine einzige Klasse |
?api | ausgeschaltet. Die Vorlage sieht nur Text, Zahlen, Wahrheitswerte, Daten, Listen und Maps und erreicht nie eine Methode |
include, import | finden nichts. Eine Revision ist genau eine Quelle, ohne Dateisystem |
| Escaping | automatisch: XHTML bei DOCUMENT, XML bei TABLE und WORD |
| Markup aus der Payload | nur über crms.svg, siehe Bilder und SVG |
| Endlosschleife | wird beim Zeitlimit unterbrochen, weil die Sandbox in Schleifen auf Unterbrechung prüft |
Was die Vorlagensprache sonst kann, steht unter Die Vorlagensprache. Ein Fehler in der Vorlage kommt als Schlüssel mit Zeile und Spalte zurück: template-syntax-error|<zeile>|<spalte> beim Lesen, template-render-failed|<zeile>|<spalte> beim Ausführen, etwa bei einem fehlenden Wert.
Welche Ressourcen ein Format lädt
Ein Format lädt nichts aus dem Netz und nichts vom Dateisystem. Es bekommt alles im Speicher mit.
| Format | Erlaubt | Abgelehnt |
|---|---|---|
| HTML | asset:<name> wird zu einer data:-Adresse | ein Asset, das die Revision nicht hat: render-asset-unknown |
asset:<name>, attachment:<name>, eingebettete Schriften aus CRMS | jede andere Adresse, auch http, https, file, jar, ftp, und unbekannte Namen: render-resource-refused | |
| DOCX | asset:<name> in <pkg:binaryData>, Hyperlinks | jede andere externe Beziehung: render-resource-refused. Ein unbekanntes Asset: render-asset-unknown. Eine DTD: render-word-invalid |
| XLSX, CSV, ODS | nur das Tabellendokument | eine DTD oder ein unbekanntes Element: render-table-invalid |