[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: [sdx-users] débrancher la session?
From: |
Frédéric Glorieux |
Subject: |
Re: [sdx-users] débrancher la session? |
Date: |
Mon, 12 Sep 2005 10:45:50 +0200 |
User-agent: |
Mozilla Thunderbird 1.0 (Windows/20041206) |
Bonjour,
Est-ce qu'il serait possible de débrancher complètement
le mécanisme de session dans SDX (idéalement, au niveau
d'une application; à défaut, au niveau de SDX)?
De manière simple, non, car c'est un fondement applicatif de SDX. Par
contre, pour le problème que vous rapportez (et que vous avez déjà très
bien décrit), je ne pense pas que la suppression de la session soit une
solution, ni non plus que la session pose problème à une solution.
Ce qu'il faut donc, c'est que certaines URI soit mises en cache. Cocoon
a un mécanisme natif de cache parfaitement adapté à ce genre de choses
(ex: les étapes de transformations dans le pipeline), à la réserve que,
par défaut, une page dynamique (XSP) n'est pas mise en cache car Cocoon.
Il ne peut savoir par défaut sur quel critère il faudrait sauvegarder ce
qui est généré. Cela vous demande de rentrer un peu dans les entrailles
de cocoon, soyez certain que ce ne sera pas un mauvais investissement
pour vos applications.
Une rare référence sur ce sujet
<http://wiki.apache.org/cocoon/XSPCachingWithCocoonHEAD>
ou les sources des générateurs
peut-être que Sylvain Wallez saura apporter plus de précisions.
L'idée est que, pour cacher un état d'un tuyau (ici le générateur xsp),
Cocoon doit avoir un identifiant du XML à sauvegarder, autrement dit, la
XSP doit savoir monter une clé unique pour toutes les pages différentes
qu'elle peut générer. C'est clairement dépendant de chaque application.
Une solution générique au niveau de SDX serait non seulement longue à
monter (il faudrait par exemple tenir compte de toutes les bases citées,
les paramètres pouvant entrer dans les requêtes, etc), mais en plus,
potentiellement sans gros avantage. En effet sur le principe, les
requêtes utilisateur sont généralement très variées, SDX n'est pas
dimensionné comme un Google qui peut faire des économies d'échelle sur
les requêtes souvent demandées.
Deuxième aspect, Cocoon doit savoir jusqu'à quand ce XML caché est
valide. En général, il ne l'est plus si l'XSP a changé, ou si d'autres
ressources nécessaires ont été modifiées, pour nous, si une base a
changé. A ce propos, on a implémenté quelque chose dans la branche HEAD
de sdx qui sait dire si une base a été modifiée. En réalité, c'est loin
d'être une solution miracle, par exemple, si SDX est utilisé en
alimentation continue, les bases changent tout le temps, ce qui fait
perdre tout avantage à une cache regénérée à chaque fois. Ce qui m'a
réussi à cet endroit, c'est l'action clear-cache, accessible en
administration, qui permet de laisser regénérer une page d'accueil à la
demande. Selon le process de l'appli, l'xsp peut très bien s'invalider
tous les jours, les premiers du matin auront des pages un peu lentes,
mais le gain en performance est ensuite énorme. J'ai eu un cas 1 à 2
secondes en génération, 30ms en cache. Pour des tampons de 1 à plusieurs
minutes (nécessaire pour site à gros traffic), penser alors plutôt
mod_cache Apache, bien documenter sur les listes Cocoon.
Passons à un cas testé
J'ai des ressources indexées dans une arborescence (ex: système
fichiers), et je voudrais conserver l'information de cette hiérarchie
pour offrir une navigation par dossiers. L'avantage de SDX, c'est que je
peux paginer si un dossier contient 2000 ressources, offrir divers
filtres. Gros inconvénients de sdx, si j'affiche tous les
enregistrements du dossier /dossier/, je les attends dans l'ordre des
noms (path=/dossier/001), d'où un "sort" qui peut être très dissuasif.
Le pipeline en sitemap
<!-- directory d'une collection -->
<map:pipeline type="caching">
<map:match pattern="**dir.xml">
<map:generate type="xsp" src="{global:actions}dir.xsp">
<map:parameter name="dir" value="/{1}"/>
</map:generate>
<map:serialize type="debug"/>
</map:match>
</map:pipeline>
Le corps de mon xsp
<sdx:page>
<xsp:logic>String dir=parameters.getParameter("dir", "/");</xsp:logic>
<sdx:executeSimpleQuery ff="folder" hilite="true" fvString="dir"
hppSession="hpp" query="sdxall:1">
<sdx:sort field="path"/>
</sdx:executeSimpleQuery>
</sdx:page>
Dans l'état, cela ne peut pas être caché, mais les principe de clé et
validité peuvent être implémenté ainsi
<?xml version="1.0" encoding="UTF-8"?>
<xsp:page
language="java"
xmlns:xsp="http://apache.org/xsp"
xmlns:sdx="http://www.culture.gouv.fr/ns/sdx/sdx"
xmlns="http://www.w3.org/1999/xhtml"
>
<xsp:structure>
<xsp:include>java.text.SimpleDateFormat</xsp:include>
<xsp:include>java.util.Comparator</xsp:include>
<xsp:include>java.io.FileFilter</xsp:include>
<xsp:include>java.util.Arrays</xsp:include>
<xsp:include>java.net.URI</xsp:include>
<xsp:include>java.net.URL</xsp:include>
<xsp:include>org.apache.excalibur.source.SourceValidity</xsp:include>
<xsp:include>org.apache.excalibur.source.impl.validity.AggregatedValidity</xsp:include>
<xsp:include>org.apache.excalibur.source.impl.validity.FileTimeStampValidity</xsp:include>
<xsp:include>org.apache.excalibur.source.impl.validity.ExpiresValidity</xsp:include>
<xsp:include>org.apache.excalibur.source.Source</xsp:include>
<xsp:include>org.apache.excalibur.source.SourceResolver</xsp:include>
</xsp:structure>
<xsp:logic><![CDATA[
/** l'objet validité agrège le fichier xsp et les bases de
l'application */
AggregatedValidity validity;
/** The input source, je fais pareil que cocoon */
protected Source inputSource;
// Méthode appellée par Cocoon pour voir si cette page est
encore valide
public SourceValidity getValidity() {
// Si validité déjà construite, la retourner, sinon la faire
if (this.validity != null) return this.validity;
else try {
// la validité doit dire, regénérer si l'une des bases a
changé, et si le fichier xsp a changé
validity=new AggregatedValidity();
// ici, il faut mettre le chemin de son xsp, relativement au
sitemap
// coocon a l'air de bien résoudre les path
inputSource = super.resolver.resolveURI("actions/dir.xsp");
// pour bien vérifier que cocoon arrive à faire un
FileTimeStampValidity,
// donc que c'est le bon fichier
// System.out.println(this.inputSource.getValidity());
validity.add(this.inputSource.getValidity());
// validité de l'application
// à noter, on peut probablement s'en passer,
// dès lors que la page d'administration fait un clear-cache
// le répertoire de l'application en cours
Enumeration enum = new java.util.StringTokenizer
(request.getServletPath(), "/");
String
app=((java.util.StringTokenizer)enum).nextToken();
// permet de vérifier que l'on cherche dans
la bonne appli,
// permet de vérifier que la méthode est appelée ( !!
<map:pipeline type="caching"/> !!)
// System.out.println(app);
validity.add( ( (FrameworkImpl)manager.lookup( Framework.ROLE
)).getApplicationByPath(app).getSourceValidity());
return this.validity;
}
catch ( Exception e ) {
return null;
}
return null;
}
// Méthode pour identifier cette page dans la gestion de la
cache
// le point critique
public Serializable getKey()
{
// le qid n'a aucun intérêt pour faire une clé de cache
// puisque relatif à l'utilisateur
// l'intitulé de requête n'est pas optimal, mais bon
// par contre il faut absolument le repasser de page en page
String q=request.getParameter("q");
if (q!=null && !"".equals(q)) q="&q="+q;
else q="";
// une page différente par page de navigation demandée
String p=request.getParameter("p");
if (p!=null)p="&p="+p;
else p="";
// différence selon le nombre de résultats par page
Session session=request.getSession();
String hpp=request.getParameter("hpp");
if (hpp == null && session != null)
hpp=(String)session.getAttribute("hpp");
if (hpp != null) hpp="&hpp="+hpp;
else hpp="";
// la clé est construite comme une pseudo URI relative à cocoon
String key= request.getRequestURI() + q + p + hpp;
// pour deboguage, permet de vérifier sa clé
// System.out.println(key);
return key;
}
]]></xsp:logic>
<sdx:page/>
En souhaitant que cette proposition vous donne des idées.
Évidemment on peut ne pas utiliser les sessions sans les
débrancher, mais alors elles sont créées quand même, etc.,
donc il serait plus intéressant de "couper le circuit",
si c'est possible: l'est-ce?
Cdt,
EB
--- explication de la demande ---
Outre la gestion des utilisateurs, la session fournit
surtout la mise en cache des résultats de requête, de
sorte que les pages successives d'une requête ne donnent
pas lieu à une nouvelle recherche.
Elle est utilisée aussi pour le hilite et le parcours
du jeu de résultat (de résultat en résultat).
Toutefois, dans plusieurs applications les requêtes
toujours identiques (lancées par des liens) représentent
plus de 95% des requêtes par rapport aux vraies recherches;
dès lors il semble plus intéressant de cacher la totalité
des pages de la requête pour tous les utilisateurs, que
les résultats de chaque requête de chaque utilisateur.
Par exemple, (à corpus identique) la page
rech.xsp?q=toto&p=27
ne change jamais (durée de validité=durée de vie du corpus),
tandis que la page
rech.xsp?qid=sdx_q3&p=27
est différente pour chaque utilisateur, expire, est
recréée, etc.
De plus, pour les mêmes raisons, la première url peut
être bookmarquée et restera toujours valide, tandis que
la seconde ne peut pas l'être, et si elle l'est ramènera
sur une page vide.
Pour le reste:
- la navigation de résultat en résultat est peu utilisée
(dans mon expérience) car les utilisateurs n'y sont pas
habitués
- la gestion des utilisateurs est rarement nécessaire;
- seul le hilite serait intéressant à conserver mais il
y a peut-être un autre moyen (utiliser directement
les termes présents dans les paramètres de requête?)
- ... autres utilisations de la session?
_______________________________________________
sdx-users mailing list
address@hidden
http://lists.nongnu.org/mailman/listinfo/sdx-users
--
Frédéric Glorieux (AJLSM, http://ajlsm.com)