chore(scanner): alte Scanner-App zurueckgebaut
Die eigenstaendige Vorgaenger-App unter scanner.perinco.de ist auf dem Server entfernt: Unit project-scanner-backend (Port 5005), beide Apache-Vhosts, das Let's-Encrypt-Zertifikat samt Renewal-Config, /var/www/Projekt Scanner (486 MB) und die Datenbank project_scanner (Dump unter /root/backups). Damit entfallen die LEGACY_*-Variablen und das Importskript, dessen Quelle es nicht mehr gibt. /root/.cache/ms-playwright bleibt bewusst stehen: der Cache stammt aus der Installation der alten App, liegt aber ausserhalb beider Verzeichnisse und wird vom CRM-Scanner benutzt - playwright ist auf 1.60.0 gepinnt, damit es genau dieser Build (chromium-1223) bleibt. Der Hinweis steht jetzt in README und docs/06-betrieb.md, damit ihn beim naechsten Aufraeumen niemand mitnimmt. SCANNER_SCHEDULER_OFFSET geht auf 0: der Versatz sollte verhindern, dass beide Instanzen mit denselben Portal-Cookies gleichzeitig losziehen. Ohne zweite Instanz hat er keinen Zweck mehr, die Mechanik bleibt fuer kuenftige Erststarts im Code. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5
parent
ab6b9f2372
commit
3c9d83161e
+50
-90
@@ -2,7 +2,8 @@
|
||||
|
||||
Der Scanner durchsucht Projektbörsen nach Aufträgen und bewertet jeden Fund mit
|
||||
OpenAI gegen die Lebensläufe der Berater. Er ist eine vollständige Portierung
|
||||
der eigenständigen App und läuft parallel zu ihr.
|
||||
der eigenständigen App, die er seit dem 09.09.2026 ersetzt
|
||||
([Rückbau](#rückbau-der-alten-app---09092026)).
|
||||
|
||||
## Ein Suchlauf
|
||||
|
||||
@@ -71,10 +72,13 @@ Takt: mit dem Endzeitpunkt kam die Laufzeit von drei bis vier Minuten jedes Mal
|
||||
obendrauf, aus 15 Minuten wurden 19 - rund ein Fuenftel weniger Durchgaenge pro
|
||||
Tag, und die Trefferliste der Boersen zeigt nur die neuesten Projekte.
|
||||
|
||||
Die **Sperrfrist** ist die Antwort auf ein konkretes Problem: beide Instanzen
|
||||
benutzen dieselben Portal-Cookies. Beim ersten Start ziehen sonst beide
|
||||
gleichzeitig los, was Rate-Limits und CAPTCHAs provoziert - und zwei Chromium
|
||||
gleichzeitig belasten den Speicher doppelt.
|
||||
Die **Sperrfrist** war die Antwort auf ein konkretes Problem des
|
||||
Parallelbetriebs: beide Instanzen benutzten dieselben Portal-Cookies. Beim
|
||||
ersten Start zogen sonst beide gleichzeitig los, was Rate-Limits und CAPTCHAs
|
||||
provozierte - und zwei Chromium gleichzeitig belasten den Speicher doppelt. Seit
|
||||
dem Rückbau der alten App steht `SCANNER_SCHEDULER_OFFSET` auf 0; die Mechanik
|
||||
bleibt im Code, weil sie bei jedem Erststart einer weiteren Instanz wieder
|
||||
greift.
|
||||
|
||||
Der Zeitpunkt des letzten Laufs steht in `settings.last_scan_at`. Das ist kein
|
||||
Luxus, sondern nach zwei beobachteten Fehlern nötig:
|
||||
@@ -155,97 +159,53 @@ nie. Dagegen das **Notventil** `PIPELINE_MAX_RUNTIME_MS`: läuft die Sperre
|
||||
länger als eine Stunde, gibt der nächste Aufruf sie frei und startet neu. So
|
||||
erholt sich der Scanner selbst, statt auf ein Deployment zu warten.
|
||||
|
||||
## Parallelbetrieb - alles verdoppelt
|
||||
## Rückbau der alten App - 09.09.2026
|
||||
|
||||
```mermaid
|
||||
flowchart LR
|
||||
subgraph alt["alte App (scanner.perinco.de)"]
|
||||
A1["Express :5005"] --> A2[("project_scanner")]
|
||||
A1 --> A3["uploads/ in<br/>/var/www/Projekt Scanner/backend"]
|
||||
A4["ENCRYPTION_KEY"] --- A1
|
||||
end
|
||||
Der Scanner lief seit dem Rollout am 06.08.2026 **parallel** zur eigenständigen
|
||||
Vorgänger-App unter `scanner.perinco.de`. Diese ist am 09.09.2026 vollständig
|
||||
zurückgebaut. Verschwunden sind:
|
||||
|
||||
subgraph neu["CRM (pcrm.perinco.de)"]
|
||||
N1["Express :5006<br/>/api/scanner"] --> N2[("perinco_scanner")]
|
||||
N1 --> N3["uploads/ in<br/>/var/www/perinco_CRM/server"]
|
||||
N4["SCANNER_ENCRYPTION_KEY"] --- N1
|
||||
end
|
||||
| Weg | War |
|
||||
| --- | --- |
|
||||
| Unit `project-scanner-backend` | Express auf `0.0.0.0:5005` |
|
||||
| Vhosts `scanner.perinco.de(.conf/-le-ssl.conf)` | eigener Apache-Vhost, Basic Auth |
|
||||
| Zertifikat `scanner.perinco.de` | eigenes Let's-Encrypt-Zert samt Renewal-Config |
|
||||
| `/var/www/Projekt Scanner` | 486 MB Code, `node_modules`, 19 CV-PDFs |
|
||||
| Datenbank `project_scanner` | 16,2 MB; Dump liegt unter `/root/backups/project_scanner_20260909-173447.sql.gz` |
|
||||
| `LEGACY_*` in `server/.env` | Quelle des Importskripts |
|
||||
| `server/src/scanner/importLegacy.js` | `npm run scanner:import` |
|
||||
|
||||
B["Projektbörsen"]
|
||||
O["OpenAI"]
|
||||
A1 --> B
|
||||
N1 --> B
|
||||
A1 --> O
|
||||
N1 --> O
|
||||
**Was bewusst stehen geblieben ist:** `/root/.cache/ms-playwright` (641 MB, Build
|
||||
`chromium-1223`). Der Cache stammt aus der Installation der alten App, aber
|
||||
`PLAYWRIGHT_BROWSERS_PATH` ist nirgends gesetzt - **beide** Apps haben ihn
|
||||
benutzt, und `playwright` ist im CRM auf exakt `1.60.0` gepinnt, damit es genau
|
||||
dieser Build bleibt. Wer den Cache mit dem alten Verzeichnis löscht, nimmt dem
|
||||
CRM-Scanner den Browser. Der Ordner `/var/www/Projekt Scanner/backend/.playwright`
|
||||
war dagegen toter Ballast einer Installation mit gesetztem
|
||||
`PLAYWRIGHT_BROWSERS_PATH` und ist mit dem Verzeichnis mitgegangen.
|
||||
|
||||
IMP["npm run scanner:import"] -.->|"liest"| A2
|
||||
IMP -.->|"schreibt"| N2
|
||||
IMP -.->|"kopiert"| N3
|
||||
```
|
||||
Was der Rückbau ändert:
|
||||
|
||||
| | alte App | CRM |
|
||||
| --- | --- | --- |
|
||||
| Datenbank | `project_scanner` | `perinco_scanner` |
|
||||
| Schlüssel | `ENCRYPTION_KEY` | `SCANNER_ENCRYPTION_KEY` |
|
||||
| CV-Dateien | eigener Ordner | eigener Ordner |
|
||||
| Aufräumen | 03:00 | 03:30 |
|
||||
| Anmeldung | HTTP Basic | CRM-Sitzung (JWT) |
|
||||
- **Kosten:** Beide Instanzen haben dieselben Projekte unabhängig voneinander
|
||||
bewertet, die OpenAI-Kosten fielen doppelt an. Faktisch war das schon am
|
||||
09.09.2026 um 08:49 vorbei - da wurde `scanning_active` in der alten
|
||||
Oberfläche auf `false` gesetzt, letzter Lauf dort 09:02.
|
||||
- **Portal-Sessions:** Beide Instanzen benutzten dieselben Cookies der
|
||||
Projektbörsen. Der Grund für `SCANNER_SCHEDULER_OFFSET` fällt damit weg, der
|
||||
Wert steht jetzt auf 0. Rate-Limits und CAPTCHAs durch zwei gleichzeitig
|
||||
scrapende Chromium-Sätze sind Geschichte.
|
||||
- **Speicher:** rund 200 MB RSS und ein zweiter Playwright-Satz weniger auf
|
||||
einer Box mit 7,7 GiB.
|
||||
- **Daten:** Nicht übernommen wurden 13380 Treffer, die es nur in der alten
|
||||
Datenbank gab, darunter 92 als *reviewed* und 5 als *applied* markierte. Ein
|
||||
nachträglicher Import war nicht sinnvoll: das Importskript vergibt die
|
||||
Original-Ids und wäre mit den vorhandenen Ids in `perinco_scanner`
|
||||
kollidiert. Der Bestand war ohnehin flüchtig - der Aufräumjob hält nur die
|
||||
jüngsten Tage. Wer doch etwas sucht, greift auf den Dump zurück.
|
||||
|
||||
**Der Preis:** Beide bewerten dieselben Projekte unabhängig voneinander, die
|
||||
OpenAI-Kosten fallen also doppelt an. Wer das senken will, stellt im CRM ein
|
||||
größeres Suchintervall ein - die Einstellung gilt nur für diese Instanz.
|
||||
|
||||
## Übernahme aus der alten Datenbank
|
||||
|
||||
`server/src/scanner/importLegacy.js`, aufrufbar als `npm run scanner:import`:
|
||||
|
||||
```mermaid
|
||||
flowchart TD
|
||||
S["Start"] --> C{"Zieltabelle agents leer?"}
|
||||
C -->|nein, ohne --force| AB["Abbruch"]
|
||||
C -->|ja oder --force| E["Einstellungen kopieren<br/>inkl. OpenAI-Key"]
|
||||
E --> P["Portale über den Namen zuordnen:<br/>Benutzername, Session-Cookies, Status"]
|
||||
P --> PW{"LEGACY_ENCRYPTION_KEY gesetzt?"}
|
||||
PW -->|ja| PW2["Passwort entschlüsseln<br/>und neu verschlüsseln"]
|
||||
PW -->|nein| PW3["Passwort auslassen"]
|
||||
PW2 --> A["Agenten anlegen, Ids behalten<br/>CV-PDF kopieren"]
|
||||
PW3 --> A
|
||||
A --> M{"--with-matches?"}
|
||||
M -->|ja| M2["Projekte und Treffer<br/>mit Original-Ids"]
|
||||
M -->|nein| F["fertig"]
|
||||
M2 --> F
|
||||
```
|
||||
|
||||
Die Ids bleiben erhalten, damit übernommene Treffer weiter auf die richtigen
|
||||
Agenten und Projekte zeigen. Deshalb bricht das Skript bei bereits vorhandenen
|
||||
Agenten ab.
|
||||
|
||||
### Agenten nachträglich holen
|
||||
|
||||
Der Vollimport ist ein Erststart-Werkzeug. Um später nur die Suchagenten
|
||||
nachzuziehen, ohne Einstellungen, Portale und Treffer anzufassen:
|
||||
|
||||
```bash
|
||||
cd /var/www/perinco_CRM/server
|
||||
npm run scanner:import -- --agents-only --skip=Bilal --dry-run
|
||||
npm run scanner:import -- --agents-only --skip=Bilal
|
||||
```
|
||||
|
||||
`--agents-only` läuft **additiv**: vorhandene Agenten blockieren nicht, sondern
|
||||
werden über den Namen erkannt und übersprungen - was hier im CRM schon
|
||||
bearbeitet wurde, bleibt also unangetastet. Die Id der Quelle wird nur
|
||||
übernommen, solange sie in `perinco_scanner` frei ist; sonst vergibt die
|
||||
Datenbank eine neue. `--skip=` nimmt einen Namen oder eine Liste
|
||||
(`--skip=Bilal,Nico`), Groß- und Kleinschreibung spielt keine Rolle.
|
||||
`--force` ist in diesem Modus gesperrt: es würde Projekte und Treffer löschen,
|
||||
die der Lauf gar nicht anrührt.
|
||||
|
||||
> **Beim Rollout am 06.08.2026 festgestellt:** Die Portal-Passwörter der alten
|
||||
> Datenbank lassen sich mit dem dortigen `ENCRYPTION_KEY` nicht mehr
|
||||
> entschlüsseln - der Schlüssel wurde nach dem Speichern getauscht. Die alte App
|
||||
> kann sie damit ebenso wenig lesen, es ging also nichts verloren. Die
|
||||
> Session-Cookies liegen im Klartext und wurden übernommen; damit scrapt die
|
||||
> neue Instanz sofort.
|
||||
Die Domain `scanner.perinco.de` zeigt weiter auf den Server, hat aber keinen
|
||||
eigenen Vhost mehr: HTTP landet beim ersten aktivierten Vhost, HTTPS gibt eine
|
||||
Zertifikatswarnung. Der DNS-Eintrag muss beim Anbieter gelöscht werden.
|
||||
|
||||
## Oberfläche
|
||||
|
||||
|
||||
Reference in New Issue
Block a user