Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content
This repository was archived by the owner on Jul 7, 2025. It is now read-only.

Commit f659796

Browse files
committed
fix(bindings): run func call until completion even when future is cancelled
1 parent 4094694 commit f659796

File tree

3 files changed

+62
-37
lines changed

3 files changed

+62
-37
lines changed

midoku-bindings/Cargo.toml

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,6 @@ midoku-types.workspace = true
1616
wasmtime.workspace = true
1717

1818
parking_lot = "0.12.3"
19-
20-
[dev-dependencies]
2119
tokio.workspace = true
2220

2321
[build-dependencies]

midoku-bindings/src/bindings.rs

Lines changed: 12 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
use std::collections::HashMap;
22
use std::path::Path;
3+
use std::sync::Arc;
34

45
use midoku_settings::types::Value;
56
use midoku_types::chapter::Chapter;
@@ -23,7 +24,7 @@ use crate::state::State;
2324
/// This struct contains the bindings to a Midoku source. It is used to call
2425
/// functions in the WebAssembly component.
2526
pub struct Bindings {
26-
store: RwLock<Store<State>>,
27+
store: Arc<RwLock<Store<State>>>,
2728
initialize: Func<(), Result<(), ()>>,
2829
get_manga_list: Func<(Vec<Filter>, u32), Result<(Vec<Manga>, bool), ()>>,
2930
get_manga_details: Func<(String,), Result<Manga, ()>>,
@@ -84,7 +85,7 @@ impl Bindings {
8485
let get_page_list = get_typed_func!(instance, store, api, "get-page-list")?.into();
8586

8687
Ok(Self {
87-
store: RwLock::new(store),
88+
store: Arc::new(RwLock::new(store)),
8889
initialize,
8990
get_manga_list,
9091
get_manga_details,
@@ -99,9 +100,7 @@ impl Bindings {
99100
/// calling other functions. This may include setting up rate limiters or
100101
/// other configuration.
101102
pub async fn initialize(&self) -> Result<(), ()> {
102-
let mut store = self.store.write();
103-
104-
self.initialize.call(&mut store, ()).await?
103+
self.initialize.call(self.store.clone(), ()).await?
105104
}
106105

107106
/// Get a list of manga from the source.
@@ -115,10 +114,8 @@ impl Bindings {
115114
filters: Vec<Filter>,
116115
page: u32,
117116
) -> Result<(Vec<Manga>, bool), ()> {
118-
let mut store = self.store.write();
119-
120117
self.get_manga_list
121-
.call(&mut store, (filters, page))
118+
.call(self.store.clone(), (filters, page))
122119
.await?
123120
}
124121

@@ -128,9 +125,9 @@ impl Bindings {
128125
///
129126
/// * `id` - The ID of the manga to get details for.
130127
pub async fn get_manga_details(&self, id: String) -> Result<Manga, ()> {
131-
let mut store = self.store.write();
132-
133-
self.get_manga_details.call(&mut store, (id,)).await?
128+
self.get_manga_details
129+
.call(self.store.clone(), (id,))
130+
.await?
134131
}
135132

136133
/// Get a list of chapters for a specific manga.
@@ -139,9 +136,9 @@ impl Bindings {
139136
///
140137
/// * `id` - The ID of the manga to get chapters for.
141138
pub async fn get_chapter_list(&self, id: String) -> Result<Vec<Chapter>, ()> {
142-
let mut store = self.store.write();
143-
144-
self.get_chapter_list.call(&mut store, (id,)).await?
139+
self.get_chapter_list
140+
.call(self.store.clone(), (id,))
141+
.await?
145142
}
146143

147144
/// Get a list of pages for a specific chapter.
@@ -151,10 +148,8 @@ impl Bindings {
151148
/// * `id` - The ID of the manga.
152149
/// * `chapter_id` - The ID of the chapter.
153150
pub async fn get_page_list(&self, id: String, chapter_id: String) -> Result<Vec<Page>, ()> {
154-
let mut store = self.store.write();
155-
156151
self.get_page_list
157-
.call(&mut store, (id, chapter_id))
152+
.call(self.store.clone(), (id, chapter_id))
158153
.await?
159154
}
160155

midoku-bindings/src/func.rs

Lines changed: 50 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,11 @@
1+
use std::sync::Arc;
2+
3+
use parking_lot::RwLock;
4+
use tokio::task::{spawn_local, LocalSet};
15
use wasmtime::component::{ComponentNamedList, Lift, Lower, TypedFunc};
2-
use wasmtime::{AsContextMut, Store};
6+
use wasmtime::Store;
37

4-
pub(crate) struct Func<Params, Return>(TypedFunc<Params, (Return,)>)
8+
pub(crate) struct Func<Params, Return>(Arc<TypedFunc<Params, (Return,)>>)
59
where
610
Params: Send + Sync,
711
Return: Send + Sync,
@@ -18,33 +22,61 @@ where
1822
(Return,): ComponentNamedList + Lift,
1923
{
2024
fn from(value: TypedFunc<Params, (Return,)>) -> Self {
21-
Func(value)
25+
Func(Arc::new(value))
2226
}
2327
}
2428

2529
impl<Params, Return> Func<Params, Return>
2630
where
27-
Params: Send + Sync,
28-
Return: Send + Sync,
31+
Params: Send + Sync + 'static,
32+
Return: Send + Sync + 'static,
2933
// Bounds from [`TypedFunc`]:
3034
Params: ComponentNamedList + Lower,
3135
(Return,): ComponentNamedList + Lift,
3236
{
33-
pub async fn call<T: Send>(&self, store: &mut Store<T>, params: Params) -> Result<Return, ()> {
34-
// function call
35-
let result = self
36-
.0
37-
.call_async(store.as_context_mut(), params)
37+
async fn call_async<T>(
38+
store: &mut Store<T>,
39+
func: &TypedFunc<Params, (Return,)>,
40+
params: Params,
41+
) -> Result<Return, ()>
42+
where
43+
T: Send + 'static,
44+
{
45+
func.call_async(store, params)
3846
.await
39-
.map_err(|_| ())?
40-
.0;
47+
.map_err(|_| ())
48+
.map(|res| res.0)
49+
}
4150

42-
// mandatory cleanup after successful call
43-
self.0
44-
.post_return_async(store.as_context_mut())
45-
.await
46-
.map_err(|_| ())?;
51+
async fn post_return_async<T>(
52+
store: &mut Store<T>,
53+
func: &TypedFunc<Params, (Return,)>,
54+
) -> Result<(), ()>
55+
where
56+
T: Send + 'static,
57+
{
58+
func.post_return_async(store).await.map_err(|_| ())
59+
}
4760

48-
Ok(result)
61+
pub async fn call<T: Send + 'static>(
62+
&self,
63+
store: Arc<RwLock<Store<T>>>,
64+
params: Params,
65+
) -> Result<Return, ()> {
66+
let func = self.0.clone();
67+
68+
let local = LocalSet::new();
69+
local
70+
.run_until(async move {
71+
spawn_local(async move {
72+
let mut store = store.write();
73+
let result = Self::call_async(&mut store, &func, params).await?;
74+
Self::post_return_async(&mut store, &func).await?;
75+
Ok(result)
76+
})
77+
.await
78+
})
79+
.await
80+
.expect("could not join handle")
4981
}
5082
}

0 commit comments

Comments
 (0)