name = 'swpb_' . md5(DB_NAME . '|' . $wpdb->prefix); } public function acquire(int $fallback_ttl = 180): bool { global $wpdb; $got = $wpdb->get_var($wpdb->prepare('SELECT GET_LOCK(%s, 0)', $this->name)); if ($got !== null && $wpdb->last_error === '') { if ((int)$got === 1) { $this->mode = 'mysql'; return true; } return false; } // Fallback: atomic insert of an option that expires. $this->token = wp_generate_password(20, false, false); $value = time() + $fallback_ttl . '|' . $this->token; if (add_option(self::FALLBACK_OPTION, $value, '', false)) { $this->mode = 'option'; return true; } $current = (string)get_option(self::FALLBACK_OPTION, ''); $expires = (int)strtok($current, '|'); if ($expires > 0 && $expires < time()) { delete_option(self::FALLBACK_OPTION); if (add_option(self::FALLBACK_OPTION, $value, '', false)) { $this->mode = 'option'; return true; } } return false; } public function release(): void { global $wpdb; if ($this->mode === 'mysql') { $wpdb->query($wpdb->prepare('SELECT RELEASE_LOCK(%s)', $this->name)); } elseif ($this->mode === 'option') { wp_cache_delete(self::FALLBACK_OPTION, 'options'); $current = (string)get_option(self::FALLBACK_OPTION, ''); if (substr($current, -strlen($this->token)) === $this->token) { delete_option(self::FALLBACK_OPTION); } } $this->mode = ''; } }