Skip to content

Commit 1a3f6c5

Browse files
chore(client): refactor closing / shutdown
1 parent e9a4334 commit 1a3f6c5

File tree

4 files changed

+78
-2
lines changed

4 files changed

+78
-2
lines changed

onebusaway-sdk-java-core/src/main/kotlin/org/onebusaway/client/OnebusawaySdkClientAsyncImpl.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -251,7 +251,7 @@ class OnebusawaySdkClientAsyncImpl(private val clientOptions: ClientOptions) :
251251

252252
override fun shape(): ShapeServiceAsync = shape
253253

254-
override fun close() = clientOptions.httpClient.close()
254+
override fun close() = clientOptions.close()
255255

256256
class WithRawResponseImpl internal constructor(private val clientOptions: ClientOptions) :
257257
OnebusawaySdkClientAsync.WithRawResponse {

onebusaway-sdk-java-core/src/main/kotlin/org/onebusaway/client/OnebusawaySdkClientImpl.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -242,7 +242,7 @@ class OnebusawaySdkClientImpl(private val clientOptions: ClientOptions) : Onebus
242242

243243
override fun shape(): ShapeService = shape
244244

245-
override fun close() = clientOptions.httpClient.close()
245+
override fun close() = clientOptions.close()
246246

247247
class WithRawResponseImpl internal constructor(private val clientOptions: ClientOptions) :
248248
OnebusawaySdkClient.WithRawResponse {

onebusaway-sdk-java-core/src/main/kotlin/org/onebusaway/core/ClientOptions.kt

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@ private constructor(
2121
* The HTTP client to use in the SDK.
2222
*
2323
* Use the one published in `onebusaway-sdk-java-client-okhttp` or implement your own.
24+
*
25+
* This class takes ownership of the client and closes it when closed.
2426
*/
2527
@get:JvmName("httpClient") val httpClient: HttpClient,
2628
/**
@@ -156,6 +158,8 @@ private constructor(
156158
* The HTTP client to use in the SDK.
157159
*
158160
* Use the one published in `onebusaway-sdk-java-client-okhttp` or implement your own.
161+
*
162+
* This class takes ownership of the client and closes it when closed.
159163
*/
160164
fun httpClient(httpClient: HttpClient) = apply {
161165
this.httpClient = PhantomReachableClosingHttpClient(httpClient)
@@ -402,4 +406,18 @@ private constructor(
402406
)
403407
}
404408
}
409+
410+
/**
411+
* Closes these client options, relinquishing any underlying resources.
412+
*
413+
* This is purposefully not inherited from [AutoCloseable] because the client options are
414+
* long-lived and usually should not be synchronously closed via try-with-resources.
415+
*
416+
* It's also usually not necessary to call this method at all. the default client automatically
417+
* releases threads and connections if they remain idle, but if you are writing an application
418+
* that needs to aggressively release unused resources, then you may call this method.
419+
*/
420+
fun close() {
421+
httpClient.close()
422+
}
405423
}
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
package org.onebusaway.core
2+
3+
import java.util.concurrent.Callable
4+
import java.util.concurrent.ExecutorService
5+
import java.util.concurrent.Future
6+
import java.util.concurrent.TimeUnit
7+
8+
/**
9+
* A delegating wrapper around an [ExecutorService] that shuts it down once it's only phantom
10+
* reachable.
11+
*
12+
* This class ensures the [ExecutorService] is shut down even if the user forgets to do it.
13+
*/
14+
internal class PhantomReachableExecutorService(private val executorService: ExecutorService) :
15+
ExecutorService {
16+
init {
17+
closeWhenPhantomReachable(this) { executorService.shutdown() }
18+
}
19+
20+
override fun execute(command: Runnable) = executorService.execute(command)
21+
22+
override fun shutdown() = executorService.shutdown()
23+
24+
override fun shutdownNow(): MutableList<Runnable> = executorService.shutdownNow()
25+
26+
override fun isShutdown(): Boolean = executorService.isShutdown
27+
28+
override fun isTerminated(): Boolean = executorService.isTerminated
29+
30+
override fun awaitTermination(timeout: Long, unit: TimeUnit): Boolean =
31+
executorService.awaitTermination(timeout, unit)
32+
33+
override fun <T : Any?> submit(task: Callable<T>): Future<T> = executorService.submit(task)
34+
35+
override fun <T : Any?> submit(task: Runnable, result: T): Future<T> =
36+
executorService.submit(task, result)
37+
38+
override fun submit(task: Runnable): Future<*> = executorService.submit(task)
39+
40+
override fun <T : Any?> invokeAll(
41+
tasks: MutableCollection<out Callable<T>>
42+
): MutableList<Future<T>> = executorService.invokeAll(tasks)
43+
44+
override fun <T : Any?> invokeAll(
45+
tasks: MutableCollection<out Callable<T>>,
46+
timeout: Long,
47+
unit: TimeUnit,
48+
): MutableList<Future<T>> = executorService.invokeAll(tasks, timeout, unit)
49+
50+
override fun <T : Any?> invokeAny(tasks: MutableCollection<out Callable<T>>): T =
51+
executorService.invokeAny(tasks)
52+
53+
override fun <T : Any?> invokeAny(
54+
tasks: MutableCollection<out Callable<T>>,
55+
timeout: Long,
56+
unit: TimeUnit,
57+
): T = executorService.invokeAny(tasks, timeout, unit)
58+
}

0 commit comments

Comments
 (0)