feat(search): gate index events by active provider and harden rebuild reconcile
Completes the search-provider-interface wiring that the catalog hardening commits already call into: - Skip the transactional search-index-event write path when Meilisearch is not the active provider (ItemRepository.WithActiveSearchProvider / SearchIndexEventRepository.disabledByActiveProvider). - Dead-letter catalog_search_index_events after 10 attempts instead of retrying forever. - Track the rebuild high-water mark (MaxEventID / MarkProcessedThrough) and persist last_processed_event_id in UpdateStateAfterRebuild so a rebuild reconciles events enqueued during the rebuild. - Validate (read-only) the embedding lock when embedding a search query instead of establishing/mutating it. - Surface total_exact on the legacy /items browse response. - Wire the active catalog search provider into the scanner and item repo at startup. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -265,9 +265,10 @@ type itemListImageURLs struct {
|
||||
|
||||
// browseResponse is the paginated response for the /items endpoint.
|
||||
type browseResponse struct {
|
||||
Total int `json:"total"`
|
||||
HasMore bool `json:"has_more"`
|
||||
Items []itemListResponse `json:"items"`
|
||||
Total int `json:"total"`
|
||||
TotalExact bool `json:"total_exact"`
|
||||
HasMore bool `json:"has_more"`
|
||||
Items []itemListResponse `json:"items"`
|
||||
}
|
||||
|
||||
type itemFiltersResponse struct {
|
||||
@@ -600,9 +601,10 @@ func (h *ItemsHandler) writeCatalogBrowseResponse(w http.ResponseWriter, r *http
|
||||
}
|
||||
|
||||
writeJSON(w, http.StatusOK, browseResponse{
|
||||
Total: result.Total,
|
||||
HasMore: result.HasMore,
|
||||
Items: items,
|
||||
Total: result.Total,
|
||||
TotalExact: result.TotalExact,
|
||||
HasMore: result.HasMore,
|
||||
Items: items,
|
||||
})
|
||||
return true
|
||||
}
|
||||
|
||||
@@ -2,12 +2,29 @@ package handlers
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/Silo-Server/silo-server/internal/catalog"
|
||||
"github.com/Silo-Server/silo-server/internal/models"
|
||||
)
|
||||
|
||||
func TestBrowseResponseIncludesTotalExact(t *testing.T) {
|
||||
data, err := json.Marshal(browseResponse{
|
||||
Total: 3,
|
||||
TotalExact: true,
|
||||
HasMore: false,
|
||||
Items: []itemListResponse{},
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if !strings.Contains(string(data), `"total_exact":true`) {
|
||||
t.Fatalf("browse response missing total_exact: %s", data)
|
||||
}
|
||||
}
|
||||
|
||||
type countingItemListImageResolver struct {
|
||||
singleCalls int
|
||||
batchCalls int
|
||||
|
||||
Reference in New Issue
Block a user