2023-06-25 19:24:05 +02:00
|
|
|
// SPDX-FileCopyrightText: Copyright The Miniflux Authors. All rights reserved.
|
|
|
|
// SPDX-License-Identifier: Apache-2.0
|
|
|
|
|
2023-08-11 04:46:45 +02:00
|
|
|
package cli // import "miniflux.app/v2/internal/cli"
|
2023-06-25 19:24:05 +02:00
|
|
|
|
|
|
|
import (
|
2023-09-25 01:32:09 +02:00
|
|
|
"log/slog"
|
2023-06-25 19:24:05 +02:00
|
|
|
"sync"
|
|
|
|
"time"
|
|
|
|
|
2023-08-11 04:46:45 +02:00
|
|
|
"miniflux.app/v2/internal/config"
|
|
|
|
"miniflux.app/v2/internal/model"
|
|
|
|
feedHandler "miniflux.app/v2/internal/reader/handler"
|
|
|
|
"miniflux.app/v2/internal/storage"
|
2023-06-25 19:24:05 +02:00
|
|
|
)
|
|
|
|
|
2023-06-25 20:23:23 +02:00
|
|
|
func refreshFeeds(store *storage.Storage) {
|
2023-06-25 19:24:05 +02:00
|
|
|
var wg sync.WaitGroup
|
|
|
|
|
|
|
|
startTime := time.Now()
|
2023-10-21 00:12:02 +02:00
|
|
|
|
|
|
|
// Generate a batch of feeds for any user that has feeds to refresh.
|
|
|
|
batchBuilder := store.NewBatchBuilder()
|
|
|
|
batchBuilder.WithBatchSize(config.Opts.BatchSize())
|
|
|
|
batchBuilder.WithErrorLimit(config.Opts.PollingParsingErrorLimit())
|
|
|
|
batchBuilder.WithoutDisabledFeeds()
|
|
|
|
batchBuilder.WithNextCheckExpired()
|
|
|
|
|
|
|
|
jobs, err := batchBuilder.FetchJobs()
|
2023-06-25 19:24:05 +02:00
|
|
|
if err != nil {
|
2023-09-25 01:32:09 +02:00
|
|
|
slog.Error("Unable to fetch jobs from database", slog.Any("error", err))
|
2023-10-20 22:19:21 +02:00
|
|
|
return
|
2023-06-25 19:24:05 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
nbJobs := len(jobs)
|
2023-09-25 01:32:09 +02:00
|
|
|
|
|
|
|
slog.Info("Created a batch of feeds",
|
|
|
|
slog.Int("nb_jobs", nbJobs),
|
|
|
|
slog.Int("batch_size", config.Opts.BatchSize()),
|
|
|
|
)
|
|
|
|
|
2023-06-25 19:24:05 +02:00
|
|
|
var jobQueue = make(chan model.Job, nbJobs)
|
|
|
|
|
2023-09-25 01:32:09 +02:00
|
|
|
slog.Info("Starting a pool of workers",
|
|
|
|
slog.Int("nb_workers", config.Opts.WorkerPoolSize()),
|
|
|
|
)
|
|
|
|
|
2024-02-29 01:01:20 +01:00
|
|
|
for i := range config.Opts.WorkerPoolSize() {
|
2023-06-25 19:24:05 +02:00
|
|
|
wg.Add(1)
|
|
|
|
go func(workerID int) {
|
|
|
|
defer wg.Done()
|
|
|
|
for job := range jobQueue {
|
2023-09-25 01:32:09 +02:00
|
|
|
slog.Info("Refreshing feed",
|
|
|
|
slog.Int64("feed_id", job.FeedID),
|
|
|
|
slog.Int64("user_id", job.UserID),
|
|
|
|
slog.Int("worker_id", workerID),
|
|
|
|
)
|
|
|
|
|
2024-01-11 06:23:38 +01:00
|
|
|
if localizedError := feedHandler.RefreshFeed(store, job.UserID, job.FeedID, false); localizedError != nil {
|
2023-10-20 22:19:21 +02:00
|
|
|
slog.Warn("Unable to refresh feed",
|
2023-09-25 01:32:09 +02:00
|
|
|
slog.Int64("feed_id", job.FeedID),
|
|
|
|
slog.Int64("user_id", job.UserID),
|
2023-11-01 19:28:24 +01:00
|
|
|
slog.Any("error", localizedError.Error()),
|
2023-09-25 01:32:09 +02:00
|
|
|
)
|
2023-06-25 19:24:05 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}(i)
|
|
|
|
}
|
|
|
|
|
|
|
|
for _, job := range jobs {
|
|
|
|
jobQueue <- job
|
|
|
|
}
|
|
|
|
close(jobQueue)
|
|
|
|
|
|
|
|
wg.Wait()
|
2023-09-25 01:32:09 +02:00
|
|
|
|
|
|
|
slog.Info("Refreshed a batch of feeds",
|
|
|
|
slog.Int("nb_feeds", nbJobs),
|
|
|
|
slog.String("duration", time.Since(startTime).String()),
|
|
|
|
)
|
2023-06-25 19:24:05 +02:00
|
|
|
}
|