diff --git a/veilid-core/src/attachment_manager.rs b/veilid-core/src/attachment_manager.rs index 60f3448a..3357500c 100644 --- a/veilid-core/src/attachment_manager.rs +++ b/veilid-core/src/attachment_manager.rs @@ -357,38 +357,38 @@ impl AttachmentManager { attachment_machine.state() } - pub async fn wait_for_state(&self, state: AttachmentState, timeout_ms: Option) -> bool { - let start_time = intf::get_timestamp(); + // pub async fn wait_for_state(&self, state: AttachmentState, timeout_ms: Option) -> bool { + // let start_time = intf::get_timestamp(); - loop { - let (current_state, eventual) = self - .inner - .lock() - .attachment_machine - .state_eventual_instance(); - if current_state == state { - break; - } - if let Some(timeout_ms) = timeout_ms { - let timeout_time = start_time + (timeout_ms as u64 * 1000); - let cur_time = intf::get_timestamp(); - if timeout_time > cur_time { - let timeout_dur_ms = ((timeout_time - cur_time) / 1000) as u32; + // loop { + // let (current_state, eventual) = self + // .inner + // .lock() + // .attachment_machine + // .state_eventual_instance(); + // if current_state == state { + // break; + // } + // if let Some(timeout_ms) = timeout_ms { + // let timeout_time = start_time + (timeout_ms as u64 * 1000); + // let cur_time = intf::get_timestamp(); + // if timeout_time > cur_time { + // let timeout_dur_ms = ((timeout_time - cur_time) / 1000) as u32; - if match intf::timeout(timeout_dur_ms, eventual).await { - Ok(v) => v, - Err(_) => return false, - } == state - { - return true; - } - } else { - return false; - } - } else if eventual.await == state { - break; - } - } - true - } + // if match intf::timeout(timeout_dur_ms, eventual).await { + // Ok(v) => v, + // Err(_) => return false, + // } == state + // { + // return true; + // } + // } else { + // return false; + // } + // } else if eventual.await == state { + // break; + // } + // } + // true + // } } diff --git a/veilid-core/src/core_context.rs b/veilid-core/src/core_context.rs index f088cf5f..f045c456 100644 --- a/veilid-core/src/core_context.rs +++ b/veilid-core/src/core_context.rs @@ -21,6 +21,7 @@ pub struct VeilidCoreContext { pub block_store: BlockStore, pub crypto: Crypto, pub attachment_manager: AttachmentManager, + pub update_callback: UpdateCallback, } impl VeilidCoreContext { @@ -128,12 +129,13 @@ impl VeilidCoreContext { // Set up attachment manager trace!("VeilidCoreContext::new init attachment manager"); + let update_callback_move = update_callback.clone(); let attachment_manager = AttachmentManager::new(config.clone(), table_store.clone(), crypto.clone()); if let Err(e) = attachment_manager .init(Arc::new( move |_old_state: AttachmentState, new_state: AttachmentState| { - update_callback(VeilidUpdate::Attachment { state: new_state }) + update_callback_move(VeilidUpdate::Attachment { state: new_state }) }, )) .await @@ -154,6 +156,7 @@ impl VeilidCoreContext { block_store, crypto, attachment_manager, + update_callback, }) } @@ -167,6 +170,9 @@ impl VeilidCoreContext { self.protected_store.terminate().await; self.config.terminate().await; + // send final shutdown update + (self.update_callback)(VeilidUpdate::Shutdown).await; + trace!("VeilidCoreContext::shutdown complete"); ApiLogger::terminate(); } diff --git a/veilid-core/src/tests/common/test_veilid_core.rs b/veilid-core/src/tests/common/test_veilid_core.rs index 5847c32a..49d97fa0 100644 --- a/veilid-core/src/tests/common/test_veilid_core.rs +++ b/veilid-core/src/tests/common/test_veilid_core.rs @@ -22,14 +22,7 @@ pub async fn test_attach_detach() { api.attach().await.unwrap(); intf::sleep(5000).await; api.detach().await.unwrap(); - api.wait_for_update( - VeilidUpdate::Attachment { - state: AttachmentState::Detached, - }, - None, - ) - .await - .unwrap(); + intf::sleep(2000).await; api.shutdown().await; info!("--- test auto detach ---"); diff --git a/veilid-core/src/veilid_api/mod.rs b/veilid-core/src/veilid_api/mod.rs index 29df412d..6092bb1f 100644 --- a/veilid-core/src/veilid_api/mod.rs +++ b/veilid-core/src/veilid_api/mod.rs @@ -168,6 +168,7 @@ pub enum VeilidUpdate { Attachment { state: AttachmentState, }, + Shutdown, } #[derive(Debug, Clone, Serialize, Deserialize)] @@ -1216,28 +1217,6 @@ impl VeilidAPI { Ok(()) } - // wait for a matching update - pub async fn wait_for_update( - &self, - update: VeilidUpdate, - timeout_ms: Option, - ) -> Result<(), VeilidAPIError> { - match update { - VeilidUpdate::Log { - log_level: _, - message: _, - } => { - // No point in waiting for a log - } - VeilidUpdate::Attachment { state } => { - self.attachment_manager()? - .wait_for_state(state, timeout_ms) - .await; - } - } - Ok(()) - } - // Change api logging level if it is enabled pub async fn change_api_log_level(&self, log_level: VeilidConfigLogLevel) { ApiLogger::change_log_level(log_level.to_level_filter()); diff --git a/veilid-flutter/example/lib/main.dart b/veilid-flutter/example/lib/main.dart index d9ec24ac..d3b874fe 100644 --- a/veilid-flutter/example/lib/main.dart +++ b/veilid-flutter/example/lib/main.dart @@ -1,13 +1,54 @@ import 'dart:async'; +import 'package:logger/logger.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:veilid/veilid.dart'; +import 'package:logger_flutter_viewer/logger_flutter_viewer.dart'; +// Logger +var stacklog = Logger( + printer: PrettyPrinter( + methodCount: 10, + errorMethodCount: 10, + printTime: true, + colors: true, + printEmojis: true), + output: ScreenOutput()); +var log = Logger( + printer: PrettyPrinter( + methodCount: 0, + errorMethodCount: 1, + printTime: true, + colors: true, + printEmojis: true, + noBoxingByDefault: true, + ), + output: ScreenOutput()); +var barelog = Logger( + printer: PrettyPrinter( + methodCount: 0, + errorMethodCount: 0, + printTime: false, + colors: true, + printEmojis: true, + noBoxingByDefault: true, + ), + output: ScreenOutput()); + +class ScreenOutput extends LogOutput { + @override + void output(OutputEvent event) { + LogConsole.output(event); + } +} + +// Entrypoint void main() { runApp(const MyApp()); } +// Main App class MyApp extends StatefulWidget { const MyApp({Key? key}) : super(key: key); @@ -34,6 +75,10 @@ class _MyAppState extends State { } on PlatformException { veilidVersion = 'Failed to get veilid version.'; } + log.e("Error test"); + log.w("Warning test"); + stacklog.i("Info test with stacklog"); + barelog.d("debug bare-log test"); // If the widget was removed from the tree while the asynchronous platform // message was in flight, we want to discard the reply rather than calling @@ -50,11 +95,9 @@ class _MyAppState extends State { return MaterialApp( home: Scaffold( appBar: AppBar( - title: const Text('Veilid Plugin Example App'), - ), - body: Center( - child: Text('Veilid version: $_veilidVersion\n'), + title: Text('Veilid Plugin Version $_veilidVersion'), ), + body: LogConsole(dark: Theme.of(context).brightness == Brightness.dark), ), ); } diff --git a/veilid-flutter/example/pubspec.lock b/veilid-flutter/example/pubspec.lock index 420d3cc6..7a96f434 100644 --- a/veilid-flutter/example/pubspec.lock +++ b/veilid-flutter/example/pubspec.lock @@ -107,6 +107,20 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "1.0.1" + logger: + dependency: "direct main" + description: + name: logger + url: "https://pub.dartlang.org" + source: hosted + version: "1.1.0" + logger_flutter_viewer: + dependency: "direct main" + description: + name: logger_flutter_viewer + url: "https://pub.dartlang.org" + source: hosted + version: "0.8.0" matcher: dependency: transitive description: @@ -135,6 +149,34 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "1.8.0" + plugin_platform_interface: + dependency: transitive + description: + name: plugin_platform_interface + url: "https://pub.dartlang.org" + source: hosted + version: "2.1.2" + sensors_plus: + dependency: transitive + description: + name: sensors_plus + url: "https://pub.dartlang.org" + source: hosted + version: "1.2.1" + sensors_plus_platform_interface: + dependency: transitive + description: + name: sensors_plus_platform_interface + url: "https://pub.dartlang.org" + source: hosted + version: "1.1.0" + sensors_plus_web: + dependency: transitive + description: + name: sensors_plus_web + url: "https://pub.dartlang.org" + source: hosted + version: "1.1.0" sky_engine: dependency: transitive description: flutter diff --git a/veilid-flutter/example/pubspec.yaml b/veilid-flutter/example/pubspec.yaml index ea8fb3ab..b55968f0 100644 --- a/veilid-flutter/example/pubspec.yaml +++ b/veilid-flutter/example/pubspec.yaml @@ -33,6 +33,8 @@ dependencies: # The following adds the Cupertino Icons font to your application. # Use with the CupertinoIcons class for iOS style icons. cupertino_icons: ^1.0.2 + logger: ^1.1.0 + logger_flutter_viewer: ^0.8.0 dev_dependencies: flutter_test: diff --git a/veilid-flutter/rust/src/dart_ffi.rs b/veilid-flutter/rust/src/dart_ffi.rs index b1e21b26..f4fa3412 100644 --- a/veilid-flutter/rust/src/dart_ffi.rs +++ b/veilid-flutter/rust/src/dart_ffi.rs @@ -119,7 +119,14 @@ pub extern "C" fn startup_veilid_core(port: i64, config: FfiStr) { move |update: veilid_core::VeilidUpdate| -> veilid_core::SystemPinBoxFuture<()> { let sink = sink.clone(); Box::pin(async move { - sink.item_json(update); + match update { + veilid_core::VeilidUpdate::Shutdown => { + sink.close(); + } + _ => { + sink.item_json(update); + } + } }) }, ); @@ -159,6 +166,16 @@ pub extern "C" fn shutdown_veilid_core(port: i64) { }); } +#[no_mangle] +pub extern "C" fn debug(port: i64, command: FfiStr) { + let command = command.into_opt_string().unwrap_or_default(); + DartIsolateWrapper::new(port).spawn_result(async move { + let veilid_api = get_veilid_api().await?; + let out = veilid_api.debug(command).await?; + APIResult::Ok(out) + }); +} + #[no_mangle] pub extern "C" fn veilid_version_string() -> *mut c_char { veilid_core::veilid_version_string().into_ffi_value() diff --git a/veilid-flutter/rust/src/dart_isolate_wrapper.rs b/veilid-flutter/rust/src/dart_isolate_wrapper.rs index 365b9b5c..3d3c1ec5 100644 --- a/veilid-flutter/rust/src/dart_isolate_wrapper.rs +++ b/veilid-flutter/rust/src/dart_isolate_wrapper.rs @@ -13,12 +13,12 @@ pub struct DartIsolateWrapper { } const MESSAGE_OK: i32 = 0; -const MESSAGE_ERR: i32 = 1; +//const MESSAGE_ERR: i32 = 1; const MESSAGE_OK_JSON: i32 = 2; const MESSAGE_ERR_JSON: i32 = 3; -const MESSAGE_STREAM_ITEM: i32 = 4; +//const MESSAGE_STREAM_ITEM: i32 = 4; const MESSAGE_STREAM_ITEM_JSON: i32 = 5; -const MESSAGE_STREAM_ABORT: i32 = 6; +//const MESSAGE_STREAM_ABORT: i32 = 6; const MESSAGE_STREAM_ABORT_JSON: i32 = 7; const MESSAGE_STREAM_CLOSE: i32 = 8; @@ -29,6 +29,17 @@ impl DartIsolateWrapper { } } + pub fn spawn_result(self, future: F) + where + F: Future> + Send + 'static, + T: IntoDart, + E: Serialize, + { + async_std::task::spawn(async move { + self.result(future.await); + }); + } + pub fn spawn_result_json(self, future: F) where F: Future> + Send + 'static, @@ -40,10 +51,10 @@ impl DartIsolateWrapper { }); } - pub fn result(&self, result: Result) -> bool { + pub fn result(&self, result: Result) -> bool { match result { Ok(v) => self.ok(v), - Err(e) => self.err(e), + Err(e) => self.err_json(e), } } pub fn result_json(&self, result: Result) -> bool { @@ -64,10 +75,10 @@ impl DartIsolateWrapper { ]) } - pub fn err(&self, error: E) -> bool { - self.isolate - .post(vec![MESSAGE_ERR.into_dart(), error.into_dart()]) - } + // pub fn err(&self, error: E) -> bool { + // self.isolate + // .post(vec![MESSAGE_ERR.into_dart(), error.into_dart()]) + // } pub fn err_json(&self, error: E) -> bool { self.isolate.post(vec![ @@ -89,14 +100,14 @@ impl DartIsolateStream { } } - pub fn item(&self, value: T) -> bool { - let isolate = self.isolate.lock(); - if let Some(isolate) = &*isolate { - isolate.post(vec![MESSAGE_STREAM_ITEM.into_dart(), value.into_dart()]) - } else { - false - } - } + // pub fn item(&self, value: T) -> bool { + // let isolate = self.isolate.lock(); + // if let Some(isolate) = &*isolate { + // isolate.post(vec![MESSAGE_STREAM_ITEM.into_dart(), value.into_dart()]) + // } else { + // false + // } + // } pub fn item_json(&self, value: T) -> bool { let isolate = self.isolate.lock(); @@ -110,14 +121,14 @@ impl DartIsolateStream { } } - pub fn abort(self, error: E) -> bool { - let mut isolate = self.isolate.lock(); - if let Some(isolate) = isolate.take() { - isolate.post(vec![MESSAGE_STREAM_ABORT.into_dart(), error.into_dart()]) - } else { - false - } - } + // pub fn abort(self, error: E) -> bool { + // let mut isolate = self.isolate.lock(); + // if let Some(isolate) = isolate.take() { + // isolate.post(vec![MESSAGE_STREAM_ABORT.into_dart(), error.into_dart()]) + // } else { + // false + // } + // } pub fn abort_json(self, error: E) -> bool { let mut isolate = self.isolate.lock(); diff --git a/veilid-server/proto/veilid-client.capnp b/veilid-server/proto/veilid-client.capnp index a8a1b93f..2e38175e 100644 --- a/veilid-server/proto/veilid-client.capnp +++ b/veilid-server/proto/veilid-client.capnp @@ -18,7 +18,7 @@ struct Attachment { struct VeilidUpdate { union { attachment @0 :Attachment; - dummy @1 :Void; + shutdown @1 :Void; } } diff --git a/veilid-server/src/client_api.rs b/veilid-server/src/client_api.rs index 3c7cf607..364ee24a 100644 --- a/veilid-server/src/client_api.rs +++ b/veilid-server/src/client_api.rs @@ -33,7 +33,7 @@ fn convert_attachment_state(state: &veilid_core::AttachmentState) -> AttachmentS fn convert_update( update: &veilid_core::VeilidUpdate, - rpc_update: crate::veilid_client_capnp::veilid_update::Builder, + mut rpc_update: crate::veilid_client_capnp::veilid_update::Builder, ) { match update { veilid_core::VeilidUpdate::Log { @@ -46,6 +46,9 @@ fn convert_update( let mut att = rpc_update.init_attachment(); att.set_state(convert_attachment_state(state)); } + veilid_core::VeilidUpdate::Shutdown => { + rpc_update.set_shutdown(()); + } } } diff --git a/veilid-wasm/src/js_veilid_core.rs b/veilid-wasm/src/js_veilid_core.rs index 53475710..e4eb7922 100644 --- a/veilid-wasm/src/js_veilid_core.rs +++ b/veilid-wasm/src/js_veilid_core.rs @@ -275,12 +275,4 @@ impl JsVeilidCore { }) } - pub fn wait_for_state(&self, state: JsVeilidState) -> Promise { - let core = self.core.clone(); - future_to_promise(async move { - let state = Self::translate_veilid_state(state)?; - core.wait_for_state(state).await; - Ok(JsValue::UNDEFINED) - }) - } }