import ballerina/io;

type Update record {
    int updateIndex;
    int stockMnt;
};

public function main() returns error? {
    Update updates = {updateIndex: 0, stockMnt: 100};
    transaction {
        check doUpdate(updates);
        check commit;
    }
}

// Called within transaction stmt
transactional function doUpdate(Update u) returns error? {
    // Call non-transactional function
    foo(u);
    // Call transactional function
    bar(u);
}

function foo(Update u) {
    if transactional {
        // This is transactional context
        bar(u);
    }
}

transactional function bar(Update u) {
    io:println("Calling from a transactional context");
}

Transactional Qualifier

At compile-time, regions of code are typed as being a transactional context. Ballerina guarantees that, whenever that region is executed, there will be a current transaction. A function with a transactional qualifier can only be called from transactional context; function body will be a transactional context. transactional is also a boolean expression that tests at runtime whether there is a current transaction: used in a condition results in transactional context.

import ballerina/io;
type Update record {
    int updateIndex;
    int stockMnt;
};
public function main() returns error? {
    Update updates = {updateIndex: 0, stockMnt: 100};
    transaction {
        check doUpdate(updates);
        check commit;
    }
}
transactional function doUpdate(Update u) returns error? {

Called within transaction stmt

    foo(u);

Call non-transactional function

    bar(u);
}

Call transactional function

function foo(Update u) {
    if transactional {
        bar(u);
    }
}

This is transactional context

transactional function bar(Update u) {
    io:println("Calling from a transactional context");
}
bal run transactional_qualifier.bal
Calling from a transactional context
Calling from a transactional context