query($wpdb->prepare("INSERT IGNORE INTO {$wpdb->options} (option_name, option_value, autoload) VALUES (%s, %s, %s)", $key, maybe_serialize(['at'=>time(), 'token'=>$token]), 'no')); self::invalidate($key); return $inserted === 1 ? $token : ''; } public static function release(string $key, string $token): void { $current = get_option($key, null); if (is_array($current) && is_string($current['token'] ?? null) && hash_equals($current['token'], $token)) { self::remove($key, $current); } } private static function remove(string $key, $expected): void { global $wpdb; // delete_option cannot compare the lease value. A conditional delete // prevents an expired/finished request from deleting its successor's lock. // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching -- Atomic compare-and-delete for a non-autoloaded option; both relevant caches are invalidated immediately below. $wpdb->query($wpdb->prepare("DELETE FROM {$wpdb->options} WHERE option_name = %s AND option_value = %s", $key, maybe_serialize($expected))); self::invalidate($key); } private static function invalidate(string $key): void { wp_cache_delete($key, 'options'); wp_cache_delete('notoptions', 'options'); } }