From 55491dff1cf44ff9c651bd0c387c0de43bebbc6f Mon Sep 17 00:00:00 2001 From: Matteo Castellucci Date: Sat, 29 Jul 2023 17:04:06 +0200 Subject: [PATCH] fix: fix client default behavior to stop actor system and shutdown program on close --- .../tuples/space/client/JsonTupleSpace.scala | 14 +++++++++++--- .../tuples/space/client/request/Request.scala | 17 +++++++++-------- .../tuples/space/client/response/Response.scala | 14 +++++++------- 3 files changed, 27 insertions(+), 18 deletions(-) diff --git a/src/main/scala/tuples/space/client/JsonTupleSpace.scala b/src/main/scala/tuples/space/client/JsonTupleSpace.scala index 1465032..a2e7783 100644 --- a/src/main/scala/tuples/space/client/JsonTupleSpace.scala +++ b/src/main/scala/tuples/space/client/JsonTupleSpace.scala @@ -244,6 +244,7 @@ object JsonTupleSpace { private class JsonTupleSpaceImpl( uri: String, bufferSize: Int, + exitOnClose: Boolean, completionPromise: Promise[Unit] )( using @@ -440,7 +441,7 @@ object JsonTupleSpace { override def close(): Future[Unit] = { queue.complete() - flowCompletion.map(_ => ()) + flowCompletion.flatMap(_ => if (exitOnClose) system.terminate().map(_ => ()) else Future.successful(())) } } @@ -462,11 +463,18 @@ object JsonTupleSpace { * a [[Future]] which its completion signals the established connection to the server */ @SuppressWarnings(Array("org.wartremover.warts.DefaultArguments", "scalafix:DisableSyntax.defaultArgs")) - def apply(uri: String, bufferSize: Int = 1)(using system: ActorSystem = ActorSystem()): Future[JsonTupleSpace] = { + def apply( + uri: String, + bufferSize: Int = 1, + exitOnClose: Boolean = true + )( + using + system: ActorSystem = ActorSystem() + ): Future[JsonTupleSpace] = { import system.dispatcher val completionPromise: Promise[Unit] = Promise[Unit]() - val tupleSpace = JsonTupleSpaceImpl(uri, bufferSize, completionPromise) + val tupleSpace = JsonTupleSpaceImpl(uri, bufferSize, exitOnClose, completionPromise) completionPromise.future.map(_ => tupleSpace) } } diff --git a/src/main/scala/tuples/space/client/request/Request.scala b/src/main/scala/tuples/space/client/request/Request.scala index 3b977ea..fddb9f3 100644 --- a/src/main/scala/tuples/space/client/request/Request.scala +++ b/src/main/scala/tuples/space/client/request/Request.scala @@ -130,16 +130,17 @@ private[client] object Request { def apply(content: JsonTemplate, tpe: TemplateRequestType): TemplateRequest = TemplateRequestImpl(content, tpe) } - /** A [[Request]] to be sent to the server for re-assigning to itself its old client id. + /** A [[Request]] to be sent to the server for re-assigning to the client sending it its old client id. * * When the connection to the server goes down, after the client reconnects, the server has no knowledge of whether this client - * has already connected to it before or not. This is on purpose: it is always allowed for a client to purposefully connect to - * the server, disconnect and then reconnect again at a later point in time. All pending operations from the client are lost, - * because even if the client will reconnect, it would not be the same client from the server point of view. If the - * disconnection happens abruptly followed by an error, the server can keep the pending operations, but it will never know if - * the client will reappear or not. This [[Request]] is needed to do just that, to tell the server that a client previously - * connected has now reconnected and its old id was the one given. This way, it can regain access to the - * [[io.github.cakelier.tuples.space.response.Response]]s associated to the [[Request]]s placed before the disconnection. + * has already connected to it before or not. This is on purpose: it is always allowed for a program using a client to + * purposefully connect to the server, disconnect and then reconnect again with another client at a later point in time. All + * pending operations from the original client are lost, because it would not be the same client. If the disconnection happens + * abruptly followed by an error, the server keeps the pending operations, but it will never know if the client will reappear + * or not. This [[Request]] is needed to do just that, to tell the server that a client previously connected has now + * reconnected and its old id was the one given. This way, it can regain access to the + * [[io.github.cakelier.tuples.space.response.Response]]s associated to the [[Request]]s placed before the disconnection, if + * they where not satisfied during its absence. */ sealed trait MergeRequest extends Request { diff --git a/src/main/scala/tuples/space/client/response/Response.scala b/src/main/scala/tuples/space/client/response/Response.scala index 65e9b83..a24213d 100644 --- a/src/main/scala/tuples/space/client/response/Response.scala +++ b/src/main/scala/tuples/space/client/response/Response.scala @@ -318,14 +318,14 @@ private[client] object Response { * [[io.github.cakelier.tuples.space.request.Request]] its old client id. * * When the connection to the server goes down, after the client reconnects, the server has no knowledge of whether this client - * has already connected to it before or not. This is on purpose: it is always allowed for a client to purposefully connect to - * the server, disconnect and then reconnect again at a later point in time. All pending operations from the client are lost, - * because even if the client will reconnect, it would not be the same client from the server point of view. If the - * disconnection happens abruptly followed by an error, the server can keep the pending operations, but it will never know if - * the client will reappear or not. This [[Response]] is sent from the server to confirm just that: the server is telling that - * a client previously connected has now reconnected and its id is now the one given in the previously sent + * has already connected to it before or not. This is on purpose: it is always allowed for a program using a client to + * purposefully connect to the server, disconnect and then reconnect again with another client at a later point in time. All + * pending operations from the original client are lost, because it would not be the same client. If the disconnection happens + * abruptly followed by an error, the server keeps the pending operations, but it will never know if the client will reappear + * or not. This [[Response]] is sent from the server to confirm just that: the server is telling that a client previously + * connected has now reconnected and its id is now the one given in the previously sent * [[io.github.cakelier.tuples.space.request.Request]]. This way, the client can regain access to the [[Response]]s associated - * to the [[Request]]s placed before the disconnection. + * to the [[Request]]s placed before the disconnection, if they where not satisfied during its absence. */ sealed trait MergeSuccessResponse extends Response {