Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
E
emiMobile
Overview
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Mac Stephens
emiMobile
Commits
c34c8c72
Commit
c34c8c72
authored
Sep 11, 2026
by
Mac Stephens
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Prevent WebSocket update lockups, recover DB listeners, and move log levels to INI
parent
9cdc7cfd
Show whitespace changes
Inline
Side-by-side
Showing
9 changed files
with
179 additions
and
55 deletions
+179
-55
Api.Database.dfm
emiMobileServer/Source/Api.Database.dfm
+1
-0
Api.Database.pas
emiMobileServer/Source/Api.Database.pas
+63
-10
Api.ServiceImpl.pas
emiMobileServer/Source/Api.ServiceImpl.pas
+1
-1
Common.Config.pas
emiMobileServer/Source/Common.Config.pas
+0
-8
WebSocket.Manager.pas
emiMobileServer/Source/WebSocket.Manager.pas
+55
-14
Ws.DataModel.pas
emiMobileServer/Source/Ws.DataModel.pas
+46
-17
emiMobileServer.json
emiMobileServer/bin/emiMobileServer.json
+1
-3
emiMobileServer.dpr
emiMobileServer/emiMobileServer.dpr
+11
-2
Module.Websocket.pas
webEMIMobile/Module.Websocket.pas
+1
-0
No files found.
emiMobileServer/Source/Api.Database.dfm
View file @
c34c8c72
...
@@ -1363,6 +1363,7 @@ object ApiDatabaseModule: TApiDatabaseModule
...
@@ -1363,6 +1363,7 @@ object ApiDatabaseModule: TApiDatabaseModule
Connection = ucENTCAD
Connection = ucENTCAD
Events = 'disupdate'
Events = 'disupdate'
OnEvent = UniAlerter1Event
OnEvent = UniAlerter1Event
OnError = UniAlerter1Error
Left = 324
Left = 324
Top = 382
Top = 382
end
end
...
...
emiMobileServer/Source/Api.Database.pas
View file @
c34c8c72
...
@@ -6,6 +6,7 @@ uses
...
@@ -6,6 +6,7 @@ uses
System
.
SysUtils
,
System
.
Classes
,
Data
.
DB
,
MemDS
,
DBAccess
,
Uni
,
UniProvider
,
System
.
SysUtils
,
System
.
Classes
,
Data
.
DB
,
MemDS
,
DBAccess
,
Uni
,
UniProvider
,
PostgreSQLUniProvider
,
System
.
Variants
,
System
.
Generics
.
Collections
,
System
.
IniFiles
,
PostgreSQLUniProvider
,
System
.
Variants
,
System
.
Generics
.
Collections
,
System
.
IniFiles
,
Common
.
Logging
,
Vcl
.
Forms
,
System
.
Character
,
Common
.
Ini
,
DAAlerter
,
Common
.
Logging
,
Vcl
.
Forms
,
System
.
Character
,
Common
.
Ini
,
DAAlerter
,
System
.
SyncObjs
,
UniAlerter
;
UniAlerter
;
type
type
...
@@ -210,14 +211,17 @@ type
...
@@ -210,14 +211,17 @@ type
procedure
DataModuleCreate
(
Sender
:
TObject
);
procedure
DataModuleCreate
(
Sender
:
TObject
);
procedure
UniAlerter1Event
(
Sender
:
TDAAlerter
;
const
EventName
,
procedure
UniAlerter1Event
(
Sender
:
TDAAlerter
;
const
EventName
,
Message
:
string
);
Message
:
string
);
procedure
UniAlerter1Error
(
Sender
:
TDAAlerter
;
E
:
Exception
);
private
private
FCADUpdate
:
Integer
;
{ Private declarations }
FUpdateListenerFailed
:
Integer
;
public
public
CADUpdate
:
Boolean
;
function
HandleUniqueFilenames
(
const
category
:
string
):
string
;
function
HandleUniqueFilenames
(
const
category
:
string
):
string
;
function
BadgeCounts
(
const
BaseQuery
:
TUniQuery
):
Integer
;
function
BadgeCounts
(
const
BaseQuery
:
TUniQuery
):
Integer
;
function
EnsureConnected
:
Boolean
;
function
EnsureConnected
:
Boolean
;
function
StartUpdateListener
:
Boolean
;
procedure
MarkCADUpdate
;
function
ConsumeCADUpdate
:
Boolean
;
end
;
end
;
var
var
...
@@ -232,7 +236,8 @@ implementation
...
@@ -232,7 +236,8 @@ implementation
procedure
TApiDatabaseModule
.
DataModuleCreate
(
Sender
:
TObject
);
procedure
TApiDatabaseModule
.
DataModuleCreate
(
Sender
:
TObject
);
begin
begin
CADUpdate
:=
False
;
FCADUpdate
:=
0
;
FUpdateListenerFailed
:=
0
;
ucENTCAD
.
ProviderName
:=
'PostgreSQL'
;
ucENTCAD
.
ProviderName
:=
'PostgreSQL'
;
ucENTCAD
.
Server
:=
IniEntries
.
DatabaseServer
;
ucENTCAD
.
Server
:=
IniEntries
.
DatabaseServer
;
...
@@ -241,8 +246,6 @@ begin
...
@@ -241,8 +246,6 @@ begin
ucENTCAD
.
Username
:=
IniEntries
.
DatabaseUsername
;
ucENTCAD
.
Username
:=
IniEntries
.
DatabaseUsername
;
ucENTCAD
.
Password
:=
IniEntries
.
DatabasePassword
;
ucENTCAD
.
Password
:=
IniEntries
.
DatabasePassword
;
ucENTCAD
.
LoginPrompt
:=
False
;
ucENTCAD
.
LoginPrompt
:=
False
;
EnsureConnected
;
end
;
end
;
...
@@ -258,21 +261,64 @@ begin
...
@@ -258,21 +261,64 @@ begin
ucENTCAD
.
ExecSQL
(
'set search_path to lems, avl, entcad, public'
);
ucENTCAD
.
ExecSQL
(
'set search_path to lems, avl, entcad, public'
);
Logger
.
Log
(
2
,
'PostgreSQL API search_path set to lems, avl, entcad, public'
);
Logger
.
Log
(
2
,
'PostgreSQL API search_path set to lems, avl, entcad, public'
);
end
;
Result
:=
True
;
except
on
E
:
Exception
do
Logger
.
Log
(
1
,
'PostgreSQL API database unavailable: '
+
E
.
Message
);
end
;
end
;
function
TApiDatabaseModule
.
StartUpdateListener
:
Boolean
;
begin
Result
:=
False
;
if
TInterlocked
.
Exchange
(
FUpdateListenerFailed
,
0
)
<>
0
then
begin
try
if
UniAlerter1
.
Active
then
UniAlerter1
.
Stop
;
ucENTCAD
.
Disconnect
;
except
on
E
:
Exception
do
begin
Logger
.
Log
(
1
,
'PostgreSQL disupdate listener reset failed: '
+
E
.
Message
);
TInterlocked
.
Exchange
(
FUpdateListenerFailed
,
1
);
Exit
;
end
;
end
;
end
;
if
not
EnsureConnected
then
Exit
;
try
if
not
UniAlerter1
.
Active
then
begin
Logger
.
Log
(
1
,
'Starting PostgreSQL disupdate listener'
);
Logger
.
Log
(
1
,
'Starting PostgreSQL disupdate listener'
);
UniAlerter1
.
Start
;
UniAlerter1
.
Start
;
Logger
.
Log
(
1
,
'PostgreSQL disupdate listener started'
);
Logger
.
Log
(
1
,
'PostgreSQL disupdate listener started'
);
MarkCADUpdate
;
CADUpdate
:=
True
;
end
;
end
;
Result
:=
True
;
Result
:=
True
;
except
except
on
E
:
Exception
do
on
E
:
Exception
do
Logger
.
Log
(
1
,
'PostgreSQL
API database
unavailable: '
+
E
.
Message
);
Logger
.
Log
(
1
,
'PostgreSQL
disupdate listener
unavailable: '
+
E
.
Message
);
end
;
end
;
end
;
end
;
procedure
TApiDatabaseModule
.
MarkCADUpdate
;
begin
TInterlocked
.
Exchange
(
FCADUpdate
,
1
);
end
;
function
TApiDatabaseModule
.
ConsumeCADUpdate
:
Boolean
;
begin
Result
:=
TInterlocked
.
Exchange
(
FCADUpdate
,
0
)
<>
0
;
end
;
procedure
TApiDatabaseModule
.
uqComplaintListCalcFields
(
DataSet
:
TDataSet
);
procedure
TApiDatabaseModule
.
uqComplaintListCalcFields
(
DataSet
:
TDataSet
);
var
var
raw
:
string
;
raw
:
string
;
...
@@ -343,7 +389,14 @@ end;
...
@@ -343,7 +389,14 @@ end;
procedure
TApiDatabaseModule
.
UniAlerter1Event
(
Sender
:
TDAAlerter
;
const
EventName
,
Message
:
string
);
procedure
TApiDatabaseModule
.
UniAlerter1Event
(
Sender
:
TDAAlerter
;
const
EventName
,
Message
:
string
);
begin
begin
if
SameText
(
EventName
,
'disupdate'
)
then
if
SameText
(
EventName
,
'disupdate'
)
then
CADUpdate
:=
True
;
MarkCADUpdate
;
end
;
procedure
TApiDatabaseModule
.
UniAlerter1Error
(
Sender
:
TDAAlerter
;
E
:
Exception
);
begin
Logger
.
Log
(
1
,
'PostgreSQL disupdate listener error: '
+
E
.
Message
);
TInterlocked
.
Exchange
(
FUpdateListenerFailed
,
1
);
MarkCADUpdate
;
end
;
end
;
function
TApiDatabaseModule
.
BadgeCounts
(
const
BaseQuery
:
TUniQuery
):
Integer
;
function
TApiDatabaseModule
.
BadgeCounts
(
const
BaseQuery
:
TUniQuery
):
Integer
;
...
...
emiMobileServer/Source/Api.ServiceImpl.pas
View file @
c34c8c72
...
@@ -47,7 +47,7 @@ begin
...
@@ -47,7 +47,7 @@ begin
ApiDB
:=
TApiDatabaseModule
.
Create
(
nil
);
ApiDB
:=
TApiDatabaseModule
.
Create
(
nil
);
if
not
ApiDB
.
ucENTCAD
.
Connected
then
if
not
ApiDB
.
Ensure
Connected
then
begin
begin
Logger
.
Log
(
1
,
'Unable to connect to API database'
);
Logger
.
Log
(
1
,
'Unable to connect to API database'
);
raise
EXDataHttpException
.
Create
(
raise
EXDataHttpException
.
Create
(
...
...
emiMobileServer/Source/Common.Config.pas
View file @
c34c8c72
...
@@ -13,8 +13,6 @@ type
...
@@ -13,8 +13,6 @@ type
FAdminPassword
:
string
;
FAdminPassword
:
string
;
FWebAppFolder
:
string
;
FWebAppFolder
:
string
;
FReportsFolder
:
string
;
FReportsFolder
:
string
;
FMemoLogLevel
:
Integer
;
FFileLogLevel
:
Integer
;
FAuditEnabled
:
Boolean
;
FAuditEnabled
:
Boolean
;
public
public
constructor
Create
;
constructor
Create
;
...
@@ -24,8 +22,6 @@ type
...
@@ -24,8 +22,6 @@ type
property
webAppFolder
:
string
read
FWebAppFolder
write
FWebAppFolder
;
property
webAppFolder
:
string
read
FWebAppFolder
write
FWebAppFolder
;
property
reportsFolder
:
string
read
FReportsFolder
write
FReportsFolder
;
property
reportsFolder
:
string
read
FReportsFolder
write
FReportsFolder
;
property
auditEnabled
:
Boolean
read
FAuditEnabled
write
FAuditEnabled
;
property
auditEnabled
:
Boolean
read
FAuditEnabled
write
FAuditEnabled
;
property
memoLogLevel
:
Integer
read
FMemoLogLevel
write
FMemoLogLevel
;
property
fileLogLevel
:
Integer
read
FFileLogLevel
write
FFileLogLevel
;
end
;
end
;
procedure
LoadServerConfig
;
procedure
LoadServerConfig
;
...
@@ -64,8 +60,6 @@ begin
...
@@ -64,8 +60,6 @@ begin
Logger
.
Log
(
1
,
'-- adminPassword: '
+
serverConfig
.
adminPassword
+
IfThen
(
serverConfig
.
adminPassword
=
'whatisthisusedfor'
,
' [default]'
,
' [from config]'
));
Logger
.
Log
(
1
,
'-- adminPassword: '
+
serverConfig
.
adminPassword
+
IfThen
(
serverConfig
.
adminPassword
=
'whatisthisusedfor'
,
' [default]'
,
' [from config]'
));
Logger
.
Log
(
1
,
'-- jwtTokenSecret: '
+
serverConfig
.
jwtTokenSecret
+
IfThen
(
serverConfig
.
jwtTokenSecret
=
'super_secret0123super_secret4567'
,
' [default]'
,
' [from config]'
));
Logger
.
Log
(
1
,
'-- jwtTokenSecret: '
+
serverConfig
.
jwtTokenSecret
+
IfThen
(
serverConfig
.
jwtTokenSecret
=
'super_secret0123super_secret4567'
,
' [default]'
,
' [from config]'
));
Logger
.
Log
(
1
,
'-- webAppFolder: '
+
serverConfig
.
webAppFolder
+
IfThen
(
serverConfig
.
webAppFolder
=
'static'
,
' [default]'
,
' [from config]'
));
Logger
.
Log
(
1
,
'-- webAppFolder: '
+
serverConfig
.
webAppFolder
+
IfThen
(
serverConfig
.
webAppFolder
=
'static'
,
' [default]'
,
' [from config]'
));
Logger
.
Log
(
1
,
'-- memoLogLevel: '
+
IntToStr
(
serverConfig
.
memoLogLevel
));
Logger
.
Log
(
1
,
'-- fileLogLevel: '
+
IntToStr
(
serverConfig
.
fileLogLevel
));
Logger
.
Log
(
1
,
'-- auditEnabled: '
+
BoolToStr
(
serverConfig
.
auditEnabled
,
True
));
Logger
.
Log
(
1
,
'-- auditEnabled: '
+
BoolToStr
(
serverConfig
.
auditEnabled
,
True
));
end
end
else
else
...
@@ -87,8 +81,6 @@ begin
...
@@ -87,8 +81,6 @@ begin
jwtTokenSecret
:=
'super_secret0123super_secret4567'
;
jwtTokenSecret
:=
'super_secret0123super_secret4567'
;
webAppFolder
:=
'static'
;
webAppFolder
:=
'static'
;
reportsFolder
:=
'reports'
;
reportsFolder
:=
'reports'
;
memoLogLevel
:=
3
;
fileLogLevel
:=
4
;
auditEnabled
:=
False
;
auditEnabled
:=
False
;
Logger
.
Log
(
1
,
'--TServerConfig.Create - end'
);
Logger
.
Log
(
1
,
'--TServerConfig.Create - end'
);
end
;
end
;
...
...
emiMobileServer/Source/WebSocket.Manager.pas
View file @
c34c8c72
...
@@ -7,7 +7,7 @@ uses
...
@@ -7,7 +7,7 @@ uses
System
.
SysUtils
,
System
.
SysUtils
,
System
.
JSON
,
System
.
JSON
,
System
.
Generics
.
Collections
,
System
.
Generics
.
Collections
,
Vcl
.
ExtCtrl
s
,
System
.
SyncObj
s
,
VCL
.
TMSFNCWebSocketServer
,
VCL
.
TMSFNCWebSocketServer
,
VCL
.
TMSFNCWebSocketCommon
;
VCL
.
TMSFNCWebSocketCommon
;
...
@@ -54,13 +54,15 @@ type
...
@@ -54,13 +54,15 @@ type
FClients
:
TObjectList
<
TConnectedClient
>;
FClients
:
TObjectList
<
TConnectedClient
>;
FClientsLock
:
TObject
;
FClientsLock
:
TObject
;
FSendLock
:
TObject
;
FSendLock
:
TObject
;
FHeartbeatTimer
:
TTimer
;
FHeartbeatThread
:
TThread
;
FHeartbeatStopEvent
:
TEvent
;
FStarted
:
Integer
;
FOnClientsChanged
:
TClientsChangedEvent
;
FOnClientsChanged
:
TClientsChangedEvent
;
function
TrySendTextToClient
(
const
AConnectionId
,
AMessage
:
string
;
function
TrySendTextToClient
(
const
AConnectionId
,
AMessage
:
string
;
ALogFailure
:
Boolean
=
True
):
Boolean
;
ALogFailure
:
Boolean
=
True
):
Boolean
;
function
TryCloseClient
(
const
AConnectionId
:
string
):
Boolean
;
function
TryCloseClient
(
const
AConnectionId
:
string
):
Boolean
;
procedure
Heartbeat
Timer
(
Sender
:
TObject
)
;
procedure
Heartbeat
Sweep
;
procedure
NotifyClientsChanged
;
procedure
NotifyClientsChanged
;
procedure
HandshakeResponseSent
(
Sender
:
TObject
;
AConnection
:
TTMSFNCWebSocketServerConnection
);
procedure
HandshakeResponseSent
(
Sender
:
TObject
;
AConnection
:
TTMSFNCWebSocketServerConnection
);
procedure
MessageReceived
(
Sender
:
TObject
;
AConnection
:
TTMSFNCWebSocketConnection
;
const
AMessage
:
string
);
procedure
MessageReceived
(
Sender
:
TObject
;
AConnection
:
TTMSFNCWebSocketConnection
;
const
AMessage
:
string
);
...
@@ -104,17 +106,32 @@ begin
...
@@ -104,17 +106,32 @@ begin
FServer
.
OnMessageReceived
:=
MessageReceived
;
FServer
.
OnMessageReceived
:=
MessageReceived
;
FServer
.
OnDisconnect
:=
ClientDisconnected
;
FServer
.
OnDisconnect
:=
ClientDisconnected
;
FHeartbeatTimer
:=
TTimer
.
Create
(
nil
);
FStarted
:=
0
;
FHeartbeatTimer
.
Enabled
:=
False
;
FHeartbeatStopEvent
:=
TEvent
.
Create
(
nil
,
False
,
False
,
''
);
FHeartbeatTimer
.
Interval
:=
HEARTBEAT_SWEEP_INTERVAL_MS
;
FHeartbeatThread
:=
TThread
.
CreateAnonymousThread
(
FHeartbeatTimer
.
OnTimer
:=
HeartbeatTimer
;
procedure
begin
while
not
TThread
.
CurrentThread
.
CheckTerminated
do
begin
if
FHeartbeatStopEvent
.
WaitFor
(
HEARTBEAT_SWEEP_INTERVAL_MS
)
=
wrSignaled
then
Break
;
if
TInterlocked
.
CompareExchange
(
FStarted
,
0
,
0
)
<>
0
then
HeartbeatSweep
;
end
;
end
);
FHeartbeatThread
.
FreeOnTerminate
:=
False
;
FHeartbeatThread
.
Start
;
end
;
end
;
destructor
TWebSocketManager
.
Destroy
;
destructor
TWebSocketManager
.
Destroy
;
begin
begin
FHeartbeatTimer
.
Enabled
:=
False
;
Stop
;
Stop
;
FHeartbeatTimer
.
Free
;
FHeartbeatThread
.
Terminate
;
FHeartbeatStopEvent
.
SetEvent
;
FHeartbeatThread
.
WaitFor
;
FHeartbeatThread
.
Free
;
FHeartbeatStopEvent
.
Free
;
FServer
.
Free
;
FServer
.
Free
;
FClients
.
Free
;
FClients
.
Free
;
FSendLock
.
Free
;
FSendLock
.
Free
;
...
@@ -126,13 +143,13 @@ end;
...
@@ -126,13 +143,13 @@ end;
procedure
TWebSocketManager
.
Start
;
procedure
TWebSocketManager
.
Start
;
begin
begin
FServer
.
Active
:=
True
;
FServer
.
Active
:=
True
;
FHeartbeatTimer
.
Enabled
:=
True
;
TInterlocked
.
Exchange
(
FStarted
,
1
)
;
end
;
end
;
procedure
TWebSocketManager
.
Stop
;
procedure
TWebSocketManager
.
Stop
;
begin
begin
if
Assigned
(
FHeartbeatTimer
)
then
TInterlocked
.
Exchange
(
FStarted
,
0
);
FHeartbeatTimer
.
Enabled
:=
False
;
if
Assigned
(
FServer
)
then
FServer
.
Active
:=
False
;
FServer
.
Active
:=
False
;
end
;
end
;
...
@@ -141,9 +158,11 @@ function TWebSocketManager.TrySendTextToClient(const AConnectionId,
...
@@ -141,9 +158,11 @@ function TWebSocketManager.TrySendTextToClient(const AConnectionId,
var
var
client
:
TConnectedClient
;
client
:
TConnectedClient
;
connection
:
TTMSFNCWebSocketServerConnection
;
connection
:
TTMSFNCWebSocketServerConnection
;
sendFailed
:
Boolean
;
begin
begin
Result
:=
False
;
Result
:=
False
;
connection
:=
nil
;
connection
:=
nil
;
sendFailed
:=
False
;
// TMS owns and frees the connection immediately after its disconnect
// TMS owns and frees the connection immediately after its disconnect
// callback returns. Holding FSendLock makes that callback wait until the
// callback returns. Holding FSendLock makes that callback wait until the
...
@@ -174,13 +193,35 @@ begin
...
@@ -174,13 +193,35 @@ begin
except
except
on
E
:
Exception
do
on
E
:
Exception
do
begin
begin
sendFailed
:=
True
;
if
ALogFailure
then
if
ALogFailure
then
Logger
.
Log
(
2
,
'WebSocket send failed: '
+
E
.
Message
);
Logger
.
Log
(
2
,
'WebSocket send failed for '
+
AConnectionId
+
': '
+
E
.
Message
);
end
;
end
;
if
sendFailed
then
begin
TMonitor
.
Enter
(
FClientsLock
);
try
for
client
in
FClients
do
if
SameText
(
client
.
ConnectionId
,
AConnectionId
)
then
begin
client
.
Closing
:=
True
;
Break
;
end
;
finally
TMonitor
.
Exit
(
FClientsLock
);
end
;
end
;
end
;
end
;
finally
finally
TMonitor
.
Exit
(
FSendLock
);
TMonitor
.
Exit
(
FSendLock
);
end
;
end
;
if
sendFailed
then
begin
NotifyClientsChanged
;
TryCloseClient
(
AConnectionId
);
end
;
end
;
end
;
function
TWebSocketManager
.
TryCloseClient
(
function
TWebSocketManager
.
TryCloseClient
(
...
@@ -224,7 +265,7 @@ begin
...
@@ -224,7 +265,7 @@ begin
end
;
end
;
end
;
end
;
procedure
TWebSocketManager
.
Heartbeat
Timer
(
Sender
:
TObject
)
;
procedure
TWebSocketManager
.
Heartbeat
Sweep
;
var
var
staleConnectionIds
:
TList
<
string
>;
staleConnectionIds
:
TList
<
string
>;
client
:
TConnectedClient
;
client
:
TConnectedClient
;
...
...
emiMobileServer/Source/Ws.DataModel.pas
View file @
c34c8c72
unit
Ws
.
DataModel
;
unit
Ws
.
DataModel
;
// Server-side WebSocket data model.
// Server-side WebSocket data model.
// Owns a
VCL timer that fire
s every FIntervalMs milliseconds, queries the
// Owns a
worker thread that check
s every FIntervalMs milliseconds, queries the
// database for the five data sets used by the polling timers that existed in
// database for the five data sets used by the polling timers that existed in
// each connected browser client, and broadcasts the results to every
// each connected browser client, and broadcasts the results to every
// handshaked WebSocket connection via the supplied broadcast callback.
// handshaked WebSocket connection via the supplied broadcast callback.
...
@@ -14,9 +14,8 @@ interface
...
@@ -14,9 +14,8 @@ interface
uses
uses
System
.
SysUtils
,
System
.
Classes
,
System
.
JSON
,
System
.
SysUtils
,
System
.
Classes
,
System
.
JSON
,
System
.
Generics
.
Collections
,
System
.
Generics
.
Collections
,
System
.
SyncObjs
,
Data
.
DB
,
Data
.
DB
,
Vcl
.
ExtCtrls
,
Api
.
Database
,
Api
.
Database
,
WsMessages
,
WsMessages
,
Common
.
Logging
;
Common
.
Logging
;
...
@@ -27,10 +26,13 @@ type
...
@@ -27,10 +26,13 @@ type
TWsDataModel
=
class
TWsDataModel
=
class
private
private
FDb
:
TApiDatabaseModule
;
FDb
:
TApiDatabaseModule
;
FTimer
:
TTimer
;
FThread
:
TThread
;
FStopEvent
:
TEvent
;
FIntervalMs
:
Integer
;
FBroadcast
:
TWsBroadcastProc
;
FBroadcast
:
TWsBroadcastProc
;
procedure
TimerFire
(
Sender
:
TObject
);
procedure
Execute
;
procedure
ConfigureQueryTimeouts
;
procedure
BroadcastAll
;
procedure
BroadcastAll
;
function
BuildBadgeCountsJson
:
string
;
function
BuildBadgeCountsJson
:
string
;
...
@@ -54,31 +56,58 @@ constructor TWsDataModel.Create(ABroadcast: TWsBroadcastProc; AIntervalMs: Integ
...
@@ -54,31 +56,58 @@ constructor TWsDataModel.Create(ABroadcast: TWsBroadcastProc; AIntervalMs: Integ
begin
begin
inherited
Create
;
inherited
Create
;
FBroadcast
:=
ABroadcast
;
FBroadcast
:=
ABroadcast
;
FIntervalMs
:=
AIntervalMs
;
FStopEvent
:=
TEvent
.
Create
(
nil
,
False
,
False
,
''
);
FDb
:=
TApiDatabaseModule
.
Create
(
nil
);
FDb
:=
TApiDatabaseModule
.
Create
(
nil
);
FTimer
:=
TTimer
.
Create
(
nil
)
;
ConfigureQueryTimeouts
;
FT
imer
.
Interval
:=
AIntervalMs
;
FT
hread
:=
TThread
.
CreateAnonymousThread
(
Execute
)
;
FT
imer
.
OnTimer
:=
TimerFir
e
;
FT
hread
.
FreeOnTerminate
:=
Fals
e
;
FT
imer
.
Enabled
:=
True
;
FT
hread
.
Start
;
end
;
end
;
destructor
TWsDataModel
.
Destroy
;
destructor
TWsDataModel
.
Destroy
;
begin
begin
FTimer
.
Enabled
:=
False
;
FThread
.
Terminate
;
FTimer
.
Free
;
FStopEvent
.
SetEvent
;
FThread
.
WaitFor
;
FThread
.
Free
;
FDb
.
Free
;
FDb
.
Free
;
FStopEvent
.
Free
;
inherited
;
inherited
;
end
;
end
;
procedure
TWsDataModel
.
TimerFire
(
Sender
:
TObject
)
;
procedure
TWsDataModel
.
Execute
;
begin
begin
if
not
FDb
.
ucENTCAD
.
Connected
then
try
Exit
;
while
not
TThread
.
CurrentThread
.
CheckTerminated
do
begin
if
FStopEvent
.
WaitFor
(
FIntervalMs
)
=
wrSignaled
then
Break
;
if
not
FDb
.
CADUpdate
then
if
not
FDb
.
StartUpdateListener
then
Exit
;
Continue
;
if
not
FDb
.
ConsumeCADUpdate
then
Continue
;
FDb
.
CADUpdate
:=
False
;
BroadcastAll
;
BroadcastAll
;
end
;
except
on
E
:
Exception
do
Logger
.
Log
(
1
,
'WsDataModel worker stopped: '
+
E
.
Message
);
end
;
end
;
procedure
TWsDataModel
.
ConfigureQueryTimeouts
;
const
COMMAND_TIMEOUT_SECONDS
=
15
;
begin
FDb
.
uqBadgeCounts
.
SpecificOptions
.
Values
[
'CommandTimeout'
]
:=
IntToStr
(
COMMAND_TIMEOUT_SECONDS
);
FDb
.
uqMapUnits
.
SpecificOptions
.
Values
[
'CommandTimeout'
]
:=
IntToStr
(
COMMAND_TIMEOUT_SECONDS
);
FDb
.
uqMapComplaintUnitsList
.
SpecificOptions
.
Values
[
'CommandTimeout'
]
:=
IntToStr
(
COMMAND_TIMEOUT_SECONDS
);
FDb
.
uqMapComplaints
.
SpecificOptions
.
Values
[
'CommandTimeout'
]
:=
IntToStr
(
COMMAND_TIMEOUT_SECONDS
);
FDb
.
uqUnitList
.
SpecificOptions
.
Values
[
'CommandTimeout'
]
:=
IntToStr
(
COMMAND_TIMEOUT_SECONDS
);
FDb
.
uqComplaintList
.
SpecificOptions
.
Values
[
'CommandTimeout'
]
:=
IntToStr
(
COMMAND_TIMEOUT_SECONDS
);
end
;
end
;
procedure
TWsDataModel
.
BroadcastAll
;
procedure
TWsDataModel
.
BroadcastAll
;
...
...
emiMobileServer/bin/emiMobileServer.json
View file @
c34c8c72
...
@@ -2,7 +2,5 @@
...
@@ -2,7 +2,5 @@
"url"
:
"http://localhost:2001/emsys/emiMobile/"
,
"url"
:
"http://localhost:2001/emsys/emiMobile/"
,
"jwtTokenSecret"
:
"super_secret0123super_secret4567"
,
"jwtTokenSecret"
:
"super_secret0123super_secret4567"
,
"adminPassword"
:
"whatisthisusedfor?"
,
"adminPassword"
:
"whatisthisusedfor?"
,
"webAppFolder"
:
"static"
,
"webAppFolder"
:
"static"
"memoLogLevel"
:
5
,
"fileLogLevel"
:
5
}
}
emiMobileServer/emiMobileServer.dpr
View file @
c34c8c72
...
@@ -2,6 +2,7 @@ program emiMobileServer;
...
@@ -2,6 +2,7 @@ program emiMobileServer;
uses
uses
FastMM4,
FastMM4,
System.Classes,
System.SyncObjs,
System.SyncObjs,
System.SysUtils,
System.SysUtils,
Vcl.StdCtrls,
Vcl.StdCtrls,
...
@@ -79,6 +80,9 @@ var
...
@@ -79,6 +80,9 @@ var
LogMsg: string;
LogMsg: string;
begin
begin
if logLevel > FLogLevel then
Exit;
FCriticalSection.Acquire;
FCriticalSection.Acquire;
try
try
LogTime := Now;
LogTime := Now;
...
@@ -90,11 +94,16 @@ begin
...
@@ -90,11 +94,16 @@ begin
else
else
FormattedMessage := FormattedMessage + '[' + IntToStr(logLevel) +'] ' + LogMsg;
FormattedMessage := FormattedMessage + '[' + IntToStr(logLevel) +'] ' + LogMsg;
if logLevel <= FLogLevel then
FLogMemo.Lines.Add( FormattedMessage );
finally
finally
FCriticalSection.Release;
FCriticalSection.Release;
end;
end;
TThread.Queue(nil,
procedure
begin
if Assigned(FLogMemo) and not (csDestroying in FLogMemo.ComponentState) then
FLogMemo.Lines.Add(FormattedMessage);
end);
end;
end;
{ TFileLogAppender }
{ TFileLogAppender }
...
...
webEMIMobile/Module.Websocket.pas
View file @
c34c8c72
...
@@ -825,6 +825,7 @@ begin
...
@@ -825,6 +825,7 @@ begin
FHeartbeatOutstanding
:=
False
;
FHeartbeatOutstanding
:=
False
;
CancelHeartbeatTimeout
;
CancelHeartbeatTimeout
;
if
FHeartbeatTimerId
=
0
then
ScheduleHeartbeat
(
HEARTBEAT_INTERVAL_MS
);
ScheduleHeartbeat
(
HEARTBEAT_INTERVAL_MS
);
end
;
end
;
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment