Technologies Used
Angular 12
Using Angular within this project meant the UI was very responsive to user interaction. Also, using Angular Material made for a enjoyable visual experience for the customer.
.NET 6
The Web API code was written in C#, with API's documented through Swagger
SignalR Core
Realtime updates about the queue status were transmitted via SignalR Core, along with log messages.
Windows Service
The application was deployed as a Windows Service and configured to restart in the case of a failure.
SQL Server
Performant stored procedures that made the best use of available resources.
Problem Overview
I was tasked with rewriting a service that generated and sent HL7 messages to downstream systems. The existing implementation was flawed for several reasons, such as:
- The existing implementation was written in Visual Basic .NET and was opaque. Problems, failures and issues were not easily spotted or observed.
- It wasn't easy to understand if the service was running correctly.
- It was difficult to understand the messages that the system produced.
Approach
When approaching this problem, I had to consider that while the existing service was problematic, it did manage to construct and send HL7 messages to downstream systems most of the time. Any change that we made in our system would affect the data sent into downstream systems.
I also saw an oppurtunity to improve the transparency of what the service was doing internally, and thought that developing and implementing a management console would benefit the customer experience and usability of the service.
The main priority was ensuring that messages were effectively the same after I had rewritten the interface service, and a second priority was to make the service more accessible and easy to use for the customer.
Planning a solution
Because the existing service was a simple console app, it would have been possible to simply extend what was already there and not actually improve upon the core offering. However, this would have meant that the customer would have inherited significant technical debt for the service. It would have also meant that it was difficult to maintain the service into the future, as it was written in an outdated language and framework.
Another issue I hoped to resolve through these actions was to bring more transparency to how the service operated, and whether it was healthy or not.
On top of this, portability of the solution was also key. As the end result would be a service that ran on a server, the service would ideally ship with all the functionality required to both process and send messages, while also answering requests that came from the API.
Solution Tour
At the login screen, the user is prompted for the API key so they can access the service. Also of note is the fact that the commit hash is prominently displayed beneath the product name.
Users’ are also able to log in and just view the documentation without possessing a valid API key (and they can only see the documentation).
After logging in, the user can see the dashboard of the application. The dashboard acts to show the current configuration of the service (as is blurred out in the screenshot).
The dashboard also shows the current queue depth as a number on the right, and also shows how deep the queue has been over time.
These tools are invaluable when troubleshooting a possible issue or outage with the service itself.
The service event log showed realtime updates for the service, and the current status. Because the solution used Serilog to produce logs, these log messages were also routed to this page via SignalR.
At times when the service was problematic or experiencing difficulties, having access to a realtime log provided information that helped to raise awareness of a possible problem.
Logs were also forwarded to email when a certain threshold was passed (for example, only warnings and above would be emailed to system administrators).
Finally, a dropdown box on the top-right provided a way for support staff to download the logs from previous days.
Problem Highlight
"How will support staff be able to read the messages?"
Health Language 7 (HL7) is notoriously difficult to read and understand. People who specialise in interfaces are able to comprehend the messages, but support staff may not possess that particular skill. However, from time to time, the support staff may be asked to confirm that the contents of a message is correct, which they can’t do without unpacking the message and inspecting it with third-party tools.
To resolve this, I created a HL7 Message Viewer within the interface monitor. This used a HL7 library available from NPM, and I also split the individual strings on the escape characters as per the HL7 specification. I then correlated the message descriptors from the package to the actual HL7 itself, before displaying the data in a purpose-built HL7 Viewer.
HL7 Sample Data
MSH|^~\&|MESA_OP|XYZ_HOSPITAL|iFW|ABC_HOSPITAL|200812121359||RDS^O13|00963425|P|2.5 PID|1|12345|12345^^^MIE&1.2.840.114398.1.100&ISO^MR||DOE^JOHN^S||19281118|M|||123 Main St.^^Lake Buena Vista^FL^3283|||||||||||||||||||
ORC|RE|1234.2||1234|||1^OD||||||07315^TESTDR^JOE
RXO|1255^Omeprazole^NZMT|40||mg|capsule||||G||90
RXR|MTH^Mouth^HL70162
RXD|1|1255^Omeprazole^NZMT |200812121359|90|capsule||
P555.2||N|||||40|mg
FT1|1|||200607211055||CD|00340024110^VERAPAMIL 120MG TABLET^NDC|||100|55.43&USD|
FT1|2|||200607211055||CP|00340024110^VERAPAMIL 120MG TABLET^NDC|||100|5.00&USD|