refactor: replace Meilisearch with PostgreSQL full-text search
Remove Meilisearch dependency entirely. Search is now handled by PostgreSQL ILIKE with pg_trgm indexes, joining series_metadata for series-level authors. No external search engine needed. - Replace search.rs Meilisearch HTTP calls with PostgreSQL queries - Remove meili.rs from indexer, sync_meili call from job pipeline - Remove MEILI_URL/MEILI_MASTER_KEY from config, state, env files - Remove meilisearch service from docker-compose.yml - Add migration 0027: drop sync_metadata, enable pg_trgm, add indexes - Remove search resync button/endpoint (no longer needed) - Update all documentation (CLAUDE.md, README.md, AGENTS.md, PLAN.md) API contract unchanged — same SearchResponse shape returned. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -21,9 +21,6 @@ export default function SettingsPage({ initialSettings, initialCacheStats, initi
|
||||
const [clearResult, setClearResult] = useState<ClearCacheResponse | null>(null);
|
||||
const [isSaving, setIsSaving] = useState(false);
|
||||
const [saveMessage, setSaveMessage] = useState<string | null>(null);
|
||||
const [isResyncing, setIsResyncing] = useState(false);
|
||||
const [resyncResult, setResyncResult] = useState<{ success: boolean; message: string } | null>(null);
|
||||
|
||||
// Komga sync state — URL and username are persisted in settings
|
||||
const [komgaUrl, setKomgaUrl] = useState("");
|
||||
const [komgaUsername, setKomgaUsername] = useState("");
|
||||
@@ -89,20 +86,6 @@ export default function SettingsPage({ initialSettings, initialCacheStats, initi
|
||||
}
|
||||
}
|
||||
|
||||
async function handleSearchResync() {
|
||||
setIsResyncing(true);
|
||||
setResyncResult(null);
|
||||
try {
|
||||
const response = await fetch("/api/settings/search/resync", { method: "POST" });
|
||||
const result = await response.json();
|
||||
setResyncResult(result);
|
||||
} catch {
|
||||
setResyncResult({ success: false, message: "Failed to trigger search resync" });
|
||||
} finally {
|
||||
setIsResyncing(false);
|
||||
}
|
||||
}
|
||||
|
||||
const fetchReports = useCallback(async () => {
|
||||
try {
|
||||
const resp = await fetch("/api/komga/reports");
|
||||
@@ -365,43 +348,6 @@ export default function SettingsPage({ initialSettings, initialCacheStats, initi
|
||||
</CardContent>
|
||||
</Card>
|
||||
|
||||
{/* Search Index */}
|
||||
<Card className="mb-6">
|
||||
<CardHeader>
|
||||
<CardTitle className="flex items-center gap-2">
|
||||
<Icon name="search" size="md" />
|
||||
Search Index
|
||||
</CardTitle>
|
||||
<CardDescription>Force a full resync of the Meilisearch index. This will re-index all books on the next indexer cycle.</CardDescription>
|
||||
</CardHeader>
|
||||
<CardContent>
|
||||
<div className="space-y-4">
|
||||
{resyncResult && (
|
||||
<div className={`p-3 rounded-lg ${resyncResult.success ? 'bg-success/10 text-success' : 'bg-destructive/10 text-destructive'}`}>
|
||||
{resyncResult.message}
|
||||
</div>
|
||||
)}
|
||||
|
||||
<Button
|
||||
onClick={handleSearchResync}
|
||||
disabled={isResyncing}
|
||||
>
|
||||
{isResyncing ? (
|
||||
<>
|
||||
<Icon name="spinner" size="sm" className="animate-spin -ml-1 mr-2" />
|
||||
Scheduling...
|
||||
</>
|
||||
) : (
|
||||
<>
|
||||
<Icon name="refresh" size="sm" className="mr-2" />
|
||||
Force Search Resync
|
||||
</>
|
||||
)}
|
||||
</Button>
|
||||
</div>
|
||||
</CardContent>
|
||||
</Card>
|
||||
|
||||
{/* Limits Settings */}
|
||||
<Card className="mb-6">
|
||||
<CardHeader>
|
||||
|
||||
Reference in New Issue
Block a user