Grahame Grieve gave an interesting presentation on Services written in
Lazarus for Windows, Linux and MacOS.
Grahame is currently somewhere in SA near the end of the Nullabor,
approaching the final stage of a yearish long trip around Australia.
Some key takeaways.
Grahames Service controller/package, is one he originally built before
delphi got one built in.
Delphi Services must not leak memory.
Delphi Services need good logging.
eg. Why did the service shutdown.
The service should log when it starts to a file, and if the startup
entry does not appear in the file, you need to fix the permissions.
Need to test your service under restricted memory conditions.
You need to make/find a console emulation, if you want to run a
console app in MacOSX.
Grahame is running his service behind an Nginx proxy, which provides
protection and other benefits for his service.
Service has a telnet entry point, so can watch logs and examine things (eg. Locks)
Also noted from Sue
Exceptions all need to be handled (and logged)
Using smartinspect has been able to have each thread logging to its
own log destination/file?
My Note:
If you have the luxury of being able to restart the service
periodically, eg. Sometime at Night. A scheduled task to do that can be good.
There was also a short discussion of the lack of open source CI and
similar functionality available in the Delphi World. Apparently Malcolm
has given a presentation on Jenkins??
Sounded like an interesting talk, thanks Grahame, sorry I missed it. Services are interesting beings. Not sure if you mentioned the following but reading over the slides prompted the following thoughts:
Creating interactive service apps is possible but problematic. An alternative is to have a service app that runs interactively if you execute another instance while logged in as an interactive user. e.g. we can run our service app exe using a shortcut with the /configure command line option to display the configuration UI (config is saved to a file) and allow execution of the functionality interactively/manually. The non-interactive running service app reads the config file and runs the functionality in the background automatically
Re: logging - in addition to logging to file you can also log to the Windows event log. Some IT staff like that but a file is usually better. I like the telnet idea - in a previous company we added a HTTP server within the service app to serve up HTML to display the state and logs from a browser, and some buttons to clear stats counters or the log
If you install the service app to run as the default Local System account then the \AppData folder is in an obscure location like C:\Windows\System32\config\systemprofile\AppData\ or C:\Windows\SysWOW64\config\systemprofile\AppData, so you might want to choose a different location to store configuration or write log files
Agree strongly with eliminating memory leaks. Also need to catch all exceptions
The app should quickly respond to service status changes like start/stop, so you need to limit long running tasks, design loops to be interrupted, threads to be woken etc (e.g. use TEvent instead of Sleep)
At system startup the service might be started before some subsystems are ready. e.g. before the network is up so you need to have good retry logic during initialisation
Services have a few automatic recovery options such as “start it again” or “run an app” if the service fails
To add a description for the service (which appears in the services applet) call Winapi.WinSvc.ChangeServiceConfig2()
That lead to an interesting discussion on various sorting algorithms with benchmark timings. The PDQSort2 that Stefan has working in the Spring4D framework looks impressive.
And the serious bug(s) in TParrallelArray need to be fixed before it can be used in production systems. The discussion was in mid September and I didn’t see any mention of a fix in the recent Delphi 12.2 Patch 1. I wonder if it has been officially reported.