feat(search): SEARXNG_BASE_URL env-var fallback and expand wiki chunk column

- docker-compose.yml: pass SEARXNG_BASE_URL into mateclaw-server so the
  app can reach the searxng sidecar container out of the box (default
  http://searxng:8080).
- SystemSettingService: resolveSearxngBaseUrl() now falls back to the
  SEARXNG_BASE_URL env var when no DB value is set, so Docker users no
  longer need to configure it manually in the UI.
- V38 migration (h2 + mysql): expand mate_wiki_chunk.content from TEXT
  (64KB) to MEDIUMTEXT (16MB) so large Chinese chunks (~30k chars
  ≈ 90KB UTF-8) no longer overflow.
This commit is contained in:
matevip 2026-04-24 13:47:37 +08:00
parent 5d5eb7e2e6
commit 72a0b5fc81
4 changed files with 30 additions and 2 deletions

View File

@ -71,6 +71,8 @@ services:
SERPER_API_KEY: ${SERPER_API_KEY:-}
JWT_SECRET: ${JWT_SECRET:-}
MATECLAW_CORS_ALLOWED_ORIGINS: ${MATECLAW_CORS_ALLOWED_ORIGINS:-}
# SearXNG: tell the app where to reach the sidecar container
SEARXNG_BASE_URL: ${SEARXNG_BASE_URL:-http://searxng:8080}
ports:
- "18080:18088" # host:container — app listens on 18088 inside the container
volumes:

View File

@ -64,6 +64,18 @@ public class SystemSettingService {
private final SystemSettingMapper systemSettingMapper;
/**
* Resolve the SearXNG base URL: DB value takes priority; fall back to the
* {@code SEARXNG_BASE_URL} environment variable so Docker deployments work
* out-of-the-box without manual configuration in the UI.
*/
private String resolveSearxngBaseUrl() {
String dbValue = getValue(SEARXNG_BASE_URL_KEY, "");
if (dbValue != null && !dbValue.isBlank()) return dbValue;
String envValue = System.getenv("SEARXNG_BASE_URL");
return (envValue != null && !envValue.isBlank()) ? envValue : "";
}
public SystemSettingsDTO getSettings() {
SystemSettingsDTO dto = new SystemSettingsDTO();
dto.setLanguage(getValue(LANGUAGE_KEY, "zh-CN"));
@ -79,7 +91,7 @@ public class SystemSettingService {
dto.setTavilyBaseUrl(getValue(TAVILY_BASE_URL_KEY, "https://api.tavily.com/search"));
// Keyless provider 配置
dto.setDuckduckgoEnabled(Boolean.parseBoolean(getValue(DUCKDUCKGO_ENABLED_KEY, "true")));
dto.setSearxngBaseUrl(getValue(SEARXNG_BASE_URL_KEY, ""));
dto.setSearxngBaseUrl(resolveSearxngBaseUrl());
// API Key 脱敏回显
dto.setSerperApiKeyMasked(maskApiKey(getValue(SERPER_API_KEY_KEY, "")));
dto.setTavilyApiKeyMasked(maskApiKey(getValue(TAVILY_API_KEY_KEY, "")));
@ -153,7 +165,7 @@ public class SystemSettingService {
dto.setTavilyApiKey(getValue(TAVILY_API_KEY_KEY, ""));
dto.setTavilyBaseUrl(getValue(TAVILY_BASE_URL_KEY, "https://api.tavily.com/search"));
dto.setDuckduckgoEnabled(Boolean.parseBoolean(getValue(DUCKDUCKGO_ENABLED_KEY, "true")));
dto.setSearxngBaseUrl(getValue(SEARXNG_BASE_URL_KEY, ""));
dto.setSearxngBaseUrl(resolveSearxngBaseUrl());
return dto;
}

View File

@ -0,0 +1,3 @@
-- V38: Expand mate_wiki_chunk.content to CLOB (H2 equivalent of MEDIUMTEXT)
-- H2's TEXT is already effectively unbounded, but align with MySQL change for consistency.
ALTER TABLE mate_wiki_chunk ALTER COLUMN content CLOB NOT NULL;

View File

@ -0,0 +1,11 @@
-- V38: Expand mate_wiki_chunk.content from TEXT (64KB) to MEDIUMTEXT (16MB)
-- TEXT max = 65,535 bytes; a 30,000-char Chinese chunk needs ~90,000 bytes (3 bytes/char UTF-8).
-- MEDIUMTEXT supports up to 16,777,215 bytes, safely covering any realistic chunk size.
SET @c := (SELECT DATA_TYPE FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_SCHEMA = DATABASE()
AND TABLE_NAME = 'mate_wiki_chunk'
AND COLUMN_NAME = 'content');
SET @s := IF(@c = 'text',
'ALTER TABLE mate_wiki_chunk MODIFY COLUMN content MEDIUMTEXT NOT NULL',
'SELECT 1');
PREPARE stmt FROM @s; EXECUTE stmt; DEALLOCATE PREPARE stmt;