Add translated notices scanning functionality to dashboard repository
continuous-integration/drone/push Build is passing
continuous-integration/drone/push Build is passing
- Introduced a new `translatedNoticesScanner` interface for scanning MinIO for daily translated notice counts. - Enhanced the `repository` struct to include fields for managing translated notice scope and caching. - Implemented the `ScanTranslatedNotices` method in the `StorageClient` to retrieve daily counts and total from MinIO. - Updated the `Statistics` method in the repository to utilize the new translated notices scope, improving data accuracy. - Added unit tests for the translated notices functionality, ensuring robust validation of the new features. This update significantly enhances the dashboard's ability to handle translated notice statistics, improving overall data management and reporting capabilities.
This commit is contained in:
@@ -33,6 +33,13 @@ type scrapedTendersScope struct {
|
||||
totalTenderCount int64 // >0 when MinIO procedure count should be used instead of Mongo Count
|
||||
}
|
||||
|
||||
// translatedNoticesScope holds MinIO-backed translation statistics when available.
|
||||
type translatedNoticesScope struct {
|
||||
fromMinIO bool
|
||||
dailyCounts map[string]int64
|
||||
totalCount int64
|
||||
}
|
||||
|
||||
func (r *repository) Statistics(ctx context.Context, days int, startUnix int64) (*StatisticsReportResponse, error) {
|
||||
_ = ctx
|
||||
|
||||
@@ -47,6 +54,7 @@ func (r *repository) Statistics(ctx context.Context, days int, startUnix int64)
|
||||
totalTranslated int64
|
||||
totalScrapedTED int64
|
||||
scrapedScope scrapedTendersScope
|
||||
translatedScope translatedNoticesScope
|
||||
)
|
||||
|
||||
var wg sync.WaitGroup
|
||||
@@ -78,23 +86,26 @@ func (r *repository) Statistics(ctx context.Context, days int, startUnix int64)
|
||||
wg.Add(1)
|
||||
go func() {
|
||||
defer wg.Done()
|
||||
scope, err := r.cachedTranslatedNoticesScope(context.Background())
|
||||
if err != nil {
|
||||
recordFailure("translated_scope", err)
|
||||
return
|
||||
}
|
||||
translatedScope = scope
|
||||
if scope.fromMinIO {
|
||||
return
|
||||
}
|
||||
|
||||
qctx, cancel := context.WithTimeout(context.Background(), statisticsMongoQueryTimeout)
|
||||
defer cancel()
|
||||
|
||||
counts, err := r.translatedNoticesPerDay(qctx, startDay, endDay)
|
||||
counts, err := r.translatedNoticesPerDayFromMetrics(qctx, startDay, endDay)
|
||||
if err != nil {
|
||||
recordFailure("translated_notices", err)
|
||||
translatedNotices = map[string]int64{}
|
||||
return
|
||||
} else {
|
||||
translatedNotices = counts
|
||||
}
|
||||
translatedNotices = counts
|
||||
}()
|
||||
|
||||
wg.Add(1)
|
||||
go func() {
|
||||
defer wg.Done()
|
||||
qctx, cancel := context.WithTimeout(context.Background(), statisticsMongoQueryTimeout)
|
||||
defer cancel()
|
||||
|
||||
total, err := r.metricsCounter.Get(qctx, orm.AITranslationSuccessCounterKey)
|
||||
if err != nil {
|
||||
@@ -118,6 +129,11 @@ func (r *repository) Statistics(ctx context.Context, days int, startUnix int64)
|
||||
|
||||
wg.Wait()
|
||||
|
||||
if translatedScope.fromMinIO {
|
||||
translatedNotices = filterDailyCountsSince(translatedScope.dailyCounts, startUnix)
|
||||
totalTranslated = translatedScope.totalCount
|
||||
}
|
||||
|
||||
wg.Add(1)
|
||||
go func() {
|
||||
defer wg.Done()
|
||||
@@ -224,10 +240,79 @@ func (r *repository) scrapedDocumentsPerDayFromMongo(ctx context.Context, startU
|
||||
return decodeDailyCounts(ctx, cursor)
|
||||
}
|
||||
|
||||
func (r *repository) translatedNoticesPerDay(ctx context.Context, startDay, endDay time.Time) (map[string]int64, error) {
|
||||
func (r *repository) translatedNoticesPerDayFromMetrics(ctx context.Context, startDay, endDay time.Time) (map[string]int64, error) {
|
||||
return r.metricsCounter.GetDailyCounts(ctx, startDay, endDay)
|
||||
}
|
||||
|
||||
func (r *repository) cachedTranslatedNoticesScope(_ context.Context) (translatedNoticesScope, error) {
|
||||
now := time.Now()
|
||||
|
||||
r.translatedScopeMu.Lock()
|
||||
if r.translatedScopeCached && now.Before(r.translatedScopeExpiry) {
|
||||
scope := r.translatedScope
|
||||
r.translatedScopeMu.Unlock()
|
||||
return scope, nil
|
||||
}
|
||||
r.translatedScopeMu.Unlock()
|
||||
|
||||
v, err, _ := r.translatedScopeGroup.Do("translated-scope", func() (interface{}, error) {
|
||||
r.translatedScopeMu.Lock()
|
||||
if r.translatedScopeCached && time.Now().Before(r.translatedScopeExpiry) {
|
||||
scope := r.translatedScope
|
||||
r.translatedScopeMu.Unlock()
|
||||
return scope, nil
|
||||
}
|
||||
r.translatedScopeMu.Unlock()
|
||||
|
||||
resolveCtx, cancel := context.WithTimeout(context.Background(), scrapedScopeResolveTimeout)
|
||||
defer cancel()
|
||||
|
||||
scope, resolveErr := r.resolveTranslatedNoticesScope(resolveCtx)
|
||||
if resolveErr != nil {
|
||||
if r.logger != nil {
|
||||
r.logger.Warn("MinIO translation scope unavailable, using metrics counter fallback for dashboard statistics", map[string]interface{}{
|
||||
"error": resolveErr.Error(),
|
||||
})
|
||||
}
|
||||
return translatedNoticesScope{}, nil
|
||||
}
|
||||
|
||||
r.translatedScopeMu.Lock()
|
||||
r.translatedScope = scope
|
||||
r.translatedScopeExpiry = time.Now().Add(scrapedScopeCacheTTL)
|
||||
r.translatedScopeCached = true
|
||||
r.translatedScopeMu.Unlock()
|
||||
|
||||
return scope, nil
|
||||
})
|
||||
if err != nil {
|
||||
return translatedNoticesScope{}, err
|
||||
}
|
||||
|
||||
return v.(translatedNoticesScope), nil
|
||||
}
|
||||
|
||||
func (r *repository) resolveTranslatedNoticesScope(ctx context.Context) (translatedNoticesScope, error) {
|
||||
if r.procedureLister == nil {
|
||||
return translatedNoticesScope{}, nil
|
||||
}
|
||||
scanner, ok := r.procedureLister.(translatedNoticesScanner)
|
||||
if !ok {
|
||||
return translatedNoticesScope{}, nil
|
||||
}
|
||||
|
||||
dailyCounts, total, err := scanner.ScanTranslatedNotices(ctx)
|
||||
if err != nil {
|
||||
return translatedNoticesScope{}, err
|
||||
}
|
||||
|
||||
return translatedNoticesScope{
|
||||
fromMinIO: true,
|
||||
dailyCounts: dailyCounts,
|
||||
totalCount: total,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (r *repository) totalScrapedTenders(ctx context.Context, scope scrapedTendersScope) (int64, error) {
|
||||
if scope.zero {
|
||||
return 0, nil
|
||||
|
||||
Reference in New Issue
Block a user