Search code examples
async-awaitconcurrencyballerinaballerina-swan-lake

How to alternatively wait on a dynamic set of Ballerina future values?


I have a requirement of writing a ballerina util function that can alternatively wait on a given set of futures and return the result, where the number of future values can vary as shown in the below pseudo source code.

function getWaitResult(future[] futures) returns any|error {
    return wait futures[0] | futures[1] | ... | futures[n];
}

What would be the best approach to have the same functionality implemented using Ballerina Swan Lake versions?


Solution

  • Since you have to provide each future reference statically, I would suggest you to generate more strands combining alternate wait actions.

    import ballerina/lang.runtime;
    import ballerina/io;
    import ballerina/random;
    
    function waitHelper(future<any>[] fs) returns any|error {
        match fs {
            var [f] => {
                return wait f;
            }
            var [f, x] => {
                return wait f | x;
            }
            var [f, x, y] => {
                return wait f | x | y;
            }
            var [f, x, y, ...r] => {
                var rest = start waitHelper(r);
                return wait f | x | y | rest;
            }
        }
    }
    
    function foo() returns int {
        int r = checkpanic random:createIntInRange(10, 200);
        io:println("waiting (ms)... ", r);
        runtime:sleep((<decimal>r)/1000);
        return r;
    }
    
    public function main() {
        future<int>[] f = [];
        foreach int i in 0...9 {
            var r = start foo();
            f.push(r);
        }
        any|error got = waitHelper(f);
        io:println("Got: ", got);
    }