Communication between Web App instances running on the same server

My Web App is running behind an NGINX load balancer (everything was setup with Lifeboat), 4 instances are running.

When I access the ‘admin’ page, I can do perform some actions but these actions are only applied to the instance I am currently connected to.

  1. Is there some way to communicate between instances?

My web app performs an action (sending emails) every 12 hours.
This is done with a timer running every 5 minutes that checks if it is time to do the action.
With 4 instances running, 4 identical emails are sent.

  1. Is there a way to define one instance as the “master” and only get that instance to perform the action?
  1. You might be able to make use of an IPCSocket to communicate between the instances. A simpler method might be using a shared SQLiteDatabase. The SQLite docs say that multiple processes can share a singular file due to file locking. The threading problems are moot because Xojo threads are time slices.

  2. You can use Lifeboat to schedule cron jobs. You could write a specific console application to perform this email routine or you could build it into your web app and determine the behavior with launch flags. The granularity of cron jobs with Lifeboat would require you to run this every hour and determine “if it’s time yet” since the next available step is daily. If you’re comfortable going outside of Lifeboat, you could schedule a cron job to run every 12 hours and not need to determine “if it’s time yet” yourself.

    You might also be able to determine a “master” instance by having them all try to acquire a FolderItem on disk. The first instance to create this file becomes the “master” and any instance where FolderItem.Exists = true knows it’s not the one to send emails. You would need to clean up this file in the App.Closing event. (Norman says a Mutex would work for this too)

As a simple workaround, what about a Mutex? And the first one to acquire it becomes the “Master Sender”

Edit:

I was waiting for Tim to send his response, and when the typing got quiet I’ve sent mine. We crossed wires here.

1 Like

The easiest way is to webhook to the local instance since each is on a different port on the local machine it’s easy as

URLConnection.Send("GET", "http://127.0.0.1:1234/specialpath?key=1234556778")

Make sure you check on the App.HandleURL of the instance if it’s a local instance that’s calling by checking the ip (request.remoteAddress) and maybe a key like above.

' Event App.HandleURL
If request.path = "specialpath" And request.Parameter("key") = "1234556778" And Request.RemoteAddress = "127.0.0.1" Then
// send back to the calling instance.
Print("hello from some instance")
End If

Oh with this you could send some commands to a specific instance, the implementation is up to you.

You need to design a better mouse trap if you are to avoid the type of problem you are now encountering and provide a stable environment that will last over time.

Use services of demons to handle the sending of mails, use a message queue to handle the communication and a web application to handle the admin, placing messages on the queue to communicate with the services. On top of this you need to log and track activity so that when things fall over as the always do, you can recover it.

I simplified my first post but I am already using a message queue.
My current implementation is to set the next task time at midnight + random minutes. Unless two instances are set to execute the task at the exact same time, emails are only sent once. But I am well aware that this is bad workaround, thus asking for a better solution.

Thank you all for the suggestions :slight_smile:
Mutex and IPCSocket seem to be the best easiest solutions for both problems.