Hey guys,
we are investigating currently a problem with slowing down performance in our token-check system. While the system is running 24/7 the query-performance with TObjectManager.Find<TToken>(TokenPk)
gets slower and slower.
Performance-Checks with the TStopWatch
, code:
// var lSW: TStopWatch;
LogManager.GetLogger.Trace('CheckToken ' + sTokenId + ' ' + lSW.ElapsedMilliseconds.ToString + 'ms');
lToken := Self.ObjectManager.Find<TToken>(sTokenId);
if not Assigned(lToken) then
begin
raise EXDataHttpUnauthorized.Create('Token is revoked');
end;
LogManager.GetLogger.Trace('> CheckToken in DB ' + sTokenId + ' ' + lSW.ElapsedMilliseconds.ToString + 'ms');
resulting in these:
[03.02.2025 16:47:49][3220][4736][Memory usage: 9,14 MB][Trace][Value: > CheckToken in DB 869DF881-B2E8-4EB2-B3B6-0BFE53C4797A 6ms][Type: string]
// snip
[04.02.2025 10:48:38][3220][9384][Memory usage: 45,17 MB][Trace][Value: > CheckToken in DB E7451A53-70F3-4A7B-AF3E-774AE4ACEACE 64ms][Type: string]
Maybe we are using the OnEntity-Events in the wrong way and the approch of checking the Token values against the DB is wrong implemented?
We have implemented all token and access checks for Aurelius CRUD entities in the XDataModule.Events.OnEntityXXX.Subscribe
(e.g. OnEntityGet
) Events like this:
XDataModule.Events.OnEntityGet.Subscribe(
procedure(Args: TEntityGetArgs)
begin
lUser := TXDataOperationContext.Current.Request.User;
if lUser = nil then
begin
raise EXDataHttpUnauthorized.Create(UserNotAuthenticated);
end;
lTokenChecker := TTokenChecker.Create(TXDataOperationContext.Current.CreateManager(), lUser);
lTokenChecker.CheckToken;
end;
Can we use the TXDataOperationContext.Current
context in these events and the ObjectManager? Or should we use the Args.Handler
and cast ist to sowemthing like this:
XDataModule.Events.OnEntityGet.Subscribe(
procedure(Args: TEntityGetArgs)
begin
lHandler := (Args.Handler as TXDataRequestHandler);
lUser := lHandler.Request.User;
if lUser = nil then
begin
raise EXDataHttpUnauthorized.Create(UserNotAuthenticated);
end;
lObjManager := TObjectManager.Create(lHandler.ConnectionPool.GetConnection);
lHandler.AddManager(lObjManager);
lTokenChecker := TTokenChecker.Create(lObjManager, lUser);
lTokenChecker.CheckToken;
end;
If we restart the service all performance values are nice again. If we run the query direct on the DB, the query always took only ~2ms
.
The Token-Checker is also called from serivce-endpoints, the performance values there are always below < 10ms
. Only in these entity-events get the performance bad. Our guess is the ObjectManager
in these Events will be not cleared and gets full of objects.
Every help is appreciated. Thanks in advance!