session_stop and session_headless_stop with force_close

master
Niko PLP 1 month ago
parent 7860a17d7f
commit 273a13b4e5
  1. 48
      nextgraph/src/local_broker.rs
  2. 33
      ng-broker/src/server_broker.rs
  3. 4
      ng-net/src/actors/app/request.rs
  4. 33
      ng-net/src/actors/app/session.rs
  5. 14
      ng-net/src/app_protocol.rs
  6. 7
      ng-net/src/server_broker.rs
  7. 1
      ng-repo/src/errors.rs
  8. 3
      ng-sdk-js/app-node/index.js
  9. 13
      ng-sdk-js/src/lib.rs
  10. 1
      ng-verifier/src/verifier.rs

@ -625,10 +625,11 @@ impl LocalBroker {
Ok(())
}
pub(crate) async fn send_request_headless(&self, req: ProtocolMessage) -> Result<AppResponse, NgError> {
pub(crate) async fn send_request_headless<A: Into<ProtocolMessage> + std::fmt::Debug + Sync + Send + 'static,
B: TryFrom<ProtocolMessage, Error = ProtocolError> + std::fmt::Debug + Sync + Send + 'static,>(&self, req: A) -> Result<B, NgError> {
self.err_if_not_headless()?;
match BROKER.read().await.request::<ProtocolMessage, AppResponse>(&None, &Some(self.config.headless_config().server_peer_id), req).await {
match BROKER.read().await.request::<A, B>(&None, &Some(self.config.headless_config().server_peer_id), req).await {
Err(e) => Err(e),
Ok(SoS::Stream(_)) => Err(NgError::InvalidResponse),
Ok(SoS::Single(res)) => Ok(res),
@ -636,10 +637,11 @@ impl LocalBroker {
}
#[allow(dead_code)]
pub(crate) async fn send_request_stream_headless(&self, req: AppRequest) -> Result<(Receiver<AppResponse>, CancelFn), NgError> {
pub(crate) async fn send_request_stream_headless<A: Into<ProtocolMessage> + std::fmt::Debug + Sync + Send + 'static,
B: TryFrom<ProtocolMessage, Error = ProtocolError> + std::fmt::Debug + Sync + Send + 'static,>(&self, req: A) -> Result<(Receiver<B>, CancelFn), NgError> {
self.err_if_not_headless()?;
match BROKER.read().await.request::<AppRequest, AppResponse>(&None, &Some(self.config.headless_config().server_peer_id), req).await {
match BROKER.read().await.request::<A, B>(&None, &Some(self.config.headless_config().server_peer_id), req).await {
Err(e) => Err(e),
Ok(SoS::Single(_)) => Err(NgError::InvalidResponse),
Ok(SoS::Stream(stream)) => {
@ -1641,7 +1643,7 @@ pub async fn session_start(config: SessionConfig) -> Result<SessionInfo, NgError
detach: true
});
let res = broker.send_request_headless(request.into()).await;
let res = broker.send_request_headless(request).await;
if res.is_err() {
let _ = broker.remove_headless_session(&session_info.user);
@ -1919,9 +1921,10 @@ pub async fn session_stop(user_id: &UserId) -> Result<(), NgError> {
let request = AppSessionStop::V0(AppSessionStopV0{
session_id,
force_close: false,
});
let _res = broker.send_request_headless(request.into()).await;
let _res = broker.send_request_headless(request).await?;
}
_ => {
// TODO implement for Remote
@ -1940,6 +1943,39 @@ pub async fn session_stop(user_id: &UserId) -> Result<(), NgError> {
Ok(())
}
/// Stops the session, that can be resumed later on. All the local data is flushed from RAM.
#[doc(hidden)]
pub async fn session_headless_stop(session_id: u64, force_close: bool) -> Result<(), NgError> {
let mut broker = match LOCAL_BROKER.get() {
None | Some(Err(_)) => return Err(NgError::LocalBrokerNotInitialized),
Some(Ok(broker)) => broker.write().await,
};
match broker.config {
LocalBrokerConfig::Headless(_) => {
let session = broker
.headless_sessions
.remove(&session_id)
.ok_or(NgError::SessionNotFound)?;
let _ = broker.opened_sessions.remove(&session.user_id).ok_or(NgError::SessionNotFound)?;
let request = AppSessionStop::V0(AppSessionStopV0{
session_id,
force_close,
});
let _res = broker.send_request_headless(request).await?;
}
_ => {
return Err(NgError::LocalBrokerIsNotHeadless);
}
}
Ok(())
}
/// Disconnects the user from the Server Broker(s), but keep all the local data opened and ready.
pub async fn user_disconnect(user_id: &UserId) -> Result<(), NgError> {
let mut broker = match LOCAL_BROKER.get() {

@ -574,8 +574,37 @@ impl IServerBroker for ServerBroker {
Ok(res)
}
fn app_session_stop(&self, _req: AppSessionStop) -> Result<EmptyAppResponse, ServerError> {
//TODO
async fn app_session_stop(
&self,
req: AppSessionStop,
remote_peer_id: &DirectPeerId,
) -> Result<EmptyAppResponse, ServerError> {
let id = (*remote_peer_id, req.session_id());
let mut write_lock = self.state.write().await;
let must_be_destroyed = {
let session_user = write_lock
.remote_apps
.remove(&id)
.ok_or(ServerError::SessionNotFound)?;
let session = Arc::clone(
write_lock
.verifiers
.get(&session_user)
.ok_or(ServerError::SessionNotFound)?,
);
let mut verifier_lock = session.write().await;
if !req.is_force_close() && verifier_lock.detach {
verifier_lock.attached = None;
None
} else {
Some(session_user)
}
};
if let Some(user) = must_be_destroyed {
let verifier = write_lock.verifiers.remove(&user);
verifier.unwrap().read().await.verifier.close().await;
}
Ok(EmptyAppResponse(()))
}

@ -63,7 +63,7 @@ impl TryFrom<ProtocolMessage> for AppResponse {
if let AppMessageContentV0::Response(res) = msg.try_into()? {
Ok(res)
} else {
log_debug!("INVALID AppMessageContentV0::Response");
log_info!("INVALID AppMessageContentV0::Response");
Err(ProtocolError::InvalidValue)
}
}
@ -83,7 +83,7 @@ impl TryFrom<ProtocolMessage> for AppMessageContentV0 {
Err(ProtocolError::ServerError)
}
} else {
log_debug!("INVALID AppMessageContentV0");
log_info!("INVALID AppMessageContentV0 {:?}", msg);
Err(ProtocolError::InvalidValue)
}
}

@ -116,7 +116,7 @@ impl EActor for Actor<'_, AppSessionStart, AppSessionStartResponse> {
impl AppSessionStop {
pub fn get_actor(&self, id: i64) -> Box<dyn EActor> {
Actor::<AppSessionStop, ()>::new_responder(id)
Actor::<AppSessionStop, EmptyAppResponse>::new_responder(id)
}
}
@ -132,6 +132,19 @@ impl TryFrom<ProtocolMessage> for AppSessionStop {
}
}
impl TryFrom<ProtocolMessage> for EmptyAppResponse {
type Error = ProtocolError;
fn try_from(msg: ProtocolMessage) -> Result<Self, Self::Error> {
let res: Result<AppMessageContentV0, ProtocolError> = msg.try_into();
if let AppMessageContentV0::EmptyResponse = res? {
Ok(EmptyAppResponse(()))
} else {
log_debug!("INVALID AppMessageContentV0::EmptyResponse");
Err(ProtocolError::InvalidValue)
}
}
}
impl From<AppSessionStop> for ProtocolMessage {
fn from(request: AppSessionStop) -> ProtocolMessage {
AppMessageContentV0::SessionStop(request).into()
@ -152,10 +165,10 @@ impl From<Result<EmptyAppResponse, ServerError>> for ProtocolMessage {
}
}
impl Actor<'_, AppSessionStop, ()> {}
impl Actor<'_, AppSessionStop, EmptyAppResponse> {}
#[async_trait::async_trait]
impl EActor for Actor<'_, AppSessionStop, ()> {
impl EActor for Actor<'_, AppSessionStop, EmptyAppResponse> {
async fn respond(
&mut self,
msg: ProtocolMessage,
@ -163,10 +176,18 @@ impl EActor for Actor<'_, AppSessionStop, ()> {
) -> Result<(), ProtocolError> {
let req = AppSessionStop::try_from(msg)?;
let res = {
let sb = { BROKER.read().await.get_server_broker()? };
let lock = sb.read().await;
lock.app_session_stop(req)
let lock = fsm.lock().await;
let remote = lock.remote_peer();
if remote.is_none() {
Err(ServerError::BrokerError)
} else {
let sb = { BROKER.read().await.get_server_broker()? };
let lock = sb.read().await;
lock.app_session_stop(req, remote.as_ref().unwrap()).await
}
};
fsm.lock()
.await
.send_in_reply_to(res.into(), self.id())

@ -189,13 +189,25 @@ impl AppRequest {
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct AppSessionStopV0 {
pub session_id: u64,
pub force_close: bool,
}
#[derive(Clone, Debug, Serialize, Deserialize)]
pub enum AppSessionStop {
V0(AppSessionStopV0),
}
impl AppSessionStop {
pub fn session_id(&self) -> u64 {
match self {
Self::V0(v0) => v0.session_id,
}
}
pub fn is_force_close(&self) -> bool {
match self {
Self::V0(v0) => v0.force_close,
}
}
}
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct AppSessionStartV0 {
pub session_id: u64,

@ -64,13 +64,18 @@ pub trait IServerBroker: Send + Sync {
request_id: i64,
fsm: &Mutex<NoiseFSM>,
) -> Result<(), ServerError>;
async fn app_session_start(
&self,
req: AppSessionStart,
remote_peer_id: DirectPeerId,
local_peer_id: DirectPeerId,
) -> Result<AppSessionStartResponse, ServerError>;
fn app_session_stop(&self, req: AppSessionStop) -> Result<EmptyAppResponse, ServerError>;
async fn app_session_stop(
&self,
req: AppSessionStop,
remote_peer_id: &DirectPeerId,
) -> Result<EmptyAppResponse, ServerError>;
fn next_seq_for_peer(&self, peer: &PeerId, seq: u64) -> Result<(), ServerError>;

@ -79,6 +79,7 @@ pub enum NgError {
OxiGraphError(String),
ConfigError(String),
LocalBrokerIsHeadless,
LocalBrokerIsNotHeadless,
}
impl Error for NgError {}

@ -30,6 +30,9 @@ ng.init_headless(config).then( async() => {
let session = await ng.session_headless_start(user_id);
console.log(session);
let res = await ng.session_headless_stop(session.session_id, true);
console.log(res);
} catch (e) {
console.error(e);
}

@ -187,6 +187,19 @@ pub async fn session_headless_start(user_js: String) -> Result<JsValue, String>
Ok(serde_wasm_bindgen::to_value(&res).unwrap())
}
#[cfg(wasmpack_target = "nodejs")]
#[wasm_bindgen]
pub async fn session_headless_stop(session_id: JsValue, force_close: bool) -> Result<(), String> {
let session_id: u64 = serde_wasm_bindgen::from_value::<u64>(session_id)
.map_err(|_| "Invalid session_id".to_string())?;
let _ = nextgraph::local_broker::session_headless_stop(session_id, force_close)
.await
.map_err(|e: NgError| e.to_string())?;
Ok(())
}
#[cfg(wasmpack_target = "nodejs")]
#[wasm_bindgen]
pub async fn admin_create_user(js_config: JsValue) -> Result<JsValue, String> {

@ -139,6 +139,7 @@ impl Verifier {
}
pub async fn close(&self) {
log_debug!("VERIFIER CLOSED {}", self.user_privkey().to_pub());
BROKER
.write()
.await

Loading…
Cancel
Save