.. _workspace_storage_thresholds:

Seuils de saturation du stockage workspace_collect
###################################################

Organisation du stockage par tenant
===================================

Le composant ``workspace-collect`` organise ses fichiers sous un répertoire propre à chaque tenant. Un conteneur ``monConteneur`` créé sur le tenant 0 est stocké dans ``<storagePath>/0/monConteneur/``, là où il occupait auparavant ``<storagePath>/monConteneur/``. Le composant ``workspace`` conserve son organisation historique sans répertoire par tenant.

Ce cloisonnement est ce qui rend mesurable l'occupation disque de chaque tenant, et donc possible le contrôle de saturation décrit ci-dessous.

Principe du contrôle
====================

Deux contrôles indépendants s'appliquent avant d'accepter un versement. Le versement est refusé dès que **l'un** des deux est en dépassement :

- **contrôle plateforme** : l'occupation cumulée de tous les tenants est comparée à ``platformCapacity``, affectée du pourcentage ``platformThresholdPercent``. Avec les valeurs par défaut, une capacité de 2000 Go et un seuil de 90 % refusent les versements dès 1800 Go occupés ;
- **contrôle par tenant** : l'occupation du tenant concerné est comparée au quota qui lui est alloué. Ce quota est une valeur absolue, sans pourcentage : le seuil de 90 % ne s'y applique pas.

.. important:: Ces contrôles ne s'appliquent **qu'aux versements du module de collecte** (``collect``), donc au stockage de ``workspace-collect``. **Les entrées réalisées par l'ingest classique n'y sont pas soumises.** Seuls les versements de données sont contrôlés : arborescence et SIP.

.. caution:: Les contrôles ne s'appliquent qu'au ``workspace-collect``, toujours organisé par tenant. Déclarer ``storageThresholds`` sous ``vitam.workspace`` reste sans effet sur les versements, aucun composant n'interrogeant le seuil du workspace principal qui conserve son organisation historique.

Configuration
=============

La stratégie de chemin est imposée : ``workspace-collect`` est toujours organisé par tenant et ``workspace`` conserve toujours son organisation historique. Les seuils se déclarent dans le bloc ``storageThresholds`` de ``vitam.workspace_collect``, dans les ``group_vars`` de votre environnement.

.. code-block:: yaml

   vitam:
     workspace_collect:
       storageThresholds:
         platformCapacity: 2000
         sizeUnit: GIGABYTE
         platformThresholdPercent: 90
         cacheRefreshIntervalSeconds: 600
         defaultTenantThreshold: 50
         tenantThresholds:
           '0': 10
           '1-3': 200

.. list-table::
   :header-rows: 1
   :widths: 27 10 63

   * - Champ
     - Défaut
     - Description
   * - ``platformCapacity``
     - ``0``
     - Capacité totale déclarée de la plateforme. C'est la référence du contrôle plateforme. La valeur ``0`` désactive ce contrôle.
   * - ``sizeUnit``
     - ``GIGABYTE``
     - Unité dans laquelle sont exprimés ``platformCapacity`` et tous les quotas. Valeurs admises : ``BYTE``, ``KILOBYTE``, ``MEGABYTE``, ``GIGABYTE``.
   * - ``platformThresholdPercent``
     - ``90``
     - Pourcentage de ``platformCapacity`` à partir duquel la plateforme est déclarée saturée. Sans effet si ``platformCapacity`` vaut ``0``.
   * - ``cacheRefreshIntervalSeconds``
     - ``600``
     - Période, en secondes, de recalcul de l'occupation disque de chaque tenant.
   * - ``defaultTenantThreshold``
     - ``0``
     - Quota appliqué à chaque tenant de la plateforme. La valeur ``0`` désactive le contrôle par tenant pour les tenants sans surcharge.
   * - ``tenantThresholds``
     - *(absent)*
     - Quotas dérogatoires par plage de tenants, prioritaires sur ``defaultTenantThreshold``. La syntaxe des plages reprend celle des :ref:`index Elasticsearch multi-tenants <grouped_tenants>` : ``'0'``, ``'1-3'``, ``'1, 3, 11-20'``.

Dans l'exemple ci-dessus, les versements sont refusés au-delà de 1800 Go cumulés ; le tenant 0 est par ailleurs limité à 10 Go, les tenants 1 à 3 à 200 Go chacun, et tout autre tenant à 50 Go.

.. warning:: ``platformCapacity`` est **déclarative** : elle n'est jamais mesurée sur le système de fichiers. Maintenez-la en cohérence avec la taille réelle du volume hébergeant ``storagePath``, en particulier après un redimensionnement.

Mesure de l'occupation
======================

Le parcours de l'arborescence étant coûteux, l'occupation par tenant n'est pas recalculée à chaque versement. Elle est maintenue dans un cache, persisté dans ``<storagePath>/threshold-cache.json``, chargé au démarrage puis rafraîchi tous les ``cacheRefreshIntervalSeconds``. Ce fichier est reconstructible : sa suppression est sans danger.

.. caution:: Le contrôle est donc **cohérent à terme**, et non instantané : une rafale de versements survenant dans une même fenêtre de rafraîchissement peut franchir le seuil avant qu'il ne soit constaté. Prévoyez une marge de sécurité sur les seuils, et réduisez ``cacheRefreshIntervalSeconds`` sur les plateformes à fort débit — au prix d'une charge d'entrées/sorties accrue.

Vérification et conduite à tenir
================================

Le point d'API interrogé par le module de collecte avant chaque versement est également consultable directement, pour le tenant passé en en-tête :

.. code-block:: bash

   curl -s -H "X-Tenant-Id: 0" http://workspace-collect.service.consul:8291/workspace-collect/v1/status/threshold-check

Il répond ``200 OK`` avec le verdict et son motif :

.. code-block:: json

   {"uploadAllowed": false, "reason": "TENANT_SATURATED"}

``reason`` vaut ``PLATFORM_SATURATED`` ou ``TENANT_SATURATED`` en cas de refus, et ``null`` lorsque le versement est autorisé. Un ``412 Precondition Failed`` signale une requête sans tenant exploitable.

Lorsqu'un seuil est atteint, le versement est refusé avec une erreur explicite de saturation (HTTP ``507``). Les traitements déjà engagés ne sont pas interrompus, et les entrées par l'ingest classique restent acceptées : le mécanisme est un garde-fou préservant une marge de manœuvre à l'exploitation, non une protection contre le remplissage total du volume. Il convient alors d'identifier les tenants concernés au moyen de l'API ci-dessus, de purger les données temporaires résiduelles, puis le cas échéant de redimensionner le volume et de mettre à jour ``platformCapacity`` en conséquence.
