# Задача "Фетчинг RSS фидов"
Это нужно для того, чтобы:
- содержимое фида загружалось быстро (для тех фидов, которые очень долго грузятся, например, фид с названием "National")
- пользователь мог видеть более ранние посты в фиде (сейчас мы не храним содержимое фида на сервере)
## Требования
- Получение наиболее актуального состояния фида
- Быстрое получение первой порции элементов фида на клиенте
- "Infinite" scroll фида
## Решение \#1 (на клиенте: Feedly + RSS parser)
Т.к. Feedly API имеет ограничение 500 запросов в сутки с одного ip адреса, появилась идея вынести обращения к их API на клиент.
### Получение первой порции данных
Для быстрого получения первых данных вызываются параллельно:
- getRssItems(url): запрос по прямой ссылке к RSS фиду (получение RssItems)
- getStreamContents(url, count): запрос содержимого стрима (StreamItems) в Feedly API: `GET https://cloud.feedly.com/v3/streams/contents?streamId=feed/{FEED_URL}&count={COUNT}`
Каждый из двух запросов делается с timeout 3-5s.
### Объединение полученных данных (mergeItems)
В ходе тестирования Feedly API было замечено, что содержимое стримов не является актуальным: иногда нет постов за последние 12-24 часа.
Для решения этой проблемы необходимо объединить полученные данные:
- сортируем RssItems по убыванию времени публикации
- из RssItems берем все элементы, которые опубликованы позже, чем StreamItems[0]
- объединяем полученные элементы и StreamItems
Если StreamItems пустой или не удалось их получить, то возвращаем отсортированный массив RssItems.
### Трекинг успешных открытий и ошибок (sendEvent)
Если не удалось загрузить ни RssItems, ни StreamItems - клиент шлет событие "fail" в Fulldive API. В ином случае клиент запрашивает метаданные по фиду у Feedly (пример, `GET https://cloud.feedly.com/v3/feeds/feed%2Fhttp%3A%2F%2Frss.cnn.com%2Frss%2Fcnn_topstories.rss`) и в событии "success" высылает метаданные и текущую локаль пользователя.
События "fail" позволят отключить фид по достижению порогового значения в данной локали. А события "success" позволят выявлять наиболее популярные фиды в данной локали (по числу успешных открытий).
Предлагается добавить роут в нашем API для обработки этих событий:
```
POST /v4/sources/:sourceId/requests
```
Fail event body
```jsonld=
{
"type": "fail",
"locale": {
"country": "us",
"language": "en"
}
}
```
Success event body
```jsonld=
{
"type": "success",
"source": {
"title": "...",
"language": "..." // optional
},
"locale": {
"country": "us",
"language": "en"
}
}
```
**Контракт роута необходимо обсудить!**
### Infinite scroll
Для бесконечного скролла фида используется Feedly API: запрос `GET https://cloud.feedly.com/v3/streams/contents?streamId=feed/{FEED_URL}&count={COUNT}&continuation={CONTINUATION}` Continuation необходимо брать из ответа на предыдущий подобный запрос (подробнее [тут](https://developer.feedly.com/v3/streams/))
Также надо учесть случай, когда исчерпается квота в 500 запросов и сервер начнет отдавать "429 Too many requests".
На диграмме наглядно представлен вышеописанный процесс:

### Class StreamItem
- originId (item's url)
- published (timestamp in ms)
- title (optional)
- author (optional)
- language (optional)
- enclosure (array of images)
### Class FeedMetadata
- id
- title
- language (optional)
- topics (optional)
Плюсы:
- возможность получать недоступные ранее фиды
- возможность сортировки по количеству открытий фида (по сути популярность фида)
- возможность отключения фида в локали
Минусы
- необходима реализация на iOS / Android
## Решение \#2 (на сервере: Feedly + RSS parser)
Клиент запрашивает содержимое фидов через Fulldive API, который собирает ответ на запрос из данных, полученных от Feedly API и данных парсинга RSS xml-файла (по тому же самому принципу, что и Решение #1)
Плюсы:
- нетривиальная логика реализована один раз на сервере
Минусы:
- ограничение в использовании Feedly API
- платим за трафик
На данный момент неизвестны доступные квоты на запросы в Enterprise плане Feedly.
Рассмотреть https://www.inoreader.com/developers/ (очень похож на Feedly) - 50,000 requests per day for $50 yearly
## Решение \#3 (на клиенте: RSS parser)
Клиент самостоятельно парсит RSS xml файл и отрисовывает полученние элементы фида.
Данное решение реализовано и используется в настоящий момент.
Плюсы:
- уже готово
Минусы:
- некоторые фиды не открываются в некоторых локалях или открываются очень долго
- достаточно маленькое количество элементов в фиде
# Задачи "Мониторинг доступности RSS фидов"
Это нужно для того, чтобы:
- пользователь видел только доступные ему фиды (которые скорее всего загрузятся у него) -> нет неработающих фидов
## Требования
## Решение \#1 (CronJob на основе статистики ошибок и открытий фидов, собранной с клиентов)
CronJob агрегирует события открытий фидов (fail / success) по (sourceId, locale). Фиды с большим процентом событий типа "fail" отключаются.
## Решение \#2 (CronJob на основе доступности фида с сервера)
CronJob по расписанию пингует с сервера все фиды и отключает недоступные.
Плюсы:
- отсутствие зависимостей 3rd-party сервисов (Feedly)
Минусы:
- много фидов долго грузятся и не успевают даже при timeout=15s
- фиды, доступные в локали пингующего сервера, могут быть недоступны в других локалях
# Задача "Получение топ фидов / фидов по категориям"
## TODO
- Наиболее популярные фиды для данной локали: рассчитывать score / internalScore на основе количества людей использующих фид и сортировать по нему
- Разметить фиды по категориям (topics)
- Отсутствие дубликатов фидов в выдаче
# Идеи по RSS фидам в целом
- Показывать время публикации поста в фиде вместо домена, т.к. для RSS фида у всех постов по идее один и тот же домен?
- Сделать названия топовых фидов покороче, чтобы в интерфейсе было легче переключаться между табами ("CNN.com - RSS Channel - HP Hero" -> "CNN.com")
# Интеграция с внешним провайдером
- Первый месяц мы скачиваем метаданные фидов (Feedly / Inoreader). Дальнейшее использование сервиса направлено в основном на увеличение доступности фидов в тех локалях, где по прямым ссылкам они недоступны.
# Что можно сделать без интеграции с внешним провайдером
(А надо ли это все с 20 RPS? Как это поможет?)
- Выключить фиды, которые недоступны из разных локаций
- Проверяется с помощью VPN
- Известны 400 фидов, которые не работают из России и США
- Клиенты: протестировать/пофиксить парсинг фидов
- Трекинг доступности фида
- Клиент отправляет статус загрузки фида (успех/фейл)
- Клиент смог или не смог показать фид (проблемы парсинга)
- Сервер прячет то, что не получается скачать с каким-то порогом
- А прячет ли то, что не парсит определенная версия клиента?
- (опционально) Трекинг просмотра (может быть, есть смысл разделить)
- Прочитать != загрузить
- Клиент открывает табу — сервер считает популярность фидов
- Сервер тащит/парсит все РСС из базы, делает по аналогии с фидами от ТВБС
- формирует файлы фидов
- по 100 постов (например)
- как с ТВБС: кладет в бакет, кэширует в CDN
- Сервер медленно (за деньги — быстро) скачивает каталог фидов из провайдера (фидли,иноридер) и наполнять базу категориями и фидами