2222package com .kingsrook .qqq .backend .core .modules .authentication ;
2323
2424
25- import java .lang .reflect .Method ;
2625import java .time .Duration ;
2726import java .util .Optional ;
2827import com .kingsrook .qqq .backend .core .logging .QLogger ;
3130
3231
3332/*******************************************************************************
34- ** Helper class for optionally interacting with the QSessionStore QBit .
33+ ** Helper class for interacting with the session store .
3534 **
36- ** Uses reflection to avoid a hard dependency on the qbit-session-store module.
37- ** All methods are designed to fail silently (returning empty/default values)
38- ** when the QBit is not on the classpath , ensuring backwards compatibility.
35+ ** Delegates to the provider registered with QSessionStoreRegistry. All methods
36+ ** are designed to fail silently (returning empty/default values) when no
37+ ** provider is registered , ensuring backwards compatibility.
3938 *******************************************************************************/
4039public class QSessionStoreHelper
4140{
4241 private static final QLogger LOG = QLogger .getLogger (QSessionStoreHelper .class );
4342
44- private static final String CONTEXT_CLASS = "com.kingsrook.qbits.sessionstore.QSessionStoreQBitContext" ;
45-
46- private static Boolean sessionStoreAvailable = null ;
43+ private static final Duration DEFAULT_TTL = Duration .ofHours (1 );
4744
4845
4946
5047 /***************************************************************************
51- ** Check if the session store QBit is available on the classpath .
48+ ** Check if a session store provider is available.
5249 ***************************************************************************/
5350 public static boolean isSessionStoreAvailable ()
5451 {
55- if (sessionStoreAvailable == null )
56- {
57- try
58- {
59- Class .forName (CONTEXT_CLASS );
60- sessionStoreAvailable = true ;
61- }
62- catch (ClassNotFoundException e )
63- {
64- sessionStoreAvailable = false ;
65- }
66- }
67- return sessionStoreAvailable ;
52+ return QSessionStoreRegistry .getInstance ().isAvailable ();
6853 }
6954
7055
7156
7257 /***************************************************************************
73- ** Store a session in the session store (if available and configured ).
58+ ** Store a session in the session store (if available).
7459 ***************************************************************************/
7560 public static void storeSession (String sessionUuid , QSession session , Duration ttl )
7661 {
77- if (!isSessionStoreAvailable ())
62+ Optional <QSessionStoreProviderInterface > provider = QSessionStoreRegistry .getInstance ().getProvider ();
63+ if (provider .isEmpty ())
7864 {
7965 return ;
8066 }
8167
8268 try
8369 {
84- Object provider = getProvider ();
85- if (provider != null )
86- {
87- Method storeMethod = provider .getClass ().getMethod ("store" , String .class , QSession .class , Duration .class );
88- storeMethod .invoke (provider , sessionUuid , session , ttl );
89- LOG .debug ("Stored session in session store" , logPair ("sessionUuid" , sessionUuid ));
90- }
70+ provider .get ().store (sessionUuid , session , ttl );
71+ LOG .debug ("Stored session in session store" , logPair ("sessionUuid" , sessionUuid ));
9172 }
9273 catch (Exception e )
9374 {
@@ -98,29 +79,24 @@ public static void storeSession(String sessionUuid, QSession session, Duration t
9879
9980
10081 /***************************************************************************
101- ** Load a session from the session store (if available and configured ).
82+ ** Load a session from the session store (if available).
10283 ***************************************************************************/
103- @ SuppressWarnings ("unchecked" )
10484 public static Optional <QSession > loadSession (String sessionUuid )
10585 {
106- if (!isSessionStoreAvailable ())
86+ Optional <QSessionStoreProviderInterface > provider = QSessionStoreRegistry .getInstance ().getProvider ();
87+ if (provider .isEmpty ())
10788 {
10889 return Optional .empty ();
10990 }
11091
11192 try
11293 {
113- Object provider = getProvider ( );
114- if (provider != null )
94+ Optional < QSession > result = provider . get (). load ( sessionUuid );
95+ if (result . isPresent () )
11596 {
116- Method loadMethod = provider .getClass ().getMethod ("load" , String .class );
117- Optional <QSession > result = (Optional <QSession >) loadMethod .invoke (provider , sessionUuid );
118- if (result .isPresent ())
119- {
120- LOG .debug ("Loaded session from session store" , logPair ("sessionUuid" , sessionUuid ));
121- }
122- return result ;
97+ LOG .debug ("Loaded session from session store" , logPair ("sessionUuid" , sessionUuid ));
12398 }
99+ return result ;
124100 }
125101 catch (Exception e )
126102 {
@@ -133,72 +109,83 @@ public static Optional<QSession> loadSession(String sessionUuid)
133109
134110
135111 /***************************************************************************
136- ** Touch a session to reset its TTL (if available and configured).
112+ ** Load a session and touch it to reset its TTL in a single operation.
113+ **
114+ ** This is more efficient than calling loadSession + touchSession separately,
115+ ** as providers may implement optimized single-call versions (e.g., Redis
116+ ** GETEX, combined SQL query).
137117 ***************************************************************************/
138- public static void touchSession (String sessionUuid )
118+ public static Optional < QSession > loadAndTouchSession (String sessionUuid )
139119 {
140- if (!isSessionStoreAvailable ())
120+ Optional <QSessionStoreProviderInterface > provider = QSessionStoreRegistry .getInstance ().getProvider ();
121+ if (provider .isEmpty ())
141122 {
142- return ;
123+ return Optional . empty () ;
143124 }
144125
145126 try
146127 {
147- Object provider = getProvider ( );
148- if (provider != null )
128+ Optional < QSession > result = provider . get (). loadAndTouch ( sessionUuid );
129+ if (result . isPresent () )
149130 {
150- Method touchMethod = provider .getClass ().getMethod ("touch" , String .class );
151- touchMethod .invoke (provider , sessionUuid );
131+ LOG .debug ("Loaded and touched session from session store" , logPair ("sessionUuid" , sessionUuid ));
152132 }
133+ return result ;
153134 }
154135 catch (Exception e )
155136 {
156- LOG .warn ("Failed to touch session in session store" , e , logPair ("sessionUuid" , sessionUuid ));
137+ LOG .warn ("Failed to load and touch session in session store" , e , logPair ("sessionUuid" , sessionUuid ));
157138 }
139+
140+ return Optional .empty ();
158141 }
159142
160143
161144
162145 /***************************************************************************
163- ** Get the configured default TTL from the session store config .
146+ ** Touch a session to reset its TTL (if available) .
164147 ***************************************************************************/
165- public static Duration getDefaultTtl ( )
148+ public static void touchSession ( String sessionUuid )
166149 {
167- if (!isSessionStoreAvailable ())
150+ Optional <QSessionStoreProviderInterface > provider = QSessionStoreRegistry .getInstance ().getProvider ();
151+ if (provider .isEmpty ())
168152 {
169- return Duration . ofHours ( 1 ) ;
153+ return ;
170154 }
171155
172156 try
173157 {
174- Class <?> contextClass = Class .forName (CONTEXT_CLASS );
175- Method getConfigMethod = contextClass .getMethod ("getConfig" );
176- Object config = getConfigMethod .invoke (null );
177-
178- if (config != null )
179- {
180- Method getTtlMethod = config .getClass ().getMethod ("getDefaultTtl" );
181- return (Duration ) getTtlMethod .invoke (config );
182- }
158+ provider .get ().touch (sessionUuid );
183159 }
184160 catch (Exception e )
185161 {
186- LOG .debug ("Failed to get default TTL from session store config " , e );
162+ LOG .warn ("Failed to touch session in session store" , e , logPair ( "sessionUuid" , sessionUuid ) );
187163 }
188-
189- return Duration .ofHours (1 );
190164 }
191165
192166
193167
194168 /***************************************************************************
195- ** Get the provider instance from the context class .
169+ ** Get the configured default TTL from the session store provider .
196170 ***************************************************************************/
197- private static Object getProvider () throws Exception
171+ public static Duration getDefaultTtl ()
198172 {
199- Class <?> contextClass = Class .forName (CONTEXT_CLASS );
200- Method getProviderMethod = contextClass .getMethod ("getProvider" );
201- return getProviderMethod .invoke (null );
173+ Optional <QSessionStoreProviderInterface > provider = QSessionStoreRegistry .getInstance ().getProvider ();
174+ if (provider .isEmpty ())
175+ {
176+ return DEFAULT_TTL ;
177+ }
178+
179+ try
180+ {
181+ return provider .get ().getDefaultTtl ();
182+ }
183+ catch (Exception e )
184+ {
185+ LOG .debug ("Failed to get default TTL from session store provider" , e );
186+ }
187+
188+ return DEFAULT_TTL ;
202189 }
203190
204191}
0 commit comments