639 lines
28 KiB
Markdown
639 lines
28 KiB
Markdown
# Marche à suivre — Mise en production API de téléchargement des langues (modèles ONNX)
|
|
|
|
> **Objet** : procédure **complète** de mise en production de l'**API dédiée** de
|
|
> téléchargement des **modèles de langue ONNX** (traduction hors-ligne pour le
|
|
> mobile). Cette API est un **service Windows séparé** (`OmikaLanguesApi`, projet
|
|
> `src/Omika.Langues.Api`), distinct d'`OmikaApi`. Elle sert au mobile les fichiers
|
|
> de modèle + un manifeste versionné, **en accès anonyme** (fichiers génériques,
|
|
> aucune donnée client). L'**URL de base reste lue en base** (`ParametreSysteme`
|
|
> `PAS_Code = 'SRV_LANGUES'`) par `OmikaApi`, qui l'expose au bootstrap mobile.
|
|
>
|
|
> **Cible** : Windows Server `SRV-OMIKA`, PowerShell **administrateur**, runtime
|
|
> .NET 10. Aucune base de données, aucune authentification, aucun service externe.
|
|
>
|
|
> Ce document **complète** `T15-RUNBOOK-DEPLOIEMENT-PRODUCTION.md` et
|
|
> `MISE_EN_PRODUCTION_DIAGNOSTICS_V2.md` : il ne couvre que le **service Langues**.
|
|
> `OmikaApi` garde uniquement la lecture `SRV_LANGUES` → `LanguesUrl` au bootstrap.
|
|
|
|
---
|
|
|
|
## 0. Vue d'ensemble de l'API Langues
|
|
|
|
| Composant | Rôle | Référence |
|
|
|---|---|---|
|
|
| `Omika.Langues.Api` | **Service dédié** : endpoints `GET /api/langues*` (manifeste + streaming). | Windows Service `OmikaLanguesApi` |
|
|
| `Omika.Core` | `LanguageModelService` (lecture manifeste + résolution fichier) + `LanguageModelOptions` + contrats partagés. | — |
|
|
| `Langues:RootPath` | Dossier racine des modèles + du manifeste. | variable d'env. `Langues__RootPath` |
|
|
| `ParametreSysteme.SRV_LANGUES` | URL de base du service Langues, lue par `OmikaApi`. | HFSQL (Omika **et** Batik) |
|
|
|
|
Flux :
|
|
|
|
```
|
|
1. GET /api/mobile/bootstrap ──> OmikaApi lit SRV_LANGUES ──> LanguesUrl (→ URL du service Langues)
|
|
2. GET {LanguesUrl}/api/langues ──> manifeste (packs + fichiers + sha256) [anonyme]
|
|
3. GET {LanguesUrl}/api/langues/{code}/{sens}/{fichier} ──> streaming (reprise) [anonyme]
|
|
```
|
|
|
|
- `SRV_LANGUES` absent/vide → `LanguesUrl = null` → le mobile désactive la
|
|
traduction hors-ligne (aucun appel, aucun plantage).
|
|
- Les textes à traduire ne sortent **jamais** de l'appareil : traduction 100 %
|
|
locale une fois le modèle téléchargé.
|
|
|
|
---
|
|
|
|
## 1. Ce qui a changé
|
|
|
|
1. **Nouveau service dédié** `OmikaLanguesApi` (`src/Omika.Langues.Api`) : les
|
|
endpoints langues ne sont **plus** dans `OmikaApi`.
|
|
2. **Accès anonyme** : aucun token requis (les modèles sont des fichiers génériques).
|
|
3. **Nouvelle section de configuration** : `Langues` (`RootPath`, `ManifestFileName`),
|
|
portée par le service `OmikaLanguesApi`.
|
|
4. **`OmikaApi`** ne conserve que la lecture `SRV_LANGUES` → `MobileConfigurationDto.LanguesUrl`.
|
|
5. **Nouveaux fichiers à déployer sur disque** : `manifest.json` + modèles ONNX
|
|
(jamais embarqués dans l'APK/IPA ni dans un binaire).
|
|
|
|
> Le **client de téléchargement ONNX côté mobile** (téléchargement, reprise,
|
|
> vérification SHA-256, stockage local) relève d'un **ticket ultérieur** : ce
|
|
> document ne couvre que le **serveur** (service Langues + exposition `SRV_LANGUES`).
|
|
|
|
---
|
|
|
|
## 2. Prérequis
|
|
|
|
### Poste DEV (publication)
|
|
```powershell
|
|
cd D:\Avalonia\Omika
|
|
dotnet --version # SDK 10 (global.json épingle 10.0.302)
|
|
git pull # branche à jour
|
|
```
|
|
|
|
### SRV-OMIKA (PowerShell administrateur)
|
|
```powershell
|
|
net session # OK sinon STOP
|
|
dotnet --list-runtimes # Microsoft.AspNetCore.App 10.x
|
|
Get-Service OmikaApi # Running (bootstrap métier)
|
|
Test-Path 'C:\Omika\Data' # dossier de données (langues)
|
|
```
|
|
|
|
> `OmikaLanguesApi` **n'a besoin d'aucun accès HFSQL** : uniquement du dossier de
|
|
> fichiers `Langues:RootPath`.
|
|
|
|
---
|
|
|
|
## 3. Publication (poste DEV)
|
|
|
|
```powershell
|
|
cd D:\Avalonia\Omika
|
|
|
|
# Omika.Api (métier : lit SRV_LANGUES → LanguesUrl ; endpoints langues retirés)
|
|
dotnet publish src\Omika.Api\Omika.Api.csproj `
|
|
-c Release -r win-x64 --self-contained false -o C:\Omika\Deploy\OmikaApi-next
|
|
|
|
# Omika.Langues.Api (NOUVEAU service dédié)
|
|
dotnet publish src\Omika.Langues.Api\Omika.Langues.Api.csproj `
|
|
-c Release -r win-x64 --self-contained false -o C:\Omika\Deploy\LanguesApi-next
|
|
```
|
|
|
|
**Contrôles** : chaque dossier contient son `.exe` ; `appsettings.Development.json`
|
|
absent ; aucun secret Dev dans les publications.
|
|
|
|
Transférer `OmikaApi-next` et `LanguesApi-next` vers `C:\Omika\Deploy\` sur SRV-OMIKA.
|
|
|
|
---
|
|
|
|
## 4. Base HFSQL — paramètre `SRV_LANGUES`
|
|
|
|
`OmikaApi` lit l'URL depuis la table `ParametreSysteme` (schéma Omika **et** Batik —
|
|
rubriques `PAS_Code` / `PAS_Valeur`, groupe `ProtectionPlus`).
|
|
|
|
| Rubrique | Valeur |
|
|
|---|---|
|
|
| `PAS_Code` | `SRV_LANGUES` |
|
|
| `PAS_Description` | ex. « URL du service de téléchargement des modèles de langue » |
|
|
| `PAS_Valeur` | URL de base du **service Langues**, **sans slash final** |
|
|
|
|
Exemples de `PAS_Valeur` (pointe vers le service `OmikaLanguesApi`) :
|
|
|
|
- Production derrière Apache (vhost/hôte dédié) : `https://langues.applilogik.fr`
|
|
- Chemin dédié derrière l'Apache existant : `https://omika.applilogik.fr/langues`
|
|
- API interne directe : `https://omika-langues.local:8443`
|
|
|
|
> Le slash final est toléré (l'API le normalise), mais **ne pas le mettre** évite
|
|
> toute ambiguïté. La valeur doit être une URL **HTTPS** joignable par le mobile.
|
|
|
|
**Écriture** : même mécanisme que `SRV_LICENCE_MOBILE` existant — côté WinDev
|
|
`ParametreSystemeEcrit("SRV_LANGUES", "<url>")`, ou insertion/UPDATE direct via
|
|
l'outil de gestion HFSQL. La valeur n'est **jamais** codée en dur dans l'application.
|
|
|
|
---
|
|
|
|
## 5. Fichiers modèles + manifeste (sur disque)
|
|
|
|
### 5.1 Arborescence sous `RootPath`
|
|
|
|
```
|
|
Langues/
|
|
├── manifest.json
|
|
├── es/
|
|
│ ├── versFrancais/
|
|
│ │ ├── encoder.onnx
|
|
│ │ └── vocab.spm
|
|
│ └── depuisFrancais/
|
|
│ ├── encoder.onnx
|
|
│ └── vocab.spm
|
|
├── pt/
|
|
│ ├── versFrancais/...
|
|
│ └── depuisFrancais/...
|
|
└── ar/ ...
|
|
```
|
|
|
|
- `{code}` : code ISO de la langue (`es`, `pt`, `ar`, `ru`, `pl`, …).
|
|
- `{sens}` : **deux valeurs canoniques** uniquement :
|
|
- `versFrancais` → langue secondaire → français (dictée, avant insertion) ;
|
|
- `depuisFrancais` → français → langue secondaire (lecture, affichage seul).
|
|
|
|
### 5.2 Fichier `manifest.json` (clés en camelCase)
|
|
|
|
```json
|
|
{
|
|
"packs": [
|
|
{
|
|
"code": "es",
|
|
"libelle": "Espagnol",
|
|
"version": "1.0.0",
|
|
"fichiers": [
|
|
{
|
|
"sens": "versFrancais",
|
|
"nomFichier": "encoder.onnx",
|
|
"tailleOctets": 122000000,
|
|
"sha256": "a1b2c3d4...<empreinte hexadécimale SHA-256>"
|
|
},
|
|
{
|
|
"sens": "versFrancais",
|
|
"nomFichier": "vocab.spm",
|
|
"tailleOctets": 804000,
|
|
"sha256": "e5f6a7b8..."
|
|
},
|
|
{
|
|
"sens": "depuisFrancais",
|
|
"nomFichier": "encoder.onnx",
|
|
"tailleOctets": 122000000,
|
|
"sha256": "11121314..."
|
|
}
|
|
]
|
|
}
|
|
]
|
|
}
|
|
```
|
|
|
|
- `url` n'est **pas** à renseigner : l'API la construit
|
|
(`/api/langues/{code}/{sens}/{nomFichier}`).
|
|
- `tailleOctets` = taille réelle en octets (progression mobile).
|
|
- `sha256` = empreinte SHA-256 **hexadécimale** (intégrité).
|
|
|
|
### 5.3 Générer les empreintes SHA-256 (PowerShell)
|
|
|
|
```powershell
|
|
Get-FileHash -Algorithm SHA256 .\es\versFrancais\encoder.onnx |
|
|
ForEach-Object { $_.Hash.ToLowerInvariant() }
|
|
```
|
|
|
|
### 5.4 Générer le manifeste (script — recommandé)
|
|
|
|
`tailleOctets` et `sha256` sont des valeurs **mesurées sur les fichiers**, jamais
|
|
saisies à la main : une empreinte fausse ou absente ne se voit **que sur le
|
|
téléphone**, où le pack est refusé sans qu'aucune erreur ne remonte au serveur.
|
|
|
|
```powershell
|
|
# Écrit <RootPath>\manifest.json depuis les fichiers réellement présents
|
|
.\infra\deploy\New-OmikaLanguesManifeste.ps1 -RootPathLangues C:\Omika\Data\Langues
|
|
|
|
# Contrôle après chaque ajout/remplacement de modèle : code 1 au moindre écart
|
|
.\infra\deploy\New-OmikaLanguesManifeste.ps1 -Verifier
|
|
```
|
|
|
|
- La racine par défaut est lue dans `Langues__RootPath` (MACHINE) : le manifeste
|
|
est donc écrit **là où l'API le lit** (§6).
|
|
- Le script **refuse d'écrire** (code 1) un manifeste vide, et signale en clair
|
|
un code de langue invalide, un dossier de sens inconnu, un fichier absent, une
|
|
taille ou une empreinte divergente. Ces cas produisent sinon un pack
|
|
**silencieusement ignoré** (code invalide) ou **refusé** (empreinte) par le
|
|
mobile.
|
|
- `-Verifier` ne demande aucun droit administrateur : c'est le contrôle à passer
|
|
dans la foulée de toute livraison de modèle.
|
|
- `-WhatIf` affiche le manifeste qui serait écrit, sans rien modifier.
|
|
|
|
> Le format de §5.2 reste la référence ; le script ne fait que le remplir avec
|
|
> des valeurs exactes. À noter : le mobile compare `sens` de façon **sensible à
|
|
> la casse** (`versFrancais` / `depuisFrancais`) — le script normalise cette
|
|
> casse et le signale s'il la corrige.
|
|
|
|
---
|
|
|
|
## 6. Configuration serveur (`Langues`)
|
|
|
|
Règle : en variable d'environnement, `:` devient `__`
|
|
(`Langues:RootPath` ⇔ `Langues__RootPath`).
|
|
Toute modification d'une variable du service exige un **redémarrage** d'`OmikaLanguesApi`.
|
|
|
|
| Variable | Défaut | Rôle |
|
|
|---|---|---|
|
|
| `Langues__RootPath` | `<dossier de l'application>\Langues` | Dossier racine des modèles + manifeste |
|
|
| `Langues__ManifestFileName` | `manifest.json` | Nom du fichier manifeste |
|
|
| `ASPNETCORE_URLS` | `http://localhost:5000` | Adresse/port d'écoute Kestrel (HTTP loopback derrière Apache) |
|
|
| `ASPNETCORE_ENVIRONMENT` | `Production` | Environnement (recommandé) |
|
|
|
|
> Le défaut de `RootPath` est le **dossier de l'application** (résolu via
|
|
> `AppContext.BaseDirectory`), jamais le répertoire de travail courant — un service
|
|
> Windows démarre dans `C:\Windows\System32`, ce qui rendrait ce dernier inutilisable.
|
|
>
|
|
> **Recommandation production** : fixer `Langues__RootPath` sur **`C:\Omika\Data\Langues`**
|
|
> (cohérent avec les autres données sous `C:\Omika\Data`). Ne **jamais** placer les
|
|
> modèles dans `C:\Omika\Apps\LanguesApi` : ils seraient écrasés à chaque
|
|
> redéploiement (voir §7.4).
|
|
>
|
|
> **Port** : voir **§6bis** — le port n'est **pas** imposé par ce document et ne
|
|
> doit **jamais** être repris d'un exemple : il se décide contre le plan de ports
|
|
> Apache, une fois, et s'écrit ensuite partout à l'identique.
|
|
|
|
---
|
|
|
|
## 6bis. Choix du port loopback (à décider AVANT §7.5bis)
|
|
|
|
**Aucun port n'est fixé par ce document.** La convention Apache/Kestrel du parc
|
|
`omika.applilogik.fr` n'est **pas consignée dans le dépôt** : elle ne peut donc pas
|
|
être devinée ici. Elle doit être relevée sur le serveur, puis appliquée.
|
|
|
|
Ports déjà connus du dépôt — à ne **pas** réutiliser :
|
|
|
|
| Port | Service | Source |
|
|
|---|---|---|
|
|
| 5097 | `Omika.Api` (développement) | `docs\start_omika_test.ps1` |
|
|
| 5098 | `Omika.Diagnostics.Api` | `DEPLOIEMENT_PRODUCTION_DIAGNOSTICS.md` §4 |
|
|
| 5080 | `Omika.Diagnostics.Web` | `DEPLOIEMENT_PRODUCTION_DIAGNOSTICS.md` §4 |
|
|
| 5000 | Kestrel par défaut (si `ASPNETCORE_URLS` absente) | — |
|
|
|
|
### Procédure (à exécuter sur le serveur)
|
|
|
|
```powershell
|
|
# <PORT_LANGUES> : à remplacer par le port candidat avant exécution.
|
|
$portLangues = <PORT_LANGUES>
|
|
|
|
# 1. Le port candidat est-il déjà en écoute ?
|
|
Get-NetTCPConnection -LocalPort $portLangues -State Listen -ErrorAction SilentlyContinue |
|
|
Select-Object LocalAddress,LocalPort,OwningProcess
|
|
|
|
# 2. Tranches réservées par Hyper-V / WSL / Docker (elles peuvent être n'importe où)
|
|
netsh int ipv4 show excludedportrange protocol=tcp
|
|
|
|
# 3. Plage éphémère Windows : le port fixe doit rester EN DESSOUS
|
|
netsh int ipv4 show dynamicport tcp
|
|
|
|
# 4. Ports Omika réellement en écoute (vue d'ensemble)
|
|
Get-NetTCPConnection -State Listen | Where-Object LocalPort -in 5097,5098,5080,$portLangues
|
|
```
|
|
|
|
### Critères d'acceptation du port
|
|
|
|
1. **Libre** : aucune écoute sur `127.0.0.1` (étapes 1 et 2).
|
|
2. **Hors plage éphémère** : en dessous de la borne basse de l'étape 3
|
|
(49152 par défaut) — sinon une socket sortante peut le préempter.
|
|
3. **Conforme au plan Apache** : le vhost proxy doit pointer vers **ce** port.
|
|
4. **Un seul chiffre dans tout le déploiement** : `ASPNETCORE_URLS`, `ProxyPass` et
|
|
`SRV_LANGUES` doivent décrire le même service. Une divergence produit un routage
|
|
silencieux vers le mauvais service (404, ou réponse d'un autre service).
|
|
|
|
> **Sécurité** : Kestrel reste lié à `127.0.0.1` (HTTP), jamais à `0.0.0.0`.
|
|
> L'exposition publique se fait **uniquement** en HTTPS par le reverse proxy Apache.
|
|
> Le numéro choisi n'a aucune incidence sur ce point : c'est l'adresse de liaison
|
|
> qui protège le service, pas le port.
|
|
|
|
---
|
|
|
|
## 7. Marche à suivre détaillée (fenêtre de maintenance)
|
|
|
|
### 7.1 Audit (lecture seule)
|
|
|
|
```powershell
|
|
Get-Service OmikaLanguesApi -ErrorAction SilentlyContinue | Select-Object Name,Status
|
|
[Environment]::GetEnvironmentVariable('Langues__RootPath','Machine')
|
|
Test-Path 'C:\Omika\Data\Langues\manifest.json'
|
|
```
|
|
|
|
### 7.2 Backup des binaires et des données (AVANT remplacement)
|
|
|
|
```powershell
|
|
$stamp = Get-Date -Format 'yyyyMMdd-HHmmss'
|
|
$root = 'C:\Omika\Backups'
|
|
# Binaires : seulement s'ils existent déjà
|
|
if (Test-Path 'C:\Omika\Apps\LanguesApi') {
|
|
Copy-Item 'C:\Omika\Apps\LanguesApi' -Destination "$root\LanguesApi_${stamp}" -Recurse -Force
|
|
}
|
|
if (Test-Path 'C:\Omika\Apps\OmikaApi') {
|
|
Copy-Item 'C:\Omika\Apps\OmikaApi' -Destination "$root\OmikaApi_${stamp}" -Recurse -Force
|
|
}
|
|
# Données langues : seulement si le dossier existe déjà
|
|
if (Test-Path 'C:\Omika\Data\Langues') {
|
|
Copy-Item 'C:\Omika\Data\Langues' -Destination "$root\Langues_${stamp}" -Recurse -Force
|
|
}
|
|
```
|
|
|
|
### 7.3 Arrêt des services
|
|
|
|
```powershell
|
|
Stop-Service OmikaLanguesApi -Force -ErrorAction SilentlyContinue
|
|
Stop-Service OmikaApi -Force
|
|
Get-Service OmikaApi,OmikaLanguesApi | Select-Object Name,Status
|
|
```
|
|
|
|
### 7.4 Copie des binaires (préserve la config serveur existante)
|
|
|
|
```powershell
|
|
robocopy 'C:\Omika\Deploy\OmikaApi-next' 'C:\Omika\Apps\OmikaApi' /E /XF appsettings.json appsettings.Production.json web.config
|
|
robocopy 'C:\Omika\Deploy\LanguesApi-next' 'C:\Omika\Apps\LanguesApi' /E /XF appsettings.json appsettings.Production.json web.config
|
|
```
|
|
|
|
> Ne **jamais** supprimer : `C:\Omika\Config\**`, `C:\Omika\Data\**` (dont
|
|
> `C:\Omika\Data\Langues\**`), certificats TLS, variables d'environnement MACHINE.
|
|
|
|
### 7.5 Création du service `OmikaLanguesApi` (NOUVEAU — premier déploiement)
|
|
|
|
Le service se crée par le **script dédié** (recommandé : idempotent, vérifie le
|
|
compte, le droit de connexion et la disponibilité du port, prend en charge
|
|
`-WhatIf` et `-Desinstaller`) :
|
|
|
|
```powershell
|
|
cd C:\Omika\Deploy\Deploy
|
|
.\Install-OmikaLanguesApi.ps1 -Port <PORT_LANGUES>
|
|
```
|
|
|
|
> Le script résout le compte, pose les ACL (**lecture seule** sur les modèles),
|
|
> vérifie que `<PORT_LANGUES>` est réellement libre, puis crée le service
|
|
> `OmikaLanguesApi` (Manual, non démarré). Il n'écrit **aucune** variable
|
|
> d'environnement : la configuration reste l'étape §7.5bis ci-dessous.
|
|
|
|
Équivalent manuel (si vous préférez ne pas utiliser le script) :
|
|
|
|
```powershell
|
|
$cred = Get-Credential -UserName '.\svc_omika_langues' -Message 'Compte service OmikaLanguesApi'
|
|
New-Service -Name 'OmikaLanguesApi' -DisplayName 'Omika Langues Api' `
|
|
-BinaryPathName '"C:\Omika\Apps\LanguesApi\Omika.Langues.Api.exe"' `
|
|
-Credential $cred -StartupType Manual
|
|
|
|
# ACL sur le dossier des modèles (lecture seule suffit)
|
|
icacls 'C:\Omika\Data\Langues' /grant:r "$env:COMPUTERNAME\svc_omika_langues:(OI)(CI)R"
|
|
```
|
|
|
|
> Le compte dédié doit avoir le droit « Ouvrir une session en tant que service »
|
|
> (le script le vérifie et avertit si le droit manque — erreur 1069 au démarrage).
|
|
>
|
|
> **Prérequis binaire** : le service doit embarquer `UseWindowsService()`. Sans
|
|
> lui, il démarre puis s'arrête aussitôt avec l'erreur **1053** (« le service n'a
|
|
> pas répondu à temps »). C'est le cas depuis l'ajout de
|
|
> `Microsoft.Extensions.Hosting.WindowsServices` à `Omika.Langues.Api`.
|
|
>
|
|
> `infra\deploy\Install-OmikaServices.ps1` couvre désormais ce service, via
|
|
> l'option `-InclureLangues` (voir §11).
|
|
|
|
### 7.5bis Configuration du service (variables d'environnement MACHINE)
|
|
|
|
**Premier déploiement uniquement** : poser la configuration en variables
|
|
d'environnement **MACHINE** (le robocopy §7.4 a exclu `appsettings.json`, donc le
|
|
service démarre sans fichier de config). Toute modification exige ensuite un
|
|
**redémarrage** du service.
|
|
|
|
```powershell
|
|
# <PORT_LANGUES> : port décidé en §6bis — NE PAS copier une valeur d'exemple.
|
|
$portLangues = <PORT_LANGUES>
|
|
|
|
[Environment]::SetEnvironmentVariable('Langues__RootPath', 'C:\Omika\Data\Langues', 'Machine')
|
|
[Environment]::SetEnvironmentVariable('ASPNETCORE_URLS', "http://127.0.0.1:$portLangues", 'Machine')
|
|
[Environment]::SetEnvironmentVariable('ASPNETCORE_ENVIRONMENT', 'Production', 'Machine')
|
|
|
|
# Contrôle
|
|
[Environment]::GetEnvironmentVariable('Langues__RootPath', 'Machine')
|
|
[Environment]::GetEnvironmentVariable('ASPNETCORE_URLS', 'Machine')
|
|
```
|
|
|
|
> - `Langues__RootPath` : **obligatoire** en production (défaut = dossier de
|
|
> l'application, qui serait écrasé au prochain déploiement).
|
|
> - `ASPNETCORE_URLS` : port loopback **explicite**, décidé en **§6bis** (ne jamais
|
|
> recopier un exemple : le port se déduit du plan Apache, pas de ce document).
|
|
> Sans cette variable, Kestrel écoute `http://localhost:5000`.
|
|
> - Le reverse proxy Apache expose ensuite ce port en **HTTPS** ; `SRV_LANGUES`
|
|
> pointe sur l'URL publique (voir §4 et §7.5ter).
|
|
|
|
### 7.5ter Exposition HTTPS par le reverse proxy Apache
|
|
|
|
Le service écoute en HTTP sur `127.0.0.1` : il est inatteignable depuis un
|
|
téléphone. L'exposition se fait dans le vhost 443 **existant**.
|
|
|
|
`SRV_LANGUES` décrit l'**URL de base** seule : le mobile construit ensuite
|
|
`{base}/api/langues` puis `{base}/api/langues/{code}/{sens}/{fichier}`
|
|
(`LanguagePackService.ConstruireUrl`, qui concatène — un chemin dans la base est
|
|
donc conservé). Pour `SRV_LANGUES = https://omika.applilogik.fr/langues`, Apache
|
|
doit donc **retirer** le préfixe `/langues` avant de transmettre au service :
|
|
|
|
```apache
|
|
# C:\Apache24\conf\extra\httpd-ssl.conf — dans le <VirtualHost ...:443>
|
|
# Service Langues : /langues/api/langues -> http://127.0.0.1:5099/api/langues
|
|
ProxyPass /langues/ http://127.0.0.1:5099/
|
|
ProxyPassReverse /langues/ http://127.0.0.1:5099/
|
|
ProxyPass /langues http://127.0.0.1:5099/
|
|
ProxyPassReverse /langues http://127.0.0.1:5099/
|
|
```
|
|
|
|
Puis :
|
|
|
|
```powershell
|
|
& C:\Apache24\bin\httpd.exe -t # doit dire « Syntaxe OK »
|
|
Restart-Service <service Apache>
|
|
```
|
|
|
|
Contrôles (le `--resolve` évite le DNS : depuis le serveur, le nom public résout
|
|
souvent vers une IP externe qui ne revient pas sur la machine) :
|
|
|
|
```powershell
|
|
$U = 'https://omika.applilogik.fr'
|
|
$C = @('--resolve','omika.applilogik.fr:443:127.0.0.1','-k','-s','-o','NUL','-w','%{http_code}\n')
|
|
|
|
curl.exe @C "$U/langues/api/langues" # 200
|
|
curl.exe @C "$U/langues/api/langues/gl/commun/vocab.json" # 200
|
|
curl.exe @C "$U/health" # 200 : API métier intacte
|
|
|
|
$j = (curl.exe -k -s --resolve omika.applilogik.fr:443:127.0.0.1 "$U/langues/api/langues") -join ''
|
|
($j | ConvertFrom-Json).packs.Count # 31
|
|
```
|
|
|
|
> - **Le préfixe `/langues` n'est pas décoratif** : la règle existante
|
|
> `ProxyPass /api/ http://127.0.0.1:5080/api/` capte `/api/langues` et
|
|
> l'envoie à l'API métier, qui ne sert plus les langues (404). Un préfixe
|
|
> dédié évite de toucher à cette règle métier et de dépendre de l'ordre des
|
|
> `ProxyPass`.
|
|
> - Variante vhost dédié (`https://langues.applilogik.fr`) : la règle devient
|
|
> `ProxyPass /api/langues http://127.0.0.1:5099/api/langues` (sans préfixe à
|
|
> retirer), et `SRV_LANGUES = https://langues.applilogik.fr`.
|
|
> - `$U/langues` seul répond `404` du service : il n'y a pas de route `/`, c'est
|
|
> normal et sans conséquence (le mobile n'appelle que les chemins `/api/...`).
|
|
> - Un `404` sur `$U/langues/api/langues` signifie que la règle n'a pas été
|
|
> chargée (fichier non réécrit, ou Apache non rechargé) — ce n'est pas un
|
|
> problème de service : `http://127.0.0.1:5099/api/langues` reste alors `200`.
|
|
|
|
### 7.6 Déploiement des fichiers modèles + manifeste
|
|
|
|
**Procédure complète : `LIVRAISON_MODELES_LANGUES.md`** (obtention des modèles,
|
|
arborescence, dépôt, génération du manifeste, contrôles). Résumé :
|
|
|
|
```powershell
|
|
$root = 'C:\Omika\Data\Langues'
|
|
New-Item -ItemType Directory -Force -Path $root | Out-Null
|
|
|
|
# 1. Copier UNIQUEMENT les dossiers de langue {code}\ (pas de manifest.json
|
|
# préparé ailleurs : il dépend des fichiers réellement présents ici)
|
|
robocopy 'C:\Omika\Deploy\Langues\es' "$root\es" /E /R:2 /W:2
|
|
|
|
# 2. GÉNÉRER le manifeste sur le serveur (taille + SHA-256 de chaque fichier)
|
|
cd C:\Omika\Deploy\Deploy
|
|
.\New-OmikaLanguesManifeste.ps1
|
|
|
|
# 3. Contrôler
|
|
.\New-OmikaLanguesManifeste.ps1 -Verifier
|
|
```
|
|
|
|
> Le manifeste n'est **jamais** recopié d'une autre machine : il contient la
|
|
> taille et l'empreinte SHA-256 des fichiers de **ce** disque. Un manifeste
|
|
> provenant d'ailleurs fait refuser chaque pack par le mobile, sans aucune
|
|
> erreur côté serveur.
|
|
>
|
|
> Le manifeste et les fichiers modèles sont relus à chaque requête : **aucun
|
|
> redémarrage n'est nécessaire**. Le mobile, lui, garde son index mémorisé :
|
|
> il faut « Actualiser la liste » dans Paramètres → Langue secondaire.
|
|
|
|
### 7.7 Création / mise à jour du paramètre `SRV_LANGUES` (HFSQL)
|
|
|
|
Écrire la ligne `ParametreSysteme` (voir §4) si elle n'existe pas, en pointant vers
|
|
l'URL du service Langues. Aucun redémarrage requis : relue à chaque bootstrap mobile.
|
|
|
|
### 7.8 Redémarrage (consommateurs avant producteurs)
|
|
|
|
```powershell
|
|
Start-Service OmikaLanguesApi # 1. service Langues (d'abord, car appelé par le mobile)
|
|
Start-Service OmikaApi # 2. API métier (expose LanguesUrl)
|
|
Get-Service OmikaApi,OmikaLanguesApi | Select-Object Name,Status
|
|
```
|
|
|
|
---
|
|
|
|
## 8. Smoke tests
|
|
|
|
> **Accès anonyme** : aucun token requis — les réponses sont directes.
|
|
> `<PORT_LANGUES>` = le port décidé en **§6bis** et posé en §7.5bis (aucun exemple
|
|
> n'est fourni ici : recopier un chiffre d'exemple est précisément l'erreur à éviter).
|
|
|
|
```powershell
|
|
# Racine du service
|
|
Invoke-WebRequest 'http://127.0.0.1:<PORT_LANGUES>/' -UseBasicParsing # 200 {status:ok}
|
|
|
|
# Manifeste
|
|
$manifest = Invoke-RestMethod 'http://127.0.0.1:<PORT_LANGUES>/api/langues'
|
|
$manifest.packs | Select-Object code,libelle,version
|
|
|
|
# Téléchargement d'un fichier (valide le streaming + la résolution)
|
|
Invoke-WebRequest 'http://127.0.0.1:<PORT_LANGUES>/api/langues/es/versFrancais/encoder.onnx' `
|
|
-OutFile "$env:TEMP\encoder.onnx"
|
|
Get-Item "$env:TEMP\encoder.onnx" | Select-Object Name,Length # taille = tailleOctets
|
|
|
|
# Cas d'erreur attendu
|
|
Invoke-WebRequest 'http://127.0.0.1:<PORT_LANGUES>/api/langues/es/versFrancais/absent.onnx' -SkipHttpErrorCheck
|
|
# → 404
|
|
```
|
|
|
|
Vérifier aussi côté métier : après un bootstrap mobile, `LanguesUrl` vaut bien
|
|
l'URL du service Langues (pas `null`).
|
|
|
|
---
|
|
|
|
## 9. Mise à jour (ajout de langue / nouvelle version de modèle)
|
|
|
|
### 9.1 Ajouter une nouvelle langue
|
|
|
|
1. Déposer les fichiers sous `C:\Omika\Data\Langues\{code}\versFrancais\` et
|
|
`{code}\depuisFrancais\`.
|
|
2. Ajouter l'objet `pack` dans `manifest.json` (avec `version`, `tailleOctets`, `sha256`).
|
|
3. **Aucun redémarrage** : le manifeste est relu à chaque `GET /api/langues`.
|
|
|
|
### 9.2 Mettre à jour un modèle existant
|
|
|
|
1. Remplacer le(s) fichier(s) `.onnx` / `.spm` sous `{code}\{sens}\`.
|
|
2. Recalculer `tailleOctets` et `sha256` (§5.3).
|
|
3. **Incrémenter `version`** du pack (ex. `1.0.0` → `1.0.1`).
|
|
|
|
> Le mobile compare `version` (et `sha256`) entre son modèle local et le manifeste
|
|
> serveur pour décider du re-téléchargement : tant que `version` et `sha256` sont
|
|
> inchangés, le mobile considère son modèle à jour.
|
|
|
|
### 9.3 Retirer une langue
|
|
|
|
1. Supprimer l'objet `pack` de `manifest.json`.
|
|
2. Optionnel : supprimer le dossier `{code}` de `C:\Omika\Data\Langues`.
|
|
|
|
---
|
|
|
|
## 10. Rollback
|
|
|
|
- **Binaires** : restaurer `C:\Omika\Backups\LanguesApi_<stamp>` (arrêt → copie →
|
|
démarrage §7.8). Idem `OmikaApi_<stamp>` si besoin.
|
|
- **Fichiers langues** : restaurer `C:\Omika\Backups\Langues_<stamp>` (simple copie,
|
|
aucune migration à annuler).
|
|
- **Paramètre HFSQL** : remettre l'ancienne valeur de `PAS_Valeur` (ou vider
|
|
`SRV_LANGUES` → `LanguesUrl = null` → la fonctionnalité est désactivée côté mobile).
|
|
|
|
---
|
|
|
|
## 11. Écarts constatés (scripts/documents à mettre à jour)
|
|
|
|
1. ~~**`infra\deploy\Install-OmikaServices.ps1`** : ne crée **pas** le service
|
|
`OmikaLanguesApi` ni ses ACL.~~ **RÉSOLU** : `infra\deploy` contient désormais
|
|
**un script par déploiement** (`Install-OmikaApi.ps1`, `Install-OmikaWorker.ps1`,
|
|
`Install-OmikaDiagnosticsApi.ps1`, `Install-OmikaDiagnosticsWorker.ps1`,
|
|
`Install-OmikaDiagnosticsWeb.ps1`, `Install-OmikaLanguesApi.ps1`) partageant le
|
|
module `Omika.Deploy.Common.psm1`. `Install-OmikaServices.ps1` devient un
|
|
orchestrateur qui les enchaîne, avec `-InclureLangues` pour le service Langues.
|
|
Le service embarque aussi `UseWindowsService()` (sans lui : erreur 1053 au
|
|
démarrage).
|
|
2. **`infra\deploy\Install-OmikaServerFiles.ps1`** : ne copie **pas** la publication
|
|
`LanguesApi` ni le dossier de livraison des modèles — à livrer séparément
|
|
(§3, §7.6). La livraison des modèles (obtention, arborescence, manifeste,
|
|
contrôles) est décrite pas à pas dans `LIVRAISON_MODELES_LANGUES.md`, et le
|
|
manifeste se génère avec `infra\deploy\New-OmikaLanguesManifeste.ps1` (§5.4).
|
|
3. **`Omika.slnx`** ne référence **pas** `Omika.Langues.Api` (comme les projets
|
|
Diagnostics) : on publie le `.csproj` directement.
|
|
4. **Client mobile** : le téléchargement des modèles est **implémenté** côté
|
|
application (voir `TRADUCTION_HORS_LIGNE_MOBILE.md`). Le **moteur d'inférence
|
|
ONNX Runtime reste à activer** (paquet NuGet optionnel, un symbole de
|
|
compilation) : sans lui, l'application télécharge et vérifie les modèles,
|
|
mais annonce la traduction comme indisponible au lieu d'échouer.
|
|
5. **Plan de ports Apache/Kestrel : non consigné dans le dépôt.** Les seuls ports
|
|
connus sont ceux de `DEPLOIEMENT_PRODUCTION_DIAGNOSTICS.md` §4 (5097, 5098,
|
|
5080), qui y sont eux-mêmes donnés comme « à définir / à confirmer » en
|
|
production. Aucun document ne fixe le port de `OmikaLanguesApi` : il se décide
|
|
sur le serveur (§6bis). Tant que ce plan n'existe pas par écrit, **tout port cité
|
|
en exemple dans un runbook doit être traité comme un espace réservé à
|
|
remplacer**, jamais comme une valeur à recopier.
|
|
|
|
---
|
|
|
|
## 12. Récapitulatif des points de configuration
|
|
|
|
1. **Base HFSQL** : ligne `ParametreSysteme` `PAS_Code = 'SRV_LANGUES'` → URL du service Langues.
|
|
2. **Service `OmikaLanguesApi`** : variables MACHINE `Langues__RootPath` → `C:\Omika\Data\Langues` **et** `ASPNETCORE_URLS` → `http://127.0.0.1:<PORT_LANGUES>` (port décidé en **§6bis**, posé §7.5bis).
|
|
3. **Fichiers** : arborescence `{code}/{sens}/{fichier}` sous `RootPath`, puis
|
|
`manifest.json` **généré** par `New-OmikaLanguesManifeste.ps1` (§5.4) — jamais
|
|
saisi à la main.
|
|
4. **Binaires** : `Omika.Langues.Api` (nouveau) + `Omika.Api` (republication).
|
|
5. **Accès** : anonyme — aucun token, aucun accès HFSQL.
|
|
6. **Mise à jour** : ajouter/remplacer les fichiers puis regénérer le manifeste ;
|
|
**aucun redémarrage** du service n'est requis (il relit le manifeste à chaque
|
|
appel de `GET /api/langues`). Le mobile, lui, garde son index mémorisé : il
|
|
faut un rafraîchissement de la liste des langues pour voir le changement.
|