[Coldbox 6] Overwriting Flash RAM Trouble

I’ve got a Coldbox app that I’m trying to migrate over from explicitly using the session scope to using the flash object. However, I’ve been experiencing some unpredictable behavior when attempting to persist data in flash using an ajax request and then retrieving it on a page refresh. Here’s what my code looks like:

I’m currently using ACF 2018.

I persist the data in Flash RAM via an ajax call to a handler. The handler looks like this:

function save( event, rc, prc ) {

    param rc.key = "";
    param rc.data = {};

    if ( isJson( rc.data ) ) {
        rc.data = deSerializeJson( rc.data );
    }

    // if we have a key and some data to store, persist it in Flash RAM
    if ( isSimpleValue( rc.key ) && isStruct( rc.data ) ) {
        flash.put(
            name = rc.key,
            value = rc.data,
            autoPurge = false,
            saveNow = true,
            inflateToRC = false
        );
    }

    return {
        "key": rc.key,
        "data": rc.data
    };

}

My retrieval handler looks like this:

function index( event, rc, prc ){
        
    var data = flash.get( "myKey", {
        "search" : "",
        "statusId" : "",
        "categoryId" : "",
        "hideChildren": ""
    } );

    writeDump( data );

}

The first execution of my ajax handler works. I set statusId to a value of 1 and I can see the ajax response returns the correct value. When I refresh the page, I can see my intended data appear in the dump. However, on subsequent executions of the ajax handler, the Flash RAM doesn’t persist the updated data.

When I dump out the session scope after the first ajax call, this is what I see:
image

On the subsequent ajax request, I updated statusId to a value of 2. I confirmed that I could see the proper value from the ajax response. However, when I refresh the handler I still see statusId has a value of 1.

image

I would have expected the value to be 2. Am I missing something? Do I need to do anything special to have flash overwrite existing data?

Update: After tooling around a bit, and a few cups of coffee, I have some additional information. My problem is the result of a race condition.

In this app, Javascript makes two separate AJAX requests simultaneously:

  1. /filters/save (saves some form data in flash ram)
  2. /pages/listAsDataTable (gets a list of data and returns it in a dataTable friendly format)

Coldbox automatically re-saves Flash RAM at the end of every request. Therefore, if Request 2 starts before Request 1 finishes, and Request 2 ends after Request 1 finishes, it will overwrite the Flash RAM “saved” in Request 1 with old data from Request 2.

I’m not sure why Coldbox would need to re-save all Flash RAM keys on every request that has a keep value of true and autoPurge set to false. This feels like a possible bug to me or at least contributes to unpredictable results in apps where AJAX calls may be running side-by-side.

I would be curious to hear others’ thoughts on this. For now, I’m going back to old-school direct session access to work around the issue.

I say we can totally improve this to avoid race conditions. What would you suggest?

@lmajano I’m just thinking out loud here, but I wonder if it would be as simple as not re-saving flash RAM keys that have a keep value of true at the end of the request? Once you’ve executed a put() with keep=true and autoPurge=false, I would think it should stay there and not be overwritten until put() is called again.

Another idea would be to have some type of request timestamp comparison to ensure that old Flash data can never replace newer data.

Finally, another possibility could be to add a new argument, immutable, that would preserve the original value of a key and prevent it from being overwritten at the end of subsequent requests.

For my use case, I didn’t realize that Flash RAM data overwrites itself at the end of every request. My intention was to use Flash storage to keep track of a user’s settings as they navigate a website. For example, filter form fields, which tabs were selected, etc… I was using an AJAX call to manually save these settings in temporary storage any time the user changed something in the user interface.