Heroku build and deployment successful but app has weird behaviour

I have built a mapping tool which allows a user to:

  • click to add a legend entry
  • select a colour from a legend
  • click on region and fill with the selected colour
  • continue to fill with the selected colour, or click the region again to wipe the colour
  • click to add a new legend entry
  • select another colour from the legend and so on…

The app has a bunch of other functions but the colour filling step behaves strangely when deployed on heroic compared to how it does for me locally.

On heroku, you can select a colour and fill a few regions and then previously filled regions get cleared randomly, then reappear after a few more regions have been filled with the same and/or with different colours.

I have tried to check the heroku logs with print statements to see where its going awry but I am completely stumped. Especially as it works locally.

The requirements.txt file I used to deploy on heroku included:
dash==2.4.1
pandas==1.3.5
matplotlib==3.5.1
geopandas==0.11.0
gunicorn==20.0.4
dash-bootstrap-components==1.1.0
whitenoise==5.2.0
plotly==5.9.0

and runtime.txt:
python-3.10.4

The draft heroku app is here: https://test-heroku-tw-app.herokuapp.com

The code for my app is here: GitHub - kamilchoi/tw_mapping: Sales territory mapping tool

Any help would be greatly appreciated!
Thanks

Hi,

Welcome to the community! :smiley:

Are you running your app in Heroku with multiple processes/workers? The sort of behaviour that you described sounds like you are using the value of a local variable in the callback (like in a stateful application).

Your code is a bit tricky to look into due to the amount of functionality it has, but my guts tell me that postcode_colour_d is the one being modified in the callback… You can fix it by sending it to a dcc.Store component and update/get it in a callback as you did for some other data.

Hope you will find this helpful!

Hi Jose,

Thanks for your reply!

My app is a bit of a monster, so thank you for taking a look.

You are correct, the postcode_colour_d variable is being modified in the callback (this maps the colour selected to the selected geography - postcode in this case). I actually have this variable sent to dcc.Store already so that’s why I am really baffled by this behaviour.

I have set multiple processes/workers for the app. Is that something that could cause or fix this issue? I paid for the higher level tiers to see if maybe it was a performance issue, but this didn’t impact this particular problem.

Cheers
K

Hi,

I actually have this variable sent to dcc.Store already so that’s why I am really baffled by this behaviour.

In the update_map you are using the object from the global scope, instead of passing it from the value in dcc.Store. Since you are also modifying it, you should have the dcc.Store containing postcode_colour_d both as State and as Output, so the callback can return the updated value to the browser. That should fix the problem.

I have set multiple processes/workers for the app. Is that something that could cause or fix this issue? I paid for the higher level tiers to see if maybe it was a performance issue, but this didn’t impact this particular problem.

Just to expand a bit on the cause: if you have multiple workers running the application, the post requests made to calculate the callbacks will be executed in an arbitrary worker. As your callback is modifying a variable in the global scope, this means that different workers will have different “versions” of the object, therefore you will get a different response (update) depending on which one ran the callback. The same would have happened if you had multiple users using the application, which is why it is a bad idea to rely on global variables in apps…

My app is a bit of a monster, so thank you for taking a look.

It is not that bad… But I would recommend you to take a look on the MultiplexerTransform from dash-extensions if you want to split your big callbacks a bit further. :smiling_face: