IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

WinDev Discussion :

Système de sessions, voir qui est connecté à une appli [WD17]


Sujet :

WinDev

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre éclairé Avatar de droliprane
    Homme Profil pro
    Architecte de système d'information
    Inscrit en
    Mai 2005
    Messages
    710
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Vendée (Pays de la Loire)

    Informations professionnelles :
    Activité : Architecte de système d'information
    Secteur : Industrie

    Informations forums :
    Inscription : Mai 2005
    Messages : 710
    Par défaut Système de sessions, voir qui est connecté à une appli
    Bonjour à tous,

    j'ai mis en place un module de supervision des utilisateurs connectés sur mon appli de gpao.
    aujourd'hui que l'appli est vraiment utilisée (une vingtaine d'utilisateurs), je me rends compte que ça ne fonctionne pas correctement.

    Voici comment je m'y prends :

    J'ai une table logg dans ma base SQL Server qui contient les champs suivants :
    - log_session_id, int champs auto (identifiant de session)
    - log_uid, int (identifiant de l'utilisateur)
    - log_ip_address (IP du poste client)
    - log_start (debut de session)
    - log_last_update (dernière activité)
    - log_end (fin de la session suite à déconnexion ou à purge)

    Quand un utilisateur ouvre une session sur la gpao, alors j'exécute la procédure declareSession() :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
     
    tic est une DateHeure = DateHeureSys()
     
    // création de l'entrée dans la table logg
    HRAZ(logg)
    logg.log_start = tic
    logg.log_last_refresh = tic
    logg.log_uid = FEN_START.uid
    logg.log_ip_address = ip_client  // je passe sur la façon dont j'obtient l'ip, ce n'est pas ce qui nous intéresse
    HAjoute(logg)
    FEN_START.sid = logg.log_session_id
    Ensuite, j'exécute toutes les 2 minutes (par un timer) la procédure updateSession() qui contient un appel à la procédure stockée du même nom sur mon serveur SQL :

    appel via le timer :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    updateSession()
    SI Timer("updateSession", 100*60*2) = 0 ALORS
    	Erreur("Création du timer impossible")
    FIN

    la procédure WinDev updateSession() :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    ProcedureStockee est une Source de Données
    Sql est une chaîne = "EXECUTE [GPAO].[dbo].[updateSession] @sid=" + sid + ", @interval=5;"
    //trace(Sql)
    SI PAS HExécuteRequêteSQL(ProcedureStockee,Cnx,hRequêteSansCorrection,Sql) ALORS
    	Erreur("Erreur d'initialisation de la requête"+RC+HErreurInfo() + RC + RC + Sql)
    	RETOUR
    FIN
    HLibèreRequête(ProcedureStockee)
    Enfin, la procédure stockée SQL Server, qui va updater l'entrée de la table logg qui concerne la session en cours, et purger les entrées trop vieilles (si log_end est null et log_last_refresh est plus vieux que 5 minutes) :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    ALTER PROCEDURE [dbo].[updateSession]
    -- Add the parameters for the stored procedure here
    	@sid int,
    	@interval int
    AS
    BEGIN
    	-- SET NOCOUNT ON added to prevent extra result sets from
    	-- interfering with SELECT statements.
    	SET NOCOUNT ON;
     
    	-- d'abord on update la session en cours @sid
    	UPDATE logg SET log_last_refresh = SYSDATETIME() WHERE log_session_id = @sid
     
    	-- ensuite on purge les vieilles sessions (appli plantée, session mal fermée)
    	UPDATE logg SET log_end = SYSDATETIME() WHERE log_end is null AND datediff(s, log_last_refresh, SYSDATETIME())/60 >= @interval
     
    END
    Quand je test moi-même, en regardant évoluer log_last_refresh toutes les 2 minutes, j'ai l'impression que tout fonctionne bien. Pourtant il y a des utiisateurs connectés pour lesquels log_end a été renseigné et donc ils sont considérés comme déconnectés. Voyez-vous dans mes programmes ce qui pourrait être la cause de ça ? A priori c'est un problème d'update qui ne se fait pas et donc log_last_refresh n'évolue plus et devient trop vieux, donc un des nombreux appels à updateSession (de la part d'autres utilisateurs) fini par mettre un terme à la ligne de logg en renseignant log_end.

    D'avance merci pour toute piste qui m'aidera à faire fonctionner ce module

  2. #2
    Expert confirmé
    Homme Profil pro
    Responsable Données
    Inscrit en
    Janvier 2009
    Messages
    5 442
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 51
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations professionnelles :
    Activité : Responsable Données

    Informations forums :
    Inscription : Janvier 2009
    Messages : 5 442
    Par défaut
    Bonjour,
    Dixit l'aide en ligne:
    Conseil : Dans la majorité des cas, utilisez la fonction TimerSys.
    En effet, la fonction Timer consomme plus de ressources que la fonction TimerSys et ne fonctionne que lorsque des fenêtres WinDev sont en cours (le timer s'arrête si une boîte de message est affichée).

    Donc il faudrait essayer avec TimerSys().

    Tatayo.

  3. #3
    R&B
    R&B est déconnecté
    Membre émérite
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Mars 2005
    Messages
    571
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : France, Drôme (Rhône Alpes)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Distribution

    Informations forums :
    Inscription : Mars 2005
    Messages : 571
    Par défaut
    Dixit notre expérience, les timer, sys ou pas sont a proscrire si l'application est susceptible d'atteindre 100% CPU car dans ce cas, le timer est simplement pas exécuté.
    Solution : passer par les processus dédiés (un exe, API createprocess) ou un thread ! C'est pas la même programmation mais au moins même à 100% CPU, le processus s'exécute.

  4. #4
    Membre éclairé Avatar de droliprane
    Homme Profil pro
    Architecte de système d'information
    Inscrit en
    Mai 2005
    Messages
    710
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Vendée (Pays de la Loire)

    Informations professionnelles :
    Activité : Architecte de système d'information
    Secteur : Industrie

    Informations forums :
    Inscription : Mai 2005
    Messages : 710
    Par défaut
    ok je vais déjà tester avec un timerSys et j'arrête le timer au début de ma procédure et je le relance à la fin.
    résultats des tests demain matin, je ne peux faire des mises à jour que le soir

    sinon pour le thread je veux bien, mais donc je fais un thread secondaire qui va lancer un timer dedans ?

    j'avais aussi pensé à une petite appli connexe qui serait lancée à l'ouverture de ma gpao, un process caché, au sein duquel se feraient les updates de session, toutes les X minutes

    enfin il y a aussi le paramétrage de la procédure au niveau de WinDev, qui permet de programmer une répétition, de lancer dans un thread, etc... je me demande ce que ça vaut

    vous feriez comment ?

  5. #5
    R&B
    R&B est déconnecté
    Membre émérite
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Mars 2005
    Messages
    571
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : France, Drôme (Rhône Alpes)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Distribution

    Informations forums :
    Inscription : Mars 2005
    Messages : 571
    Par défaut
    Attention, n'empilez pas thread et timer car c'est faire deux fois la même chose !

    Vu la confusion, il vous faut étudier sérieusement les thread avant de vous lancer... Ce n'est que lorsque vous afficherez un beau "hello world il est xx:yy:zz" avec les heures minutes secondes que vous pourrez passer au stade suivant. Notez que la programmation des processus (thread) n'est pas simple, ni leur déboggage.

  6. #6
    Membre éclairé Avatar de droliprane
    Homme Profil pro
    Architecte de système d'information
    Inscrit en
    Mai 2005
    Messages
    710
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Vendée (Pays de la Loire)

    Informations professionnelles :
    Activité : Architecte de système d'information
    Secteur : Industrie

    Informations forums :
    Inscription : Mai 2005
    Messages : 710
    Par défaut
    Oh je ne fais pas vraiment de confusion, après c'est sur qu'au niveau de l'utilisation/partage du contexte mémoire il doit y avoir des différences importantes

    Mais j'ai quand même dépassé le stade de l'affichage de l'heure

    Je vois bien les deux techniques, ce que je n'ai pas, c'est l'expérience pour dire si dans telle ou telle situation il vaut mieux utiliser l'un plutôt que l'autre.

    Finalement, dans mon cas, j'ai opté pour un thread avec un threadpause, comme ça je ne me repose plus sur un timer, dont la fiabilité ne semble pas être aussi éprouvé qu'un thread

    Aussi, maintenant le client s'annonce toutes les minutes, et donc la purge des vieux logs se fait sur la base de 70 secondes

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    ProcedureStockee est une Source de Données
    Sql est une chaîne = "EXECUTE [GPAO].[dbo].[updateSession] @sid=" + FEN_START.sid + ", @interval=70;"
     
    TANTQUE Vrai
     
    	SI PAS HExécuteRequêteSQL(ProcedureStockee,Cnx,hRequêteSansCorrection,Sql) ALORS
    		//Erreur("Erreur d'initialisation de la requête"+RC+HErreurInfo() + RC + RC + Sql)
    		RETOUR
    	FIN
    	HLibèreRequête(ProcedureStockee)
     
    	ThreadPause (60 * 100) // endort le Thread 60 secondes
     
    FIN
    En local c'est nickel avec plusieurs sessions, dont certaines que je ferme à l'arrache depuis le gestionnaire de processus pour simuler un plantage ou une coupure réseau

    Demain test en prod, je vous redirai ce qu'il en est.

    La prochaine étape sera de faire un système de kill session, pour quand un utilisateur a laissé sa session TSE ouverte et que je veux faire une mise à jour.
    Je pense mettre un booleen dans un champ de la table logg, et faire que ma procédure stockée (exécutée toutes les minutes) renvoie ce même booléen de kill session, et fermer l'appli en fonction de ça (avec un message d'explication).
    Donc entre le moment où j'aurai demandé la fermeture d'une session donnée, et se fermeture effective, il se passera dans le pire des cas 60 secondes.


    Merci à vous

  7. #7
    Membre averti
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2010
    Messages
    16
    Détails du profil
    Informations personnelles :
    Sexe : Homme

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Industrie Pharmaceutique

    Informations forums :
    Inscription : Février 2010
    Messages : 16
    Par défaut
    Citation Envoyé par droliprane Voir le message
    Bonjour à tous,

    j'ai mis en place un module de supervision des utilisateurs connectés sur mon appli de gpao.
    aujourd'hui que l'appli est vraiment utilisée (une vingtaine d'utilisateurs), je me rends compte que ça ne fonctionne pas correctement.

    Voici comment je m'y prends :

    J'ai une table logg dans ma base SQL Server qui contient les champs suivants :
    - log_session_id, int champs auto (identifiant de session)
    - log_uid, int (identifiant de l'utilisateur)
    - log_ip_address (IP du poste client)
    - log_start (debut de session)
    - log_last_update (dernière activité)
    - log_end (fin de la session suite à déconnexion ou à purge)

    Quand un utilisateur ouvre une session sur la gpao, alors j'exécute la procédure declareSession() :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
     
    tic est une DateHeure = DateHeureSys()
     
    // création de l'entrée dans la table logg
    HRAZ(logg)
    logg.log_start = tic
    logg.log_last_refresh = tic
    logg.log_uid = FEN_START.uid
    logg.log_ip_address = ip_client  // je passe sur la façon dont j'obtient l'ip, ce n'est pas ce qui nous intéresse
    HAjoute(logg)
    FEN_START.sid = logg.log_session_id
    Ensuite, j'exécute toutes les 2 minutes (par un timer) la procédure updateSession() qui contient un appel à la procédure stockée du même nom sur mon serveur SQL :

    appel via le timer :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    updateSession()
    SI Timer("updateSession", 100*60*2) = 0 ALORS
    	Erreur("Création du timer impossible")
    FIN

    la procédure WinDev updateSession() :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    ProcedureStockee est une Source de Données
    Sql est une chaîne = "EXECUTE [GPAO].[dbo].[updateSession] @sid=" + sid + ", @interval=5;"
    //trace(Sql)
    SI PAS HExécuteRequêteSQL(ProcedureStockee,Cnx,hRequêteSansCorrection,Sql) ALORS
    	Erreur("Erreur d'initialisation de la requête"+RC+HErreurInfo() + RC + RC + Sql)
    	RETOUR
    FIN
    HLibèreRequête(ProcedureStockee)
    Enfin, la procédure stockée SQL Server, qui va updater l'entrée de la table logg qui concerne la session en cours, et purger les entrées trop vieilles (si log_end est null et log_last_refresh est plus vieux que 5 minutes) :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    ALTER PROCEDURE [dbo].[updateSession]
    -- Add the parameters for the stored procedure here
    	@sid int,
    	@interval int
    AS
    BEGIN
    	-- SET NOCOUNT ON added to prevent extra result sets from
    	-- interfering with SELECT statements.
    	SET NOCOUNT ON;
     
    	-- d'abord on update la session en cours @sid
    	UPDATE logg SET log_last_refresh = SYSDATETIME() WHERE log_session_id = @sid
     
    	-- ensuite on purge les vieilles sessions (appli plantée, session mal fermée)
    	UPDATE logg SET log_end = SYSDATETIME() WHERE log_end is null AND datediff(s, log_last_refresh, SYSDATETIME())/60 >= @interval
     
    END
    Quand je test moi-même, en regardant évoluer log_last_refresh toutes les 2 minutes, j'ai l'impression que tout fonctionne bien. Pourtant il y a des utiisateurs connectés pour lesquels log_end a été renseigné et donc ils sont considérés comme déconnectés. Voyez-vous dans mes programmes ce qui pourrait être la cause de ça ? A priori c'est un problème d'update qui ne se fait pas et donc log_last_refresh n'évolue plus et devient trop vieux, donc un des nombreux appels à updateSession (de la part d'autres utilisateurs) fini par mettre un terme à la ligne de logg en renseignant log_end.

    D'avance merci pour toute piste qui m'aidera à faire fonctionner ce module

    Esseyez avec le code suivant au lieu de "HExécuteRequêteSQL" :

    example:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    SI PAS SQLExec(command,"req") ALORS
    		   SQLInfoGene("req")      
          	   Erreur(SQL.MesErreur)
    	       RepriseSaisie(tab_auto)
    	FIN

  8. #8
    Membre éclairé Avatar de droliprane
    Homme Profil pro
    Architecte de système d'information
    Inscrit en
    Mai 2005
    Messages
    710
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Vendée (Pays de la Loire)

    Informations professionnelles :
    Activité : Architecte de système d'information
    Secteur : Industrie

    Informations forums :
    Inscription : Mai 2005
    Messages : 710
    Par défaut
    Pour info, j'ai modifié le principe de gestion de mes sessions de cette façon :

    j'ai maintenant un champs supplémentaire log_kill dans ma table logg, que je peux mettre à 1 depuis un module admin de mon ihm et qui flag les sessions que je veux fermer de force (par exemple quand je fais une maintenance).

    Ensuite toutes les 70 secondes l'ihm exécute une procédure stockée sql server depuis, dans laquelle je passe en argument l'identifiant de la session courante, et cette procédure va purger les sessions plus vieilles qu'un certain temps (moi je mets 60 secondes) et en même me dire si ma propre session doit se fermer.

    Voici la procédure en question :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    ALTER PROCEDURE [dbo].[updateSession]
    -- Add the parameters for the stored procedure here
    	@sid int,
    	@interval int
    AS
    BEGIN
    	SET NOCOUNT ON;
     
    	DECLARE @kill int
     
    	SELECT @kill = log_kill FROM logg WHERE log_session_id = @sid
     
    	IF @kill = 1
    		-- si je suis une session qui doit être fermée, je mets juste log_end
    		UPDATE logg SET log_end = SYSDATETIME() WHERE log_session_id = @sid
    	ELSE
    		-- sinon je réactualise log_last_refresh, et je mets null dans log_end
    		UPDATE logg SET log_last_refresh = SYSDATETIME(), log_end = null WHERE log_session_id = @sid
     
     
    	-- dans tous les cas, on purge les vieilles sessions (appli plantée, session mal fermée)
    	UPDATE logg SET log_end = SYSDATETIME() WHERE log_end is null AND datediff(s, log_last_refresh, SYSDATETIME()) >= @interval
     
    END
    Au retour de la procédure je teste la valeur kill et si kill = 1 alors j'informe l'utilisateur de la nécessité de fermer sa session, et je mets une tempo de 5s avant de fermer l'ihm.

    Ailleurs dans mon appli j'ai un booléen de maintenance qui interdit toute connexion à l'appli aux utilisateurs non root tant que ce booléen n'est pas repassé dans l'état normal.

    Avec ce système, chaque occurrence de l'appli fait le ménage toutes les 70 secondes dans les sessions qui ont pu s'interrompre anormalement (crash, coupure réseau, etc...) et en même temps je peux déclencher une opération de maintenance en déconnectant de force les utilisateurs en leur envoyant un signal de déconnexion (update log_kill = 1 where log_session_id = xxx) et je suis certain que au plus tard 70s après, l'appli n'a plus d'utilisateurs connectés.

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. [Réseau sans-fil] Connecter une camera ip sur le port éthernet de mon pc qui est connecté à internet en wifi
    Par Coussati dans le forum Achat et Conseils
    Réponses: 2
    Dernier message: 31/08/2011, 14h28
  2. Gestion des sessions: Qui est connecté ?
    Par Mengué georges dans le forum Servlets/JSP
    Réponses: 5
    Dernier message: 24/01/2008, 14h39
  3. [Système] Savoir qui est connecté en ce moment
    Par sourivore dans le forum Langage
    Réponses: 13
    Dernier message: 12/06/2006, 17h05
  4. XP voir qui est connecté a un dossier partagé
    Par totoche dans le forum Windows XP
    Réponses: 2
    Dernier message: 02/06/2006, 09h55
  5. voir comment est alimentée une vue qui est dans dba_objects
    Par meufeu dans le forum Administration
    Réponses: 15
    Dernier message: 06/10/2004, 17h27

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo