3
\$\begingroup\$

I'm just after some sanity checking of this code:

public struct function defer(required function job, function onSuccess, function onFailure, function onError, function onTerminate){
    var threadId = "deferredThread_#createUuid()#";

    local[threadId] = "";

    try {
        cfthread.status = "Running";
        thread name=threadId action="run" attributecollection=arguments {
            try {
                successData.result = job();
                cfthread.status = "Completed";
                if (structKeyExists(attributes, "onSuccess")){
                    onSuccess(successData);
                }
            } catch (any e){
                cfthread.status = "Failed";
                if (structKeyExists(attributes, "onFailure")){
                    onFailure(e);
                }else{
                    rethrow;
                }
            }
        }
    } catch (any e){
        cfthread.status = "Errored";
        if (structKeyExists(arguments, "onError")){
            onError(e);
        }else{
            rethrow;
        }
    }
    return {
        getStatus = function(){
            return cfthread.status;
        },
        getThreadId = function(){
            return threadId;
        },
        terminate = function(){
            if (cfthread.status == "Running"){
                thread name=threadId action="terminate";
                cfthread.status = "Terminated";
                if (isDefined("onTerminate")){
                    onTerminate();
                }
            }
        }
    };
}

Blog article about it: "Threads, callbacks, closure and a pub", and tests and stuff on Github.

Here is a summary of that, copied from the article, and edited for length & situation:

A week or so ago I encountered a feature proposition for CFML which was adding closure callback support to the following functions/operations so they can be processed natively in the background (non-blocking) and then call back when done:

FileRead FileWrite etc

Basically any operation that can block a network or local resource. Imagine doing this:

fileRead( file, function(contents){
    // process file here in the background once it is read.
});

This is a reasonable idea in general, but I don't think the suggested approach is very good as it's too focused on specific pain points.

My suggested approach would be more all-encompassing. Why limit this functionality to a subset of predetermined built-in functions? What about other built-in operations that might be slow, but otherwise doesn't need to interact with the rest of the code subsequent to it in the request? What about custom code that is similar? It makes little sense to me to "hard-code" this sort of behaviour to specific operations, to me.

A better solution would be to provide a general mechanism that can be used by any code to background-thread its execution, and fire callbacks on completion, failure etc, so as to kick off the next process, or flag-up that the process has completed.

Then it occurred to me that I thought I could knock a solution out to this using a single function. Not a very complete solution, but a solution nevertheless.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.