Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Reuse contract and service instances inside transaction (#1506)
* Add missing sentence period to documentation Ensure consistency. * Create `User{Contract,Service}Instance` aliases Make it easier to use the dynamically dispatched types. * Rename `as_inner` into `inner` Try to be closer to the Rust API naming conventions. * Simplify code when accessing inner only once No need to create a separate binding for `this` if it's only going to be used once. * Refactor to split `SyncRuntimeInternal` methods Create separate blocks for the contract-specific methods and the service-specific methods. * Refactor to add a `load_contract_instance` method Prepare to use it to reload active contract instances without having to create a new instance. Add a `Weak` reference in `SyncRuntimeInternal` to reference the handle used to reference itself. * Refactor runtime set-up for cross-app. calls Place common code in new methods so that there's only one place to update. * Replace `WRITABLE: bool` with `ContractOrService` Use a generic type parameter instead of a const parameter in order to have a single map of loaded application instances (either contracts or services). * Wrap contract instances in an `Arc<Mutex<_>>` Prepare to share the instances in the runtime. * Create a `LoadedApplication` helper type Store the data necessary for running an application instance. * Return `LoadedApplication` directly Prepare to return the value stored inside a map. * Reuse contract instances inside a transaction Store the loaded instances in a map, and reuse them if there are more calls to them. * Refactor to create `load_service_instance` method Like the `load_contract_instance` method, return an `Arc<Mutex<_>>` with the instance and the parameters directly, in preparation to share the instance. * Reuse service instances inside a query Store the loaded instances in a map, and reuse them if there are more calls to them. * Fix deadlock caused by circular references The `ExecutionStateView` starts a thread to execute the application with the synchronous runtime, and in its original thread it loops listening for requests from the application. When the execution finishes, the thread ends and when the runtime is dropped it also drops the sender of requests to the `ExecutionStateView`. Therefore the `ExecutionStateView` then detects that the channel has closed and finishes the loop continuing execution. However, with the addition of the `loaded_applications` map, each loaded application has a strong reference to the runtime, so there's a circular dependency which prevents the `SyncRuntimeInternal` type from dropping. This prevents the channel from closing, and causes a deadlock. To avoid this situation, the `loaded_applications` map must be cleared at the end of the execution, independently if it succeeded or if it failed. * Ensure that the logger is only installed once Prepare to allow the same Wasm guest instance to be reused for different calls inside the same transaction. * Refactor to split the `MockApplication` type Create a separate `MockApplicationInstance` that does not share the expected calls list. This means that now the application forwards the list to the created instance, and each instance has a separate call list. This tests if the instances are reused or not. If they are not reused, session calls will always fail. * replace ContractOrService by UserInstance * remove weak reference --------- Co-authored-by: Mathieu Baudet <1105398+ma2bd@users.noreply.github.com>
- Loading branch information