Skip to content

Persist the state with vm.invoke #4175

Open
@lastmjs

Description

@lastmjs

Is there a way to persist the state/scope when using vm.invoke? For my application, I have a global interpreter that is executed once with the user's code. This sets up their Python application. This is running on the Internet Computer, basically a decentralized cloud environment. The interpreter will always be running, such as in a long-running server process.

I need the interpreter and the scope to be persisted across calls. Right now record_message does not persist the message. I'm not sure how to provide the scope appropriately when using vm.invoke.

saved_message = ''

@update
def record_message(message: str) -> str:
    saved_message = message
    return saved_message

@query
def get_message() -> str:
    return saved_message
use rustpython;
use rustpython::vm::convert::ToPyObject;
static mut _KYBRA_INTERPRETER_OPTION: Option<rustpython::vm::Interpreter> = None;
static mut _KYBRA_SCOPE_OPTION: Option<rustpython::vm::scope::Scope> = None;

// There's other code, such as initializing the interpreter and the scope, that is not shown here

#[ic_cdk_macros::update]
#[candid::candid_method(update)]
async fn record_message(message: String) -> String {
    unsafe {
        let _kybra_interpreter = _KYBRA_INTERPRETER_OPTION.as_mut().unwrap();
        let _kybra_scope = _KYBRA_SCOPE_OPTION.as_mut().unwrap();
        let result = _kybra_interpreter.enter(|vm| {
            let method_py_object_ref = _kybra_scope.globals.get_item("record_message", vm).unwrap();
            let result_py_object_ref = vm
                .invoke(
                    &method_py_object_ref,
                    (message.try_into_vm_value(vm).unwrap(),),
                )
                .unwrap();

            result_py_object_ref.try_from_vm_value(vm).unwrap()
        });
        result
    }
}

#[ic_cdk_macros::query]
#[candid::candid_method(query)]
async fn get_message() -> String {
    unsafe {
        let _kybra_interpreter = _KYBRA_INTERPRETER_OPTION.as_mut().unwrap();
        let _kybra_scope = _KYBRA_SCOPE_OPTION.as_mut().unwrap();
        let result = _kybra_interpreter.enter(|vm| {
            let method_py_object_ref = _kybra_scope.globals.get_item("get_message", vm).unwrap();
            let result_py_object_ref = vm.invoke(&method_py_object_ref, ()).unwrap();

            result_py_object_ref.try_from_vm_value(vm).unwrap()
        });
        result
    }
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions