0

I needed a simple test-and-set instruction in my Flask webserver. The code for the TaS is pretty straightforward (I don't think this is the problem actually, but I'm putting it here for completeness):

from threading import Lock

class TaS:
    def __init__(self, default):
        self.__lock  = Lock()
        self.__value = default

    def update(self, new):
        self.__lock.acquire()
        old = self.__value
        self.__value = new
        self.__lock.release()
        return old

I made this sample Flask application to check if it works:

from Asdf import app
from ...helpers import TaS
from time import sleep
from flask import jsonify    

l = TaS(0)

@app.route("/test")
def test():
    old = l.update(1)
    sleep(3)
    return jsonify({"Old TaS value" : old})

Now, when I run this locally and make 2 requests within 3 seconds, the responses I get are: {"Old TaS value": 0} and {"Old TaS value": 1}, so it looks like my TaS works nicely. However, when I push it to an Azure dev server and make two concurrent requests, I get {"Old TaS value": 0} and {"Old TaS value": 0}... After the two concurrent requests have finished and I make one or more new requests (concurrent or not, it doesn't matter) I do always get {"Old TaS value": 1} responses.

What is going on? It looks like Azure only actually executes 1 of multiple identical concurrent requests and then returns its result to all requests. Even when I add random unique get parameters to the urls of the concurrent requests, they all respond with {"Old TaS value": 0}. It feels like very weird caching I didn't ask for.

Joris
  • 15
  • 4

1 Answers1

3

No, that's not what is happening.

Your production environment is running multiple processes. Each process in Python has its own memory space. And since each request blocks for 3 seconds, making multiple requests within that time means that each is served by a different process.

You should not use the global memory space to store things between requests. You need an external store, such as a database. Redis is a good choice for this sort of thing.

Daniel Roseman
  • 588,541
  • 66
  • 880
  • 895