Skip to content

Commit

Permalink
Do nothing if Action.StartDaemon being executed while already start…
Browse files Browse the repository at this point in the history
…ed (#387)
  • Loading branch information
05nelsonm authored May 21, 2024
1 parent 2f268d9 commit 25d4f06
Show file tree
Hide file tree
Showing 7 changed files with 67 additions and 36 deletions.
16 changes: 7 additions & 9 deletions library/runtime-core/api/runtime-core.api
Original file line number Diff line number Diff line change
Expand Up @@ -1170,10 +1170,10 @@ public class io/matthewnelson/kmp/tor/runtime/core/ctrl/Reply {
public synthetic fun <init> (Ljava/lang/String;Ljava/lang/String;Lkotlin/jvm/internal/DefaultConstructorMarker;)V
public final fun component1 ()Ljava/lang/String;
public final fun component2 ()Ljava/lang/String;
public fun equals (Ljava/lang/Object;)Z
public fun hashCode ()I
public final fun equals (Ljava/lang/Object;)Z
public final fun hashCode ()I
public static final fun of (Ljava/lang/String;Ljava/lang/String;)Lio/matthewnelson/kmp/tor/runtime/core/ctrl/Reply;
public fun toString ()Ljava/lang/String;
public final fun toString ()Ljava/lang/String;
}

public final class io/matthewnelson/kmp/tor/runtime/core/ctrl/Reply$Companion {
Expand All @@ -1182,14 +1182,15 @@ public final class io/matthewnelson/kmp/tor/runtime/core/ctrl/Reply$Companion {

public final class io/matthewnelson/kmp/tor/runtime/core/ctrl/Reply$Error : java/lang/RuntimeException {
public static final field Companion Lio/matthewnelson/kmp/tor/runtime/core/ctrl/Reply$Error$Companion;
public final field jobName Ljava/lang/String;
public final field replies Ljava/util/List;
public synthetic fun <init> (Ljava/util/List;Lkotlin/jvm/internal/DefaultConstructorMarker;)V
public static final fun get (Ljava/util/List;)Lio/matthewnelson/kmp/tor/runtime/core/ctrl/Reply$Error;
public synthetic fun <init> (Ljava/lang/String;Ljava/util/List;Lkotlin/jvm/internal/DefaultConstructorMarker;)V
public static final fun get (Ljava/util/List;Ljava/lang/String;)Lio/matthewnelson/kmp/tor/runtime/core/ctrl/Reply$Error;
public fun getMessage ()Ljava/lang/String;
}

public final class io/matthewnelson/kmp/tor/runtime/core/ctrl/Reply$Error$Companion {
public final fun get (Ljava/util/List;)Lio/matthewnelson/kmp/tor/runtime/core/ctrl/Reply$Error;
public final fun get (Ljava/util/List;Ljava/lang/String;)Lio/matthewnelson/kmp/tor/runtime/core/ctrl/Reply$Error;
}

public class io/matthewnelson/kmp/tor/runtime/core/ctrl/Reply$Success : io/matthewnelson/kmp/tor/runtime/core/ctrl/Reply {
Expand All @@ -1199,9 +1200,6 @@ public class io/matthewnelson/kmp/tor/runtime/core/ctrl/Reply$Success : io/matth

public final class io/matthewnelson/kmp/tor/runtime/core/ctrl/Reply$Success$OK : io/matthewnelson/kmp/tor/runtime/core/ctrl/Reply$Success {
public static final field INSTANCE Lio/matthewnelson/kmp/tor/runtime/core/ctrl/Reply$Success$OK;
public fun equals (Ljava/lang/Object;)Z
public fun hashCode ()I
public fun toString ()Ljava/lang/String;
}

public abstract class io/matthewnelson/kmp/tor/runtime/core/ctrl/TorCmd {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,8 @@ import kotlin.jvm.JvmSynthetic
* @see [io.matthewnelson.kmp.tor.runtime.RuntimeEvent.ERROR]
* */
public class UncaughtException private constructor(
override val message: String,
override val cause: Throwable,
public override val message: String,
public override val cause: Throwable,
): Exception(message, cause) {

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -112,42 +112,55 @@ public open class Reply private constructor(
*
* @see [toError]
* */
public class Error private constructor(replies: List<Reply>): RuntimeException() {
public class Error private constructor(
@JvmField
public val jobName: String,
replies: List<Reply>
): RuntimeException() {

@JvmField
public val replies: List<Reply> = replies.toImmutableList()

override val message: String by lazy { _message }
public override val message: String = buildString {
append("jobName: ")
append(jobName)
appendLine()

append("replies: [")
for (reply in this@Error.replies) {
appendLine()
append(" ")
append(reply)
}

@Suppress("NOTHING_TO_INLINE", "KotlinRedundantDiagnosticSuppress")
private inline val _message: String get() = buildString {
replies.joinTo(this, separator = "\n")
appendLine()
append(']')
}

public companion object {

@JvmStatic
@JvmName("get")
@Throws(IllegalArgumentException::class)
public fun List<Reply>.toError(): Error {
public fun List<Reply>.toError(jobName: String): Error {
require(isNotEmpty()) { "replies cannot be empty" }
return Error(this)
return Error(jobName, this)
}
}
}

override fun equals(other: Any?): Boolean {
public final override fun equals(other: Any?): Boolean {
return other is Reply
&& other.status == status
&& other.message == message
}

override fun hashCode(): Int {
public final override fun hashCode(): Int {
var result = 17
result = result * 31 + status.hashCode()
result = result * 31 + message.hashCode()
return result
}

override fun toString(): String = "$status $message"
public final override fun toString(): String = "$status $message"
}
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ internal fun TorCmdJob<*>.respond(replies: ArrayList<Reply>) {
}

if (success == null) {
error(replies.toError())
error(replies.toError(name))
return
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -63,12 +63,7 @@ class ProcessorUnitTest {
var threw: Throwable? = null
var invocationSuccess = 0
try {
val ctrl = try {
factory.connectAsync(address)
} catch (_: Throwable) {
withContext(Dispatchers.Default) { delay(350.milliseconds) }
factory.connectAsync(address)
}
val ctrl = factory.connectAsync(address)

val onFailure = OnFailure { threw = it }
val onSuccess = OnSuccess<Reply.Success.OK> { synchronized(lock) { invocationSuccess++ } }
Expand All @@ -78,6 +73,12 @@ class ProcessorUnitTest {
ctrl.enqueue(TorCmd.Signal.Heartbeat, onFailure, onSuccess)
ctrl.enqueue(TorCmd.Signal.Heartbeat, onFailure, onSuccess)
ctrl.enqueue(TorCmd.Signal.Heartbeat, onFailure, onSuccess)
ctrl.enqueue(TorCmd.Signal.Heartbeat, onFailure, onSuccess)
ctrl.enqueue(TorCmd.Signal.Heartbeat, onFailure, onSuccess)
ctrl.enqueue(TorCmd.Signal.Heartbeat, onFailure, onSuccess)
ctrl.enqueue(TorCmd.Signal.Heartbeat, onFailure, onSuccess)
ctrl.enqueue(TorCmd.Signal.Heartbeat, onFailure, onSuccess)
ctrl.enqueue(TorCmd.Signal.Heartbeat, onFailure, onSuccess)

// Suspends test until non-suspending complete
ctrl.executeAsync(TorCmd.Signal.Dump)
Expand All @@ -97,22 +98,19 @@ class ProcessorUnitTest {
threw?.let { throw it }

// All commands for our test executed successfully
assertEquals(7, invocationSuccess)
assertEquals(3, invocationIntercept)
assertEquals(13, invocationSuccess)
assertEquals(9, invocationIntercept)

// Ensure that given our flurry of commands, a single processor
// coroutine was started to handle them all.
synchronized(lock) {
val processorStarts = debugLogs.mapNotNull {
// println(it)
if (it.contains("Processor Started")) it else null
}
val processorStarts = debugLogs.count { it.contains("Processor Started") }

// Simply need to know if the processor handled multiple
// commands when they were available, and other startProcessor
// calls were ignored (b/c was already looping). Cannot utilize
// a hard number because test will be flaky.
assertTrue(processorStarts.size < invocationSuccess)
assertTrue(processorStarts < invocationSuccess)
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -508,9 +508,19 @@ internal class RealTorRuntime private constructor(
ensureActive()

val cmdQueue = _cmdQueue

// Should never be the case, but...
check(cmdQueue != null) { "cmdQueue cannot be null" }
cmdQueue.checkIsNotDestroyed()
check(cmdQueue.connection == null) { "cmdQueue already has a connection attach" }

cmdQueue.connection?.let { ctrl ->
// Should never be the case, but...
ctrl.checkIsNotDestroyed()

// Already started
NOTIFIER.d(this@ActionProcessor, "TorCtrl connection present. Already started.")
return
}

TorProcess.start(generator, NOTIFIER, scope, connect = {
val ctrl = connection.openWith(factory)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -256,13 +256,25 @@ class ServiceFactoryUnitTest {
lces.clear()
}

// Should already be started and do nothing
factory.startDaemonAsync()
withContext(Dispatchers.Default) { delay(50.milliseconds) }

synchronized(lock) { assertTrue(lces.isEmpty()) }

factory.restartDaemonAsync()
withContext(Dispatchers.Default) { delay(50.milliseconds) }

synchronized(lock) {
// Old process stopped
lces.assertContains("TorProcess", Lifecycle.Event.Name.OnDestroy, fid = factory)
lces.assertContains("RealTorCtrl", Lifecycle.Event.Name.OnDestroy, fid = factory)

// New process started
lces.assertContains("TorProcess", Lifecycle.Event.Name.OnCreate, fid = factory)
lces.assertContains("TorProcess", Lifecycle.Event.Name.OnStart, fid = factory)
lces.assertContains("RealTorCtrl", Lifecycle.Event.Name.OnCreate, fid = factory)

lces.assertDoesNotContain("RealTorRuntime", Lifecycle.Event.Name.OnDestroy, fid = factory)
lces.assertDoesNotContain("DestroyableTorRuntime", Lifecycle.Event.Name.OnDestroy, fid = factory)
lces.clear()
Expand Down

0 comments on commit 25d4f06

Please sign in to comment.