dfab3e17d2
- Introduced caching mechanisms for summary and statistics in the dashboard service, improving performance by reducing redundant data retrieval. - Refactored the Summary method to utilize MongoDB aggregation for more efficient data processing and retrieval. - Added synchronization features using singleflight to prevent duplicate processing of requests for cached data. - Updated the repository to include a cachedScrapedTendersScope method, enhancing the efficiency of scraped document statistics retrieval. This update significantly optimizes the dashboard's performance and data handling capabilities, ensuring faster response times and reduced load on the database.
142 lines
3.6 KiB
Go
142 lines
3.6 KiB
Go
package dashboard
|
|
|
|
import (
|
|
"context"
|
|
"errors"
|
|
"testing"
|
|
|
|
"tm/pkg/ai_summarizer"
|
|
|
|
"go.mongodb.org/mongo-driver/v2/bson"
|
|
)
|
|
|
|
type mockProcedureDocumentsLister struct {
|
|
procedures []ai_summarizer.ProcedureDocumentsSummary
|
|
err error
|
|
}
|
|
|
|
func (m *mockProcedureDocumentsLister) ListProceduresWithDocuments(context.Context) ([]ai_summarizer.ProcedureDocumentsSummary, error) {
|
|
if m.err != nil {
|
|
return nil, m.err
|
|
}
|
|
return m.procedures, nil
|
|
}
|
|
|
|
func TestScrapedDocumentsFolderIDsUsesMinIOProcedures(t *testing.T) {
|
|
repo := &repository{
|
|
procedureLister: &mockProcedureDocumentsLister{
|
|
procedures: []ai_summarizer.ProcedureDocumentsSummary{
|
|
{ContractFolderID: "PROC-1", DocumentCount: 3},
|
|
{ContractFolderID: "PROC-2", DocumentCount: 0},
|
|
{ContractFolderID: " PROC-3 ", DocumentCount: 1},
|
|
{ContractFolderID: "PROC-1", DocumentCount: 2},
|
|
},
|
|
},
|
|
}
|
|
|
|
got, err := repo.scrapedDocumentsFolderIDs(context.Background())
|
|
if err != nil {
|
|
t.Fatalf("unexpected error: %v", err)
|
|
}
|
|
|
|
want := []string{"PROC-1", "PROC-3"}
|
|
if len(got) != len(want) {
|
|
t.Fatalf("expected %d folder IDs, got %d: %v", len(want), len(got), got)
|
|
}
|
|
for i, id := range want {
|
|
if got[i] != id {
|
|
t.Fatalf("expected folder ID %q at index %d, got %q", id, i, got[i])
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestScrapedDocumentsFolderIDsWithoutLister(t *testing.T) {
|
|
repo := &repository{}
|
|
|
|
got, err := repo.scrapedDocumentsFolderIDs(context.Background())
|
|
if err != nil {
|
|
t.Fatalf("unexpected error: %v", err)
|
|
}
|
|
if got != nil {
|
|
t.Fatalf("expected nil folder IDs without lister, got %v", got)
|
|
}
|
|
}
|
|
|
|
func TestScrapedDocumentsFolderIDsPropagatesError(t *testing.T) {
|
|
repo := &repository{
|
|
procedureLister: &mockProcedureDocumentsLister{
|
|
err: errors.New("minio unavailable"),
|
|
},
|
|
}
|
|
|
|
_, err := repo.scrapedDocumentsFolderIDs(context.Background())
|
|
if err == nil {
|
|
t.Fatal("expected error")
|
|
}
|
|
}
|
|
|
|
func TestResolveScrapedTendersScopeUsesMinIOFolders(t *testing.T) {
|
|
repo := &repository{
|
|
procedureLister: &mockProcedureDocumentsLister{
|
|
procedures: []ai_summarizer.ProcedureDocumentsSummary{
|
|
{ContractFolderID: "PROC-1", DocumentCount: 2},
|
|
},
|
|
},
|
|
}
|
|
|
|
scope, err := repo.resolveScrapedTendersScope(context.Background())
|
|
if err != nil {
|
|
t.Fatalf("unexpected error: %v", err)
|
|
}
|
|
if scope.zero {
|
|
t.Fatal("expected non-zero scope")
|
|
}
|
|
in, ok := scope.match["contract_folder_id"].(bson.M)
|
|
if !ok {
|
|
t.Fatalf("expected contract_folder_id filter, got %#v", scope.match)
|
|
}
|
|
ids, ok := in["$in"].([]string)
|
|
if !ok || len(ids) != 1 || ids[0] != "PROC-1" {
|
|
t.Fatalf("unexpected folder IDs: %#v", in["$in"])
|
|
}
|
|
}
|
|
|
|
func TestResolveScrapedTendersScopeZeroWhenMinIOEmpty(t *testing.T) {
|
|
repo := &repository{
|
|
procedureLister: &mockProcedureDocumentsLister{},
|
|
}
|
|
|
|
scope, err := repo.resolveScrapedTendersScope(context.Background())
|
|
if err != nil {
|
|
t.Fatalf("unexpected error: %v", err)
|
|
}
|
|
if !scope.zero {
|
|
t.Fatalf("expected zero scope, got %#v", scope)
|
|
}
|
|
}
|
|
|
|
func TestResolveScrapedTendersScopeMongoFallbackWithoutLister(t *testing.T) {
|
|
repo := &repository{}
|
|
|
|
scope, err := repo.resolveScrapedTendersScope(context.Background())
|
|
if err != nil {
|
|
t.Fatalf("unexpected error: %v", err)
|
|
}
|
|
if scope.zero {
|
|
t.Fatal("expected mongo fallback scope")
|
|
}
|
|
if scope.match["processing_metadata.documents_scraped"] != true {
|
|
t.Fatalf("expected mongo fallback filter, got %#v", scope.match)
|
|
}
|
|
}
|
|
|
|
func TestMongoScrapedTendersScopeMatchesStatisticsFilter(t *testing.T) {
|
|
scope := mongoScrapedTendersScope()
|
|
if scope.zero {
|
|
t.Fatal("expected non-zero mongo statistics scope")
|
|
}
|
|
if scope.match["processing_metadata.documents_scraped"] != true {
|
|
t.Fatalf("expected documents_scraped filter, got %#v", scope.match)
|
|
}
|
|
}
|