Frappe.cache().get_value() inside for loop not working

Hello,

i want to control the cancellation of a server process with a value in the Redis-Cache.

To explain the problem, I created a piece of code that iterates through a loop 20 times.

@frappe.whitelist()    
def cache_cancel_loop():

    if cancel == 0:      
        for i in range(0, 20):
            time.sleep(1)
            #Get Cancel-Condition      
            cancel = frappe.cache().get_value("cancel-condition"))
            if cancel is None:
                cancel = 0
            if cancel >= 1:
                break

    return {
        "cancel": cancel,
        "status": 1
    }

To stop the loop, I call this Python function via the Javascript function frappe.call() to set the termination variable.

@frappe.whitelist()
def cache_set_cancel():
    frappe.cache().set_value("cancel-condition", 1)
    
    return {
        "cancel": 1,
        "status": 1
    }

Why doesn’t the call

cancel = frappe.cache().get_value("cancel-condition")) 

return the value 1 within the loop and terminate the loop?

If I make a separate javascript frappe.call() to get the value from the user interface, then the value 1 is returned to me.

@frappe.whitelist()    
def cache_get_cancel():
    cancel = frappe.cache().get_value("cancel-condition")
    
    return {
        "cancel": cancel,
        "status": 1
    }

I’m confused. :face_with_spiral_eyes:

Thanks in advance for your help.

The issue is that Frappe’s frappe.cache() uses an in-process local cache frappe.local.cache. Inside a long running loop, get_value() returns the locally cached value from when the request started not a fresh value from Redis

your separate cache_get_cancel() call works because it runs in a new request with a clean context. Use the raw Redis client to always get a fresh value

redis_client = frappe.cache().redis
full_key = frappe.cache().make_key(“cancel-condition”)
raw_value = redis_client.get(full_key)
cancel = int(raw_value) if raw_value else 0

try this code

Oh :smiley: - thank you so much for the answer! :saluting_face:

1 Like

redis_client = frappe.cache().redis did not working - frappe.cache() returns the RedisWrapper :roll_eyes:

But the hint that Frappe’s Redis queries are also cached put me on the right track.

The solution was quite simple: you just have to set the additional parameter use_local_cache to False.

cancel = frappe.cache.get_value("cancel-condition"), use_local_cache=False)

:partying_face:

1 Like