feat(api): on-write search reindex after catalogue writes (#17)

Wire best-effort Meilisearch index sync into the admin write paths
(create/update/delete/set_fields/set_visibility). Adds
SearchClient::sync_object (reindex if the object exists, remove if gone —
one uniform path), an optional AppState.search client, and a reindex
helper that logs failures via tracing without failing the committed
write. Server gains MEILI_URL/MEILI_MASTER_KEY/MEILI_INDEX config;
search stays disabled (no-op) when unset. reindex_all remains the
recovery path.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-06-02 23:25:43 +02:00
parent c4e0c4c834
commit d15afda9b2
17 changed files with 299 additions and 0 deletions
+24
View File
@@ -22,10 +22,34 @@ pub async fn run(config: Config) -> anyhow::Result<()> {
.await
.context("creating the session store")?;
let search = match (&config.meili_url, &config.meili_master_key) {
(Some(url), Some(key)) => {
let client = search::SearchClient::connect(url, key, &config.meili_index)
.context("connecting to Meilisearch")?;
client
.ensure_index()
.await
.context("ensuring the search index exists")?;
tracing::info!(index = %config.meili_index, "search indexing enabled");
Some(client)
}
_ => {
tracing::warn!(
"MEILI_URL/MEILI_MASTER_KEY not set — search indexing disabled (reindex_all remains the rebuild path)"
);
None
}
};
let state = AppState {
db,
app_name: config.app_name.clone(),
cookie_secure: config.cookie_secure,
search,
};
let listener = TcpListener::bind(&config.bind_addr)