fix: async runtime error

This commit is contained in:
xkeyC 2025-12-05 17:24:52 +08:00
parent 289691896d
commit 39ddea7254
8 changed files with 86 additions and 78 deletions

View File

@ -16,7 +16,7 @@ import 'package:flutter_rust_bridge/flutter_rust_bridge_for_generated.dart';
/// - default_download_dir: The default directory to store downloads /// - default_download_dir: The default directory to store downloads
/// - upload_limit_bps: Upload speed limit in bytes per second (0 = unlimited) /// - upload_limit_bps: Upload speed limit in bytes per second (0 = unlimited)
/// - download_limit_bps: Download speed limit in bytes per second (0 = unlimited) /// - download_limit_bps: Download speed limit in bytes per second (0 = unlimited)
void downloaderInit({ Future<void> downloaderInit({
required String workingDir, required String workingDir,
required String defaultDownloadDir, required String defaultDownloadDir,
int? uploadLimitBps, int? uploadLimitBps,

View File

@ -128,7 +128,7 @@ abstract class RustLibApi extends BaseApi {
Future<bool> crateApiDownloaderApiDownloaderHasActiveTasks(); Future<bool> crateApiDownloaderApiDownloaderHasActiveTasks();
void crateApiDownloaderApiDownloaderInit({ Future<void> crateApiDownloaderApiDownloaderInit({
required String workingDir, required String workingDir,
required String defaultDownloadDir, required String defaultDownloadDir,
int? uploadLimitBps, int? uploadLimitBps,
@ -743,20 +743,21 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi {
); );
@override @override
void crateApiDownloaderApiDownloaderInit({ Future<void> crateApiDownloaderApiDownloaderInit({
required String workingDir, required String workingDir,
required String defaultDownloadDir, required String defaultDownloadDir,
int? uploadLimitBps, int? uploadLimitBps,
int? downloadLimitBps, int? downloadLimitBps,
}) { }) {
return handler.executeSync( return handler.executeNormal(
SyncTask( NormalTask(
callFfi: () { callFfi: (port_) {
var arg0 = cst_encode_String(workingDir); var arg0 = cst_encode_String(workingDir);
var arg1 = cst_encode_String(defaultDownloadDir); var arg1 = cst_encode_String(defaultDownloadDir);
var arg2 = cst_encode_opt_box_autoadd_u_32(uploadLimitBps); var arg2 = cst_encode_opt_box_autoadd_u_32(uploadLimitBps);
var arg3 = cst_encode_opt_box_autoadd_u_32(downloadLimitBps); var arg3 = cst_encode_opt_box_autoadd_u_32(downloadLimitBps);
return wire.wire__crate__api__downloader_api__downloader_init( return wire.wire__crate__api__downloader_api__downloader_init(
port_,
arg0, arg0,
arg1, arg1,
arg2, arg2,

View File

@ -1383,13 +1383,15 @@ class RustLibWire implements BaseWire {
_wire__crate__api__downloader_api__downloader_has_active_tasksPtr _wire__crate__api__downloader_api__downloader_has_active_tasksPtr
.asFunction<void Function(int)>(); .asFunction<void Function(int)>();
WireSyncRust2DartDco wire__crate__api__downloader_api__downloader_init( void wire__crate__api__downloader_api__downloader_init(
int port_,
ffi.Pointer<wire_cst_list_prim_u_8_strict> working_dir, ffi.Pointer<wire_cst_list_prim_u_8_strict> working_dir,
ffi.Pointer<wire_cst_list_prim_u_8_strict> default_download_dir, ffi.Pointer<wire_cst_list_prim_u_8_strict> default_download_dir,
ffi.Pointer<ffi.Uint32> upload_limit_bps, ffi.Pointer<ffi.Uint32> upload_limit_bps,
ffi.Pointer<ffi.Uint32> download_limit_bps, ffi.Pointer<ffi.Uint32> download_limit_bps,
) { ) {
return _wire__crate__api__downloader_api__downloader_init( return _wire__crate__api__downloader_api__downloader_init(
port_,
working_dir, working_dir,
default_download_dir, default_download_dir,
upload_limit_bps, upload_limit_bps,
@ -1400,7 +1402,8 @@ class RustLibWire implements BaseWire {
late final _wire__crate__api__downloader_api__downloader_initPtr = late final _wire__crate__api__downloader_api__downloader_initPtr =
_lookup< _lookup<
ffi.NativeFunction< ffi.NativeFunction<
WireSyncRust2DartDco Function( ffi.Void Function(
ffi.Int64,
ffi.Pointer<wire_cst_list_prim_u_8_strict>, ffi.Pointer<wire_cst_list_prim_u_8_strict>,
ffi.Pointer<wire_cst_list_prim_u_8_strict>, ffi.Pointer<wire_cst_list_prim_u_8_strict>,
ffi.Pointer<ffi.Uint32>, ffi.Pointer<ffi.Uint32>,
@ -1413,7 +1416,8 @@ class RustLibWire implements BaseWire {
late final _wire__crate__api__downloader_api__downloader_init = late final _wire__crate__api__downloader_api__downloader_init =
_wire__crate__api__downloader_api__downloader_initPtr _wire__crate__api__downloader_api__downloader_initPtr
.asFunction< .asFunction<
WireSyncRust2DartDco Function( void Function(
int,
ffi.Pointer<wire_cst_list_prim_u_8_strict>, ffi.Pointer<wire_cst_list_prim_u_8_strict>,
ffi.Pointer<wire_cst_list_prim_u_8_strict>, ffi.Pointer<wire_cst_list_prim_u_8_strict>,
ffi.Pointer<ffi.Uint32>, ffi.Pointer<ffi.Uint32>,

View File

@ -86,7 +86,7 @@ class DownloadManager extends _$DownloadManager {
} }
// Initialize the Rust downloader with optional speed limits // Initialize the Rust downloader with optional speed limits
downloader_api.downloaderInit( await downloader_api.downloaderInit(
workingDir: state.workingDir, workingDir: state.workingDir,
defaultDownloadDir: state.downloadDir, defaultDownloadDir: state.downloadDir,
uploadLimitBps: uploadLimitBps, uploadLimitBps: uploadLimitBps,

View File

@ -41,7 +41,7 @@ final class DownloadManagerProvider
} }
} }
String _$downloadManagerHash() => r'f0fd818851be0d1c9e6774803aae465c33843cde'; String _$downloadManagerHash() => r'95a8105bb544c8a1996f321e1d0258c41e18effa';
abstract class _$DownloadManager extends $Notifier<DownloadManagerState> { abstract class _$DownloadManager extends $Notifier<DownloadManagerState> {
DownloadManagerState build(); DownloadManagerState build();

View File

@ -42,7 +42,7 @@ final class HomeDownloaderUIModelProvider
} }
String _$homeDownloaderUIModelHash() => String _$homeDownloaderUIModelHash() =>
r'3dd2ca0b1c03113d577c322de81078faa378230b'; r'567cf106d69ed24a5adb8d7f4ad9c422cf33dc1e';
abstract class _$HomeDownloaderUIModel abstract class _$HomeDownloaderUIModel
extends $Notifier<HomeDownloaderUIState> { extends $Notifier<HomeDownloaderUIState> {

View File

@ -76,8 +76,7 @@ pub struct DownloadGlobalStat {
/// - default_download_dir: The default directory to store downloads /// - default_download_dir: The default directory to store downloads
/// - upload_limit_bps: Upload speed limit in bytes per second (0 = unlimited) /// - upload_limit_bps: Upload speed limit in bytes per second (0 = unlimited)
/// - download_limit_bps: Download speed limit in bytes per second (0 = unlimited) /// - download_limit_bps: Download speed limit in bytes per second (0 = unlimited)
#[frb(sync)] pub async fn downloader_init(
pub fn downloader_init(
working_dir: String, working_dir: String,
default_download_dir: String, default_download_dir: String,
upload_limit_bps: Option<u32>, upload_limit_bps: Option<u32>,
@ -88,60 +87,57 @@ pub fn downloader_init(
return Ok(()); return Ok(());
} }
let rt = tokio::runtime::Handle::current(); let _lock = SESSION_INIT_LOCK.lock().await;
rt.block_on(async {
let _lock = SESSION_INIT_LOCK.lock().await; // Double check after acquiring lock
if SESSION.read().is_some() {
// Double check after acquiring lock return Ok(());
if SESSION.read().is_some() { }
return Ok(());
}
// Working directory for persistence and session data // Working directory for persistence and session data
let working_folder = PathBuf::from(&working_dir); let working_folder = PathBuf::from(&working_dir);
std::fs::create_dir_all(&working_folder)?; std::fs::create_dir_all(&working_folder)?;
// Default download folder // Default download folder
let output_folder = PathBuf::from(&default_download_dir); let output_folder = PathBuf::from(&default_download_dir);
std::fs::create_dir_all(&output_folder)?; std::fs::create_dir_all(&output_folder)?;
// Create persistence folder for session state in working directory // Create persistence folder for session state in working directory
let persistence_folder = working_folder.join("rqbit-session"); let persistence_folder = working_folder.join("rqbit-session");
std::fs::create_dir_all(&persistence_folder)?; std::fs::create_dir_all(&persistence_folder)?;
// DHT persistence file in working directory // DHT persistence file in working directory
let dht_persistence_file = working_folder.join("dht.json"); let dht_persistence_file = working_folder.join("dht.json");
let session = Session::new_with_opts( let session = Session::new_with_opts(
output_folder, output_folder,
SessionOptions { SessionOptions {
disable_dht: false, disable_dht: false,
disable_dht_persistence: false, disable_dht_persistence: false,
// Configure DHT persistence to use working directory // Configure DHT persistence to use working directory
dht_config: Some(PersistentDhtConfig { dht_config: Some(PersistentDhtConfig {
config_filename: Some(dht_persistence_file), config_filename: Some(dht_persistence_file),
..Default::default()
}),
// Enable JSON-based session persistence for task recovery
persistence: Some(SessionPersistenceConfig::Json {
folder: Some(persistence_folder),
}),
fastresume: false,
// Configure rate limits
ratelimits: LimitsConfig {
upload_bps: upload_limit_bps.and_then(NonZeroU32::new),
download_bps: download_limit_bps.and_then(NonZeroU32::new),
},
..Default::default() ..Default::default()
}),
// Enable JSON-based session persistence for task recovery
persistence: Some(SessionPersistenceConfig::Json {
folder: Some(persistence_folder),
}),
fastresume: false,
// Configure rate limits
ratelimits: LimitsConfig {
upload_bps: upload_limit_bps.and_then(NonZeroU32::new),
download_bps: download_limit_bps.and_then(NonZeroU32::new),
}, },
) ..Default::default()
.await },
.context("Failed to create rqbit session")?; )
.await
.context("Failed to create rqbit session")?;
*SESSION.write() = Some(session); *SESSION.write() = Some(session);
Ok(()) Ok(())
})
} }
/// Check if the downloader is initialized /// Check if the downloader is initialized

View File

@ -401,33 +401,38 @@ fn wire__crate__api__downloader_api__downloader_has_active_tasks_impl(
) )
} }
fn wire__crate__api__downloader_api__downloader_init_impl( fn wire__crate__api__downloader_api__downloader_init_impl(
port_: flutter_rust_bridge::for_generated::MessagePort,
working_dir: impl CstDecode<String>, working_dir: impl CstDecode<String>,
default_download_dir: impl CstDecode<String>, default_download_dir: impl CstDecode<String>,
upload_limit_bps: impl CstDecode<Option<u32>>, upload_limit_bps: impl CstDecode<Option<u32>>,
download_limit_bps: impl CstDecode<Option<u32>>, download_limit_bps: impl CstDecode<Option<u32>>,
) -> flutter_rust_bridge::for_generated::WireSyncRust2DartDco { ) {
FLUTTER_RUST_BRIDGE_HANDLER.wrap_sync::<flutter_rust_bridge::for_generated::DcoCodec, _>( FLUTTER_RUST_BRIDGE_HANDLER.wrap_async::<flutter_rust_bridge::for_generated::DcoCodec, _, _, _>(
flutter_rust_bridge::for_generated::TaskInfo { flutter_rust_bridge::for_generated::TaskInfo {
debug_name: "downloader_init", debug_name: "downloader_init",
port: None, port: Some(port_),
mode: flutter_rust_bridge::for_generated::FfiCallMode::Sync, mode: flutter_rust_bridge::for_generated::FfiCallMode::Normal,
}, },
move || { move || {
let api_working_dir = working_dir.cst_decode(); let api_working_dir = working_dir.cst_decode();
let api_default_download_dir = default_download_dir.cst_decode(); let api_default_download_dir = default_download_dir.cst_decode();
let api_upload_limit_bps = upload_limit_bps.cst_decode(); let api_upload_limit_bps = upload_limit_bps.cst_decode();
let api_download_limit_bps = download_limit_bps.cst_decode(); let api_download_limit_bps = download_limit_bps.cst_decode();
transform_result_dco::<_, _, flutter_rust_bridge::for_generated::anyhow::Error>( move |context| async move {
(move || { transform_result_dco::<_, _, flutter_rust_bridge::for_generated::anyhow::Error>(
let output_ok = crate::api::downloader_api::downloader_init( (move || async move {
api_working_dir, let output_ok = crate::api::downloader_api::downloader_init(
api_default_download_dir, api_working_dir,
api_upload_limit_bps, api_default_download_dir,
api_download_limit_bps, api_upload_limit_bps,
)?; api_download_limit_bps,
Ok(output_ok) )
})(), .await?;
) Ok(output_ok)
})()
.await,
)
}
}, },
) )
} }
@ -4093,12 +4098,14 @@ mod io {
#[unsafe(no_mangle)] #[unsafe(no_mangle)]
pub extern "C" fn frbgen_starcitizen_doctor_wire__crate__api__downloader_api__downloader_init( pub extern "C" fn frbgen_starcitizen_doctor_wire__crate__api__downloader_api__downloader_init(
port_: i64,
working_dir: *mut wire_cst_list_prim_u_8_strict, working_dir: *mut wire_cst_list_prim_u_8_strict,
default_download_dir: *mut wire_cst_list_prim_u_8_strict, default_download_dir: *mut wire_cst_list_prim_u_8_strict,
upload_limit_bps: *mut u32, upload_limit_bps: *mut u32,
download_limit_bps: *mut u32, download_limit_bps: *mut u32,
) -> flutter_rust_bridge::for_generated::WireSyncRust2DartDco { ) {
wire__crate__api__downloader_api__downloader_init_impl( wire__crate__api__downloader_api__downloader_init_impl(
port_,
working_dir, working_dir,
default_download_dir, default_download_dir,
upload_limit_bps, upload_limit_bps,