getId(); if (null === $siteId) { // Garde defensive : un site non persiste n'a pas de compteur (et la FK // weighbridge_dsd_counter.site_id -> site(id) rejetterait l'INSERT). throw new LogicException('Impossible d\'allouer un DSD pour un site non persiste (id null).'); } return $this->connection->transactional(function (Connection $conn) use ($siteId): int { // Garantit l'existence de la ligne compteur du site sans ecraser une // valeur deja presente (idempotent, concurrence-safe). $conn->executeStatement( 'INSERT INTO weighbridge_dsd_counter (site_id, last_value) VALUES (:site, 0) ON CONFLICT (site_id) DO NOTHING', ['site' => $siteId], ); // Verrou ligne : serialise les pesees concurrentes du meme site. $current = (int) $conn->fetchOne( 'SELECT last_value FROM weighbridge_dsd_counter WHERE site_id = :site FOR UPDATE', ['site' => $siteId], ); $next = $current + 1; $conn->executeStatement( 'UPDATE weighbridge_dsd_counter SET last_value = :value WHERE site_id = :site', ['value' => $next, 'site' => $siteId], ); return $next; }); } }