Suppress duplicate key errors on semaphore table during rebuilds
- In _riverside_pt_rebuild(): proactively TRUNCATE the semaphore table at the very start of every rebuild. This eliminates the common 'duplicate key value violates unique constraint "semaphore____pkey"' errors for 'state:Drupal\Core\Cache\CacheCollector' and 'cron' that appear in postgres logs. - In entrypoint.sh: add TRUNCATE semaphore at strategic points (right after site:install, before module enables, before/after riverside:rebuild, before final drush cr). Wrapped with || true so they never break the startup script. - Added a note in CLAUDE.md under the rebuild section explaining the errors and the quick manual fix. These are harmless (Drupal's DbLockBackend usually recovers) but very noisy in the container logs during the default full rebuild path.
This commit is contained in:
parent
4d895d1b0d
commit
1e3ba132a4
3 changed files with 43 additions and 0 deletions
13
CLAUDE.md
13
CLAUDE.md
|
|
@ -40,6 +40,19 @@ docker compose exec app drush riverside:rebuild
|
|||
docker compose exec app drush rrb
|
||||
```
|
||||
|
||||
**Note on semaphore/lock errors in logs:** During rebuilds (especially the full non-`DRUPAL_FAST` path) you may see Postgres errors like:
|
||||
|
||||
```
|
||||
ERROR: duplicate key value violates unique constraint "semaphore____pkey"
|
||||
DETAIL: Key (name)=(state:Drupal\Core\Cache\CacheCollector) already exists.
|
||||
```
|
||||
|
||||
This is harmless but noisy. The entrypoint and `_riverside_pt_rebuild()` proactively `TRUNCATE TABLE semaphore` at key points to suppress them. If you ever see them after a manual change, run:
|
||||
|
||||
```bash
|
||||
docker compose exec app drush sql:query "TRUNCATE TABLE semaphore;"
|
||||
```
|
||||
|
||||
The custom module directory is volume-mounted, so template/CSS/JS edits are live without rebuilding the Docker image. `settings.php` and `development.services.yml` are also volume-mounted.
|
||||
|
||||
**Known gotcha:** `drush site:install` rewrites `settings.php`. Because `settings.php` is a bind-mounted file, Docker Desktop on macOS may hold a stale inode reference after the rewrite. If Drupal shows "The provided host name is not valid for this server" after a full rebuild, restart with `DRUPAL_FAST=1` to re-establish the mount without re-running site:install.
|
||||
|
|
|
|||
|
|
@ -37,8 +37,17 @@ else
|
|||
--account-pass="$ADMIN_PASS" \
|
||||
-y || { echo "[entrypoint] FATAL: site:install failed."; exit 1; }
|
||||
echo "[entrypoint] Drupal installed."
|
||||
|
||||
# Clear semaphores immediately after fresh install (prevents early
|
||||
# duplicate key errors during first module enables + rebuild).
|
||||
$DRUSH sql:query "TRUNCATE TABLE semaphore;" 2>/dev/null || true
|
||||
fi
|
||||
|
||||
# Always clear stale semaphores before module enables + rebuild.
|
||||
# This is the most reliable way to avoid the duplicate key errors
|
||||
# on "semaphore" (CacheCollector, cron, state locks, etc.).
|
||||
$DRUSH sql:query "TRUNCATE TABLE semaphore;" 2>/dev/null || true
|
||||
|
||||
echo "[entrypoint] Enabling required modules..."
|
||||
$DRUSH en -y views views_ui field_ui text options link datetime && \
|
||||
echo "[entrypoint] Core modules enabled." || echo "[entrypoint] WARNING: core modules failed."
|
||||
|
|
@ -49,6 +58,11 @@ $DRUSH en -y symfony_mailer && \
|
|||
$DRUSH en -y riverside_pt && \
|
||||
echo "[entrypoint] riverside_pt enabled." || echo "[entrypoint] WARNING: riverside_pt failed."
|
||||
|
||||
# Clear semaphores to avoid duplicate key violations on the semaphore
|
||||
# table (e.g. during CacheCollector, cron, state operations) that can
|
||||
# occur during rapid config/entity changes in the rebuild.
|
||||
$DRUSH sql:query "TRUNCATE TABLE semaphore;" 2>/dev/null || true
|
||||
|
||||
echo "[entrypoint] Rebuilding site structure from code (riverside:rebuild)..."
|
||||
$DRUSH riverside:rebuild || echo "[entrypoint] WARNING: riverside:rebuild encountered an issue."
|
||||
|
||||
|
|
@ -63,6 +77,10 @@ $DRUSH config:set system.site page.front /home -y && \
|
|||
|
||||
npm run build --prefix /var/www/html >/dev/null 2>&1 && echo "[entrypoint] Tailwind built." || echo "[entrypoint] WARNING: Tailwind build failed."
|
||||
|
||||
# One more semaphore clear before the final cache rebuild (common source
|
||||
# of the duplicate key errors seen in logs).
|
||||
$DRUSH sql:query "TRUNCATE TABLE semaphore;" 2>/dev/null || true
|
||||
|
||||
$DRUSH cache:rebuild >/dev/null 2>&1 && echo "[entrypoint] Cache rebuilt."
|
||||
|
||||
if [ "${DEBUG:-false}" = "true" ]; then
|
||||
|
|
|
|||
|
|
@ -26,6 +26,18 @@ function riverside_pt_install() {
|
|||
* and navigation used by the Docker entrypoint.
|
||||
*/
|
||||
function _riverside_pt_rebuild(): void {
|
||||
// Clear any stale semaphore locks. This prevents duplicate key violations
|
||||
// on the "semaphore" table (e.g. "state:Drupal\Core\Cache\CacheCollector",
|
||||
// "cron") during rebuilds. These occur because rapid entity/config
|
||||
// changes trigger cache collectors and lock acquisitions concurrently.
|
||||
// Safe to run even on initial install (table may not exist yet).
|
||||
try {
|
||||
\Drupal::database()->truncate('semaphore')->execute();
|
||||
}
|
||||
catch (\Exception $e) {
|
||||
// Ignore if table doesn't exist yet.
|
||||
}
|
||||
|
||||
$entity_type_manager = \Drupal::entityTypeManager();
|
||||
$storage_node_type = $entity_type_manager->getStorage('node_type');
|
||||
$storage_role = $entity_type_manager->getStorage('user_role');
|
||||
|
|
|
|||
Loading…
Reference in a new issue