@@ -13,6 +13,7 @@ class GostProcessManager(
1313 context : Context ,
1414 private val logStore : LogStore ,
1515 private val statusStore : StatusStore ,
16+ private val onStatusChanged : () -> Unit = {},
1617) {
1718 private val appContext = context.applicationContext
1819 private val installer = GostBinaryInstaller (appContext, logStore)
@@ -37,7 +38,7 @@ class GostProcessManager(
3738 return
3839 }
3940 desiredRunning = true
40- statusStore.update {
41+ updateStatus {
4142 it.copy(
4243 desiredRunning = true ,
4344 bindAddress = config.bindAddress,
@@ -69,7 +70,7 @@ class GostProcessManager(
6970 val stopped = stopCurrentProcess(reason)
7071 val current = process
7172 val currentPid = ProcessUtil .pidOf(current)
72- statusStore.update {
73+ updateStatus {
7374 it.copy(
7475 desiredRunning = false ,
7576 proxyRunning = ! stopped && current?.isAlive == true ,
@@ -90,7 +91,7 @@ class GostProcessManager(
9091 return
9192 }
9293 desiredRunning = true
93- statusStore.update {
94+ updateStatus {
9495 it.copy(
9596 desiredRunning = true ,
9697 startOnBoot = config.startOnBoot,
@@ -116,7 +117,7 @@ class GostProcessManager(
116117 fun markProcessCheck () {
117118 val current = process
118119 val running = current?.isAlive == true
119- statusStore.update { it.copy(proxyRunning = running, proxyPid = ProcessUtil .pidOf(current)) }
120+ updateStatus { it.copy(proxyRunning = running, proxyPid = ProcessUtil .pidOf(current)) }
120121 if (desiredRunning && ! running) {
121122 scheduleRestart(" process_watchdog" , immediate = false )
122123 }
@@ -129,7 +130,7 @@ class GostProcessManager(
129130 if (current.isAlive) {
130131 val pid = ProcessUtil .pidOf(current)
131132 logStore.append(" app" , " gost start deferred reason=$reason current_pid=$pid " )
132- statusStore.update {
133+ updateStatus {
133134 it.copy(proxyRunning = true , proxyPid = pid, lastError = " gost still stopping:$reason " )
134135 }
135136 if (desiredRunning) scheduleRestart(" start_deferred:$reason " , immediate = false )
@@ -153,7 +154,7 @@ class GostProcessManager(
153154 process = started
154155 val pid = ProcessUtil .pidOf(started)
155156 logStore.append(" app" , " gost started pid=$pid reason=$reason " )
156- statusStore.update {
157+ updateStatus {
157158 it.copy(
158159 proxyRunning = true ,
159160 proxyPid = pid,
@@ -174,7 +175,7 @@ class GostProcessManager(
174175 }.getOrElse { throwable ->
175176 val message = throwable.message ? : throwable.javaClass.simpleName
176177 logStore.append(" app" , " gost start failed error=$message " )
177- statusStore.update {
178+ updateStatus {
178179 it.copy(proxyRunning = false , proxyPid = - 1 , lastError = message)
179180 }
180181 if (desiredRunning) scheduleRestart(" start_failed:$message " , immediate = false )
@@ -207,7 +208,7 @@ class GostProcessManager(
207208 logStore.append(" app" , " ignoring stale gost exit pid=$pid code=$exitCode " )
208209 return
209210 }
210- statusStore.update {
211+ updateStatus {
211212 it.copy(
212213 proxyRunning = false ,
213214 proxyPid = - 1 ,
@@ -222,7 +223,7 @@ class GostProcessManager(
222223 private fun rejectInvalidStart (error : String , reason : String ) {
223224 logStore.append(" app" , " gost start rejected reason=$reason error=$error " )
224225 stop(" invalid_config:$reason " )
225- statusStore.update {
226+ updateStatus {
226227 it.copy(
227228 desiredRunning = false ,
228229 proxyRunning = false ,
@@ -248,7 +249,7 @@ class GostProcessManager(
248249 val delay = next.delaySeconds
249250 restartDelaySeconds = next.nextDelaySeconds
250251 logStore.append(" app" , " scheduling gost restart reason=$reason delay=${delay} s" )
251- statusStore.update { it.copy(lastRestartReason = reason, lastError = reason) }
252+ updateStatus { it.copy(lastRestartReason = reason, lastError = reason) }
252253 restartFuture = supervisor.schedule({ runScheduledRestart(reason) }, delay, TimeUnit .SECONDS )
253254 }
254255
@@ -299,7 +300,7 @@ class GostProcessManager(
299300 }
300301
301302 logStore.append(" app" , " gost still alive pid=$pid reason=$reason " )
302- statusStore.update {
303+ updateStatus {
303304 it.copy(proxyRunning = true , proxyPid = pid, lastError = " gost stop timed out:$reason " )
304305 }
305306 return false
@@ -327,10 +328,17 @@ class GostProcessManager(
327328 if (remaining.isEmpty()) return true
328329 val message = " untracked gost still running pids=${remaining.joinToString(" ," )} "
329330 logStore.append(" app" , " $message reason=$reason " )
330- statusStore.update { it.copy(lastError = message) }
331+ updateStatus { it.copy(lastError = message) }
331332 return false
332333 }
333334
335+ private fun updateStatus (transform : (RuntimeStatus ) -> RuntimeStatus ): RuntimeStatus {
336+ val next = statusStore.update(transform)
337+ runCatching { onStatusChanged() }
338+ .onFailure { logStore.append(" app" , " status change callback failed error=${it.message} " ) }
339+ return next
340+ }
341+
334342 private fun runningGostPids (): List <Long > {
335343 return GOST_PROCESS_NAMES
336344 .flatMap { processName -> pidOf(processName) }
0 commit comments