Reader RSS simple et efficace

Hello,

Vue la discussion sans fin sur quel est le meilleur remplaçant pour Reader (http://forum.geekzone.fr/t/quel-lecteur-web-de-flux-rss/50327quel-lecteur-web-de-flux-rss/page-7), et vu que pour l’instant je ne suis convaincu par aucun, à part theoldreader mais vu qu’ils galèrent et qu’il va passer en privé, je me demandais comment concevoir un lecteur RSS web aujourd’hui. Je ne sais pas si je me lancerais dedans, mais si je le faisais ce serait sous forme de projet open source.
En gros, le cahier des charges serait :

  • Etre dispo sur tout terminal web moderne (la cible c'est les gens qui n'utilisent plus IE8-) avec une interface claire et responsive
  • Un état unique (flux, historique, préférences, articles lus/non lus) quelque soit le terminal depuis lequel on se connecte
  • Ne rien coûter côté serveur en terme de stockage ou de CPU (ouais ouais je sais, attendez ne partez pas  :tongue2: ), vue la mésaventure de TOR
Vu où je poste, vous avez deviné que je pense à une appli web. Aujourd'hui, pour arroser tous les terminaux ya pas mieux. Si je veux que le nombre de clients n'ai pas ou peu d'impact sur les ressources du serveur, il faut que la quasi-totalité de la logique soit côté client.

Problème principal 1 : Comment faire la synchronisation entre les différents terminaux sans coûter un bras côté serveur ?

On a deux trucs supers avec Chrome et Firefox : le localStorage et la synchronization. Seulement on ne peut pas aujourd’hui synchroniser le localStorage.
Chrome propose une API assez proche, chrome.storage, qui permet une synchronisation. Par contre ça restreint l’usage à Chrome uniquement.

Problème principal 2 : Sur les terminaux mobiles, si c’est le client qui parse tous les flux RSS, ça risque de mettre une plombe voir d’être inutilisable vu le nombre de requêtes à lancer.

On pourrait proposer de n’actualiser les flux que lorsqu’on est en wifi par exemple, et permettre de marquer les articles à lire offline. Personnellement quand je suis sur le téléphone, je lis les flux instantannés comme Twitter/FB/mails plutôt que les flux à longues durées de vie comme les RSS.

Qu’est-ce que vous en pensez ? Est-ce que vous voyez de meilleures solutions ?

Idée intéressante. Sur la partie technique :

  • backend
    • ElasticSearch sur Lucène pour la base de données de flux RSS (sous forme de documents XML ou JSON)
      • utilisation de la River RSS pour pull les flux
    • MariaDB (SQL classique) pour la base utilisateurs (tout ce qui est authentification, sauvegarde des URL de flux etc.)
  • services
    • serveur HTTP "maison" en Go, avec différents modules
      • gestion des connexions (identification, authentification)
      • gestion des abonnements
      • gestion de son profil (mot de passe, email)
      • stats techniques (charge serveur, fréquentation)
      • stats fonctionnelles (proposition de nouveaux flux, flux les plus populaires etc.)
    • Google enteprise (email, G+, aide pour le référencement, stats)
  • HTML5/CSS3 + JS/JQuery*
    • quasi-gratuitement ça donne le Web et le Web mobile (JQuery mobile)
    • pour pas cher ça donne aussi l'app mobile iOS et Android (basée sur une web view avec quelques fonctionnalités natives)
    • via un peu de .NET et d'API Microsoft ça donne aussi l'app modern UI pour Windows 8
    • je connais pas les Windows phone, mais je pense que ça suit le même mouvement
    • bonnes pratiques de mobilité (cache LocalStorage pour gérer les actions utilisateur en cas de déconnexion, sprites/minification pour réduire les aller-retour serveur)


Perso, quand je lis des news, je reviens rarement dans le passé pour relire quelque chose que j'ai laissé de côté. D'ailleurs c'est un reproche que je fais à News Bento : quand je coche un article comme lu, il n'y a que celui là qui est grisé. C'est la fonctionnalité attendue, mais pas celle que je préfèrerais. Personnellement je pense qu'un flux RSS c'est avant tout justement un "flux". Un peu comme dans un dépôt Git, revenir dans le passé devrait être le cas rare, pas le cas nominal. Pour moi il faut qu'à la fin de ma séance de lecture l'outil se souvienne de tous les articles que j'ai lu, et grise tout jusqu'au plus récent lu.

Du coup techniquement ça revient à stocker une tête de lecture par flux. Autrement dit, un ID de la base (Lucene dans mon exemple) par flux auquel je suis abonné. A synchroniser ça devient du coup très très simple : LocalStorage tant que je suis hors-ligne, et réconciliation avec la base (MariaDB dans mon exemple) dès que le réseau revient.

Ca me rappelle ce message.

Côté serveurs, le but est bien de ne pas stocker la masse de données des utilisateurs. On pourrait quasiment se contenter de servir quelques fichiers statiques. Pas de stats, pas d’identification, etc. L’idée est de déléguer aux browsers la synchronisation du localStorage entre les terminaux, et de les laisser bosser pour l’acutalisation des flux !
Le choix de jQuery+jQueryMobile/Angular/MooTools/etc assez accessoire je pense, ça dépend surtout des préférences des dev.

Un problème que vous allez rencontrer est la fréquence d’update des flux. Si vous le faites côté client vous n’aurez que le flux à l’instant T. En fonction du refresh d’articles et de la quantité d’items du flux vous allez en louper, plein…

Techniquement ce n’est pas vraiment un problème avec les applis web modernes qui rafraichissent ce genre de données avec des requêtes asynchrones.
Un peu comme la shootbox de GZ par exemple qui est rafraichie régulièrement sans devoir appuyer sur F5, on peut imaginer la même chose pour raffraichir ses flux, ou comme le panel de réponse de ce forum qui sauvegarde automatiquement un brouillon toutes les x secondes, on peut imaginer un truc équivalent pour sauvegarder les articles lus.

[quote=“SkullyFM, post:5, topic: 55185”][/quote]

Ah ouais je n’avais pas vu ça. On va rencontrer ce problème sur les flux les plus intenses, genre AFP/Le Monde/01 etc.
Je pense que ça pourrait quand même être une limite acceptable. On pourrait fixer une limite du nombre d’'entrée affichées paramétrable par flux, avec une valeur par défaut raisonable à 50 par exemple.
Après, on peut ajouter à l’appli la possibilité de bookmarker un article à lire plus tard, dans ce cas on garde le titre, le lien et la description dans un dossier à part pour pas le perdre lorsqu’on actualise le flux longtemps après.

@Mimick oui tout se ferait en asynchrone mais le problème soulevé est plutôt que si tu mets à jour les flux uniquement lorsque tu lances l’appli, et non à intervalles réguliers comme lorsque c’est fait sur un serveur, tu peux te retrouver à fetcher les XXX derniers articles, et même en rater lorsque le flux est très verbeux et qu’il ne remonte que les XX derniers articles.

Il y a aussi la restriction côté browser: tu ne peux pas faire de requête Ajax sur un domaine autre que celui sur lequel tu es… donc impossible de récupérer directement GZ.fr/rss quand tu es par exemple sur le site de ton lecteur.
Pour ce faire il faut un proxy qui va récupérer le flux pour toi côté serveur. Il n’y a pas nécessité de stocker les articles car on peut les passer ensuite au navigateur pour qu’ils se débrouille pour l’affichage.
Pour éviter que 1000 personnes ne fassent la même requête il faut mettre un memcache qui va garder de manière temporaire le flux en RAM, cela permet aussi de faire en sorte qu’un flux populaire soit à jour même si un utilisateur ne vient que 1 ou 2 fois par semaine.
On faisait comme ça au début de Netvibes (2005-2006) mais on c’est ensuite rendu compte (2008) qu’il nous fallait notre propre backend avec des vrais crawler si on voulait rajouter des features de search…

[quote=“DrDrakeRamore, post:4, topic: 55185”][/quote]

C’est quoi la masse de données des utilisateurs ? Un login, un hash de mot de passe, un sel pour la partie admin (interface pour ajouter/supprimer une syndication) + une ligne par syndication. C’est rien. Même avec des millions d’utilisateurs, c’est très facilement sécable en partitions.

Et niveau stats je ne suis pas du tout d’accord. Je trouve ça super important, à mes yeux c’est ce qui fait la valeur ajoutée d’un site ou d’une appli. Si tu sais dire qui lit quel flux, quel flux est le préféré de tel type d’utilisateur, alors tu as une chance d’en faire un business model rentable, soit via la pub ciblée, soit via des fonctionnalités freemium.

@Histrion : Le but n’est pas d’avoir un business model mais une appli libre qui marche sans avoir besoin d’avoir un serveur (chez soit ou vps ou whatever). La masse de donnée on voit ce que ça donne pour theoldreader. Plus d’1To, avec des SSD qui pètent et les galères que ça entraîne. Quand t’es une boîte avec des fonds confortables, 1To c’est pas grand chose, mais quand tu veux juste proposer un service libre tu t’orientes plutôt vers du distribué que du centralisé. :slight_smile:

@SkullyFM : Super relou le XSS, je pensais que ça ne posait problème que lorsqu’on voulait réutiliser une session/un cookie, pas un simple http get ! Comment ils font du coup par exemple avec Google Analytics et autes ?? Ils vont bien passer des données sur un autre domaine ? :confused:
Je vois qu’avec jQuery tu peux ruser en utilisant jsonp mais alors pour l’instant je saisis pas la différence. Si tu vas récupérer du XML ça marche pas, si c’est du JSON ça marche, WTF ?

Autre problème selon moi, c’est que HTTP est pas idéal pour gérer les flux: pas de notion de “donne moi la nouveauté dans ce flux”.
Avec des potes on avait commencé à réfléchir à une façon smart de faire, qui fonctionnerait à l’envers, et donc où les sources de données pusheraient les notifications vers les readers.

Parceque souvent, un article est mis à jour. Quid de sa tête dans le flux…

Bref. Sinon un lecteur très simple que j’avais vu passer sur IRC : https://github.com/tontof/kriss_feed

[quote=“DrDrakeRamore, post:10, topic: 55185”][/quote]

Je comprends totalement ton point de vue, et je suis totalement en désaccord ^^

AMHA si TheOldReader arrive a des problèmes de financement c’est que le modèle n’était pas viable. Tu peux avoir la meilleure techno, si c’est pas financé, ça a peu de chances de survivre. Du coup, penser financement (business model) c’est s’assurer de payer les serveurs. Même sans but lucratif.

Après, pour ce que tu souhaites comme expérience utilisateur, je suis 100% d’accord. Il faut un truc le plus simple possible. L’idéal c’est le Web / Web mobile : zéro logiciel à installer. Avec JS/JQuery qui arrivent à maturité c’est clairement possible.

Ah oui merci pour ces précisions, du coup je comprends mieux les contraintes.
Même si on veut monter sa propre appli web il faudrait faire des appels AJAX sur un serveur qui nous appartient, ça limite le côté distribué.

Par contre si on veut limiter au maximum les infos stockées sur le serveur, de quoi a-t-on besoin? Dans ce cas je dirais que le serveur pourrait utiliser la date du dernier article récupéré, date donnée par le client. Il faudrait que le serveur streame le flux pour s’arrêter de récupérer les infos dès qu’un article est plus ancien que cette date. Lorsque la page est entièrement rafraichie, il faudrait charger les X derniers articles de chaque flux.

Côté serveur, il faudrait stocker au minimum les articles lus, sans ça je ne sais pas comment synchroniser les différents appareils. Ceci demande donc une gestion d’utilisateurs.

Pour AJAX et le JSON, arrêtez moi si je me trompe mais le HTTPrequest qui est l’outil habituel pour les requêtes asynchrone ne permet effectivement pas de faire des requêtes sur n’importe quel serveur. Par contre il y a un moyen de tricher et de faire de l’AJAX même avec des navigateurs préhistoriques, du moment qu’ils supportent le javascript. En effet on peut rajouter une balise javascript à la volée grace à du code javascript. Du code qui écrit du code en somme. Si la nouvelle balise exécute un fichier .js, il suffit que le serveur le mette à jour pour avoir de l’AJAX, du coup tant qu’à faire autant que les données soient en JSON directement plutôt que du XML. Je suppose que c’est comme ça qu’on passe cette barrière de l’AJAX sur un autre domaine en faisant du JSON plutôt que du XML.

Après ce n’est qu’une supposition.

[quote=“Mimick, post:13, topic: 55185”][/quote]

Je pense que tu parles de JSONP. Si c’est ça, c’est à implémenter côté serveur.

C.-à-d. que c’est au serveur de renvoyer le bout de code JS à exécuter (en général un simple appel à une fonction callback, dont le nom est même généralement passé à l’appel au serveur). Ca fonctionne en cross-domain et c’est considéré comme sûr parce que c’est un contrat fort entre le client et le serveur, qui ne peut pas injecter de code non souhaité (s’il essaie d’appeler autre chose que “callback”, il y aura juste une erreur).

Exemple :

Client :

  • possède une fonction “callback”
  • appelle en JSONP un serveur cross-domain et lui dit de répondre en appelant “callback”

Serveur :

  • traite la requêtre, et répond avec un bout de JS qui appelle “callback” (la vraie réponse ce sont les arguments passés à “callback” dans ce bout de JS)


    [quote=“fser, post:11, topic: 55185”][/quote]

C’est le contraire (ou j’ai mal compris ce que tu veux dire). HTTP c’est justement presque entièrement pensé pour gérer du contenu qui évolue. Et ça s’utilise par exemple très très bien pour gérer des caches.

Il n’y a qu’à voir les code de retour HTTP pour s’en rendre compte :
http://en.wikipedia.org/wiki/HTTP_code

Par contre ça n’est pas fait pour être en flux poussé (push), mais plutôt en flux tiré (pull) : c’est au client de régulièrement interroger le serveur pour obtenir des màj.

Le contraire est possible, mais encore très rarement mis en oeuvre (une des solutions, du W3C, s’appelle les Websockets : http://www.w3.org/TR/2009/WD-websockets-20091029/). Avec l’évolution du Web ce genre de choses arriveront peut-être à maturité, mais c’est pour l’instant plutôt un gros tas de solutions propriétaires pas réjouissantes…

Non c’était pas aussi chiadé dans mon esprit, mais c’est bien j’apprend des trucs. ^^

On se retrouve avec un proxy, c’est obligé, ok. Du coup on perd quand même pas mal de vue l’objectif de la solution 100% client-side, qui n’est pas réaliste. Même optimisé, un proxy va bouffer de la bande passante et du CPU en fonction du nombre d’utilisateurs et de flux. On peut gérer un cache, sans tout stocker, mais un redémarrage du serveur va plomber les perfs. Du coup est-ce qu’il ne vaut pas mieux de toute façon stocker les flux dans une base ? Mais on en revient aux archis classiques.

Ce qu’on gagne quand même avec l’utilisation du chrome.storage et son sync, c’est l’absence de stockage de tous les articles lus/non-lus pour chaque utilisateur, et les I/O qui vont avec. On n’a même toujours pas besoin d’une authentification. L’inconvénient est que ce n’est supporté que par Chrome. :cassetete:

Pour revenir à l’objectif initial ce qu’il faudrait c’est un coup de génie pour récupérer les flux depuis le client, mais si ça existait ce serait sans doute un hack.

[quote=“fser, post:11, topic: 55185”][/quote]

Pour le HTTP il y a la notion de ETag qui est pas mal utilisée par les aggrégateurs pour éviter de recharger des flux entiers pour rien…

@histirion et skullyFM : le problème que j’identifie dans HTTP, c’est la granularité du résultat.
Imaginons qu’un serveur nous serve les 20 derniers articles sous le nom last-articles.xml

ok le browser GET last-articles, le cache fonctionne etc …

Puis, une mise à jour survient sur le site. +1 article. On en a donc encore 19 de valides, et 1 à mettre à jour.
Le client va donc faire un GET (eventuellement avec un ETag pour savoir si ça a changé). Le serveur va lui répondre que “oui vient, ça a plus rien à voir!”. En fait, il n’y a eu qu’un changement. Il va quand même valloir se palucher le traitement des 20 et se rendre compte qu’on a déjà 19 des 20.

Mais en terme de bande passante, c’est dommage.

Pour l’aspect “push” , c’était bien ce que j’avais en tête. Encore que l’on se pose la question de savoir ce qui est le mieux côté serveur : un pool énorme de connexions en iddle, ou du keepalive sur un pool “changeant” de clients?

Je sais que c’est old-school de lire les RFC et les spécifications, mais celles de HTTP sont super bien foutues, et contiennent des pépites pour tout un tas de cas pratiques.

http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html

Regarde le §14.16 sur le header “Content-Range” pour la méthode GET.

Et la manière dont ça évolue (mais tu peux gérer ça pareil avec des headers maison en attendant mieux) :

http://greenbytes.de/tech/webdav/draft-ietf-httpbis-p5-range-latest.html

(je sais, je lag à répondre, sorry).

Oui en HTTP 1.1 tu peux demander des bouts de pages. Mais sérieux? Pour un flux rss de texte?
“ah t’as été modifié? Bon en moyenne, tu dois faire 200k de texte, avec 10k de header … bon au pif je vais demander un content range de 10-200, et voir si ça passe la moulinette de validation!”