Best practice for a client that connects to multiple servers

Post Reply
bencover
Posts: 7
Joined: Wed May 26, 2021 12:40 pm

Best practice for a client that connects to multiple servers

Post by bencover » Wed May 26, 2021 1:01 pm

Hey,
We currently got a system that has multiple HTTP API integrations to SMS providers.
In order to improve scalability and to make it easier to integrate with other providers we are willing to develop an SMPP client using InetLab as all of the providers we work with also has an SMPP credentials integration available.

I couldn't find exactly what would be the best practice for my needs -

1.Every time we blast a campaign we are sending through multiple providers and load-balancing the sent messages between them, which means I'll need to use different ip/port/username/password for each one.
should I hold a connected and bound SMPP client for each provider? (lets say 20 providers)
if so how would such code look like?
My idea was that at the beginning of every blast request I will create an instance of each SMPP client. some sort of a base-class that does the basic SMPP client initialization (like in the docs) that receives the ip/port/username/password as dynamic params.

2.In regards to DLR, final DLR status might take a while, that means I need to keep those clients up and running 24/7 to wait for a DLR response to the SMPP client? so far we simply had a Webhook configured in our http API, but having the ability to do that through SMPP as well will spare us a lot of unnecessary integration hassles, how is that usually done?

Thanks for reading
alt
Site Admin
Posts: 985
Joined: Tue Apr 25, 2006 9:45 am

Re: Best practice for a client that connects to multiple servers

Post by alt » Wed May 26, 2021 7:21 pm

Hi bencover,

SmppClient represents a connection to the SMPP server. You need to create at least one SmppClient instance for each provider.
In general you should keep the connection with SMPP server alive. The connection recovery feature helps you here.
The extension method RetryUntilConnectedAsync helps when SMPP provider is unreachable and your application starts.

To receive DLR you need to subscribe to evDeliverSm event on each client instance. You can use the same event handler methods for all clients. The sender parameter of the method is SmppClient instance.
bencover
Posts: 7
Joined: Wed May 26, 2021 12:40 pm

Re: Best practice for a client that connects to multiple servers

Post by bencover » Mon May 31, 2021 8:22 pm

alt wrote:
Wed May 26, 2021 7:21 pm
Hi bencover,

SmppClient represents a connection to the SMPP server. You need to create at least one SmppClient instance for each provider.
In general you should keep the connection with SMPP server alive. The connection recovery feature helps you here.
The extension method RetryUntilConnectedAsync helps when SMPP provider is unreachable and your application starts.

To receive DLR you need to subscribe to evDeliverSm event on each client instance. You can use the same event handler methods for all clients. The sender parameter of the method is SmppClient instance.

Hey alt, thanks for helping out mate.
Iv'e succesfuly implemented as adviced on your comment.

I got a question regarding the evDeliverSm event, the signature of the method assigned to the event has to be a sync method, how would you implement async actions (updating the DB) without blocking the main thread which keeps submitting messages.
Here is the example of my evDeliverSm -

Code: Select all

        private void DeliveryStatus(object o, DeliverSm deliverSm)
        {
            if (deliverSm.MessageType == MessageTypes.SMSCDeliveryReceipt)
            {
                if (string.IsNullOrEmpty(deliverSm.Receipt.MessageId))
                    return;

                _=UpdateMessageStatus(deliverSm);
            }
        }
`UpdateMessageStatus` is an async method that performs the update to the DB.
Doing the above in a fire and forget type of way works, but It means I can't capture exceptions thrown inside of it, and overall it's the less reliable approach.
Doing

Code: Select all

UpdateMessageStatus(deliverSm).GetAwaiter().GetResult();
Works, but will block my main thread from sending additional requests which will slow down my sending process.

Thought of initializing a new thread for it, not sure if that's a good approach...
How would you implement such a thing?

Thanks!
alt
Site Admin
Posts: 985
Joined: Tue Apr 25, 2006 9:45 am

Re: Best practice for a client that connects to multiple servers

Post by alt » Tue Jun 01, 2021 9:06 am

In this case I would implement manual response sending
https://docs.inetlab.com/smpp/v2.9/arti ... onses.html
bencover
Posts: 7
Joined: Wed May 26, 2021 12:40 pm

Re: Best practice for a client that connects to multiple servers

Post by bencover » Tue Jun 01, 2021 9:38 am

alt wrote:
Tue Jun 01, 2021 9:06 am
In this case I would implement manual response sending
https://docs.inetlab.com/smpp/v2.9/arti ... onses.html
The link you've shared is strictly for SMPP servers isn't it?
I'm running an SMPP Client, and simply willing to receive DLR and incoming replies to messages I sent, as seen in the example below under SMPP Client section -
https://docs.inetlab.com/smpp/v2.9/arti ... ceive.html
alt
Site Admin
Posts: 985
Joined: Tue Apr 25, 2006 9:45 am

Re: Best practice for a client that connects to multiple servers

Post by alt » Tue Jun 01, 2021 10:17 am

The same way you can implement evDeliverSm event handler method.
bencover
Posts: 7
Joined: Wed May 26, 2021 12:40 pm

Re: Best practice for a client that connects to multiple servers

Post by bencover » Tue Jun 01, 2021 10:37 am

alt wrote:
Tue Jun 01, 2021 10:17 am
The same way you can implement evDeliverSm event handler method.
Sorry I'm uncertain on what you mean and how exactly it fits my needs.

evDeliverSm is an event triggered when request is being made from the server to my client (either incoming message or a DLR).
This event only accepts SYNC void signature methods -

Code: Select all

    public delegate void DeliverSmEventHandler(object sender, DeliverSm data);
Inside the method assigned to this event I need to perform ASYNC (db update) action, without blocking the main thread from continually sending more messages.
Your advice is to adjust my method provided above to that ?-

Code: Select all

        private void DeliveryStatus(object o, DeliverSm deliverSm)
        {
            if (deliverSm.MessageType == MessageTypes.SMSCDeliveryReceipt)
            {
                if (string.IsNullOrEmpty(deliverSm.Receipt.MessageId))
                    return;

		Task handleTask = UpdateMessageStatus(deliverSm);
            }
        }
This is basically the same exact approach as I initially did isnt it? a task that isn't being awaited for on the same thread meaning I wont be able to catch exceptions inside of it.
Updating the DB when a DLR/Incoming message is received sounds like the most common thing people do, so I must be missing something that should be fairly straight forward.

Thanks.
alt
Site Admin
Posts: 985
Joined: Tue Apr 25, 2006 9:45 am

Re: Best practice for a client that connects to multiple servers

Post by alt » Tue Jun 01, 2021 12:25 pm

When you start UpdateMessageStatus task, the DeliverSmResp will be sent at the same time without waiting for task completion. If you want to send response after task completion you need to send it manually as it described in "Control SMPP responses" article.
bencover wrote:
Tue Jun 01, 2021 10:37 am
without blocking the main thread from continually sending more messages.
actually .GetAwaiter().GetResult(); will block only one of the worker threads for the SmppClient. which prevents to receive and process more DeliverSm commands. By default there are 3 threads.
Sure it is not recommended way. Just start the task.
bencover wrote:
Tue Jun 01, 2021 10:37 am
I wont be able to catch exceptions inside of it.
You can always implement try catch inside UpdateMessageStatus method.
bencover
Posts: 7
Joined: Wed May 26, 2021 12:40 pm

Re: Best practice for a client that connects to multiple servers

Post by bencover » Tue Jun 01, 2021 1:51 pm

alt wrote:
Tue Jun 01, 2021 12:25 pm
When you start UpdateMessageStatus task, the DeliverSmResp will be sent at the same time without waiting for task completion. If you want to send response after task completion you need to send it manually as it described in "Control SMPP responses" article.
bencover wrote:
Tue Jun 01, 2021 10:37 am
without blocking the main thread from continually sending more messages.
actually .GetAwaiter().GetResult(); will block only one of the worker threads for the SmppClient. which prevents to receive and process more DeliverSm commands. By default there are 3 threads.
Sure it is not recommended way. Just start the task.
bencover wrote:
Tue Jun 01, 2021 10:37 am
I wont be able to catch exceptions inside of it.
You can always implement try catch inside UpdateMessageStatus method.

Thanks for helping, I'll use Task.Run and implement trycatch inside.
Post Reply